Compare commits
31
Commits
master
...
c0c799c4b6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0c799c4b6 | ||
|
|
e18a416bf4 | ||
|
|
440c53acd7 | ||
|
|
722b513ee0 | ||
|
|
119d63ed1c | ||
|
|
ca656403bb | ||
|
|
8df9591c99 | ||
|
|
4474714c00 | ||
|
|
1164a72ea3 | ||
|
|
01a9ba4b0b | ||
|
|
56da0d60cf | ||
|
|
b37a0ddcc4 | ||
|
|
366615bcb9 | ||
|
|
9d4a862b7d | ||
|
|
2bcffa5131 | ||
|
|
ae2a4a0f08 | ||
|
|
6e17dedff2 | ||
|
|
fe7b5e0f02 | ||
|
|
93c3df1c95 | ||
|
|
24fb292cee | ||
|
|
4c04cd88de | ||
|
|
b14c864814 | ||
|
|
05fd748537 | ||
|
|
5ac9ed673c | ||
|
|
0c2e333bb4 | ||
|
|
7013087bcd | ||
|
|
fe96d310d6 | ||
|
|
df55203a96 | ||
|
|
046cb79b7a | ||
|
|
fa8e7d07dd | ||
|
|
9b4985b5aa |
No files matched your search
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"original": {
|
||||
"graph": "5d632279d7e25748f3bd8e7ffe954482821334bef12088aad885e6a3ef79c6ac",
|
||||
"executor": "016cdfb51387ab58d3e15a36b91e8fd69381b66962edd62214e4c54868340468",
|
||||
"header": "61ccbca3b666016a465d8a9a9049dfa5420177e66aa073fdfe927d749ad2b53b"
|
||||
},
|
||||
"patched": {
|
||||
"graph": "a9da61755df58666cfa2c6deb7f5d886760036936bc51b51b91ad4ef0ff76ecd",
|
||||
"executor": "cbb79474640192c5c853174e219deade3694231060d90163362385db2fd6fb6c",
|
||||
"header": "64bd460621aa63c3cf7e341173249a5b945091e955e2673523478b0762e89dde"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Vcore C8.5: local semantic world points for clientless AdventureBots.
|
||||
CREATE TABLE IF NOT EXISTS `vcore_clientless_world_point` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`point_key` varchar(100) NOT NULL,
|
||||
`category` varchar(64) NOT NULL,
|
||||
`map` smallint(5) unsigned NOT NULL DEFAULT 0,
|
||||
`position_x` float NOT NULL DEFAULT 0,
|
||||
`position_y` float NOT NULL DEFAULT 0,
|
||||
`position_z` float NOT NULL DEFAULT 0,
|
||||
`orientation` float NOT NULL DEFAULT 0,
|
||||
`enabled` tinyint(1) unsigned NOT NULL DEFAULT 1,
|
||||
`comment` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_vcore_clientless_world_point_key` (`point_key`),
|
||||
KEY `idx_vcore_clientless_world_point_category_map` (`category`,`map`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='Vcore AdventureBot semantic local world points';
|
||||
@@ -0,0 +1,31 @@
|
||||
-- Vcore C8.6: incremental AdventureBot travel graph.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `vcore_clientless_travel_node` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`node_key` varchar(100) NOT NULL,
|
||||
`node_type` varchar(32) NOT NULL DEFAULT 'location',
|
||||
`world_point_key` varchar(100) NOT NULL,
|
||||
`enabled` tinyint(1) unsigned NOT NULL DEFAULT 1,
|
||||
`comment` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_vcore_clientless_travel_node_key` (`node_key`),
|
||||
KEY `idx_vcore_clientless_travel_node_world_point` (`world_point_key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='Vcore AdventureBot travel graph nodes';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `vcore_clientless_travel_edge` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`from_node_key` varchar(100) NOT NULL,
|
||||
`to_node_key` varchar(100) NOT NULL,
|
||||
`edge_type` varchar(32) NOT NULL DEFAULT 'ground',
|
||||
`cost` float NOT NULL DEFAULT 1,
|
||||
`bidirectional` tinyint(1) unsigned NOT NULL DEFAULT 0,
|
||||
`enabled` tinyint(1) unsigned NOT NULL DEFAULT 1,
|
||||
`comment` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_vcore_clientless_travel_edge`
|
||||
(`from_node_key`,`to_node_key`,`edge_type`),
|
||||
KEY `idx_vcore_clientless_travel_edge_from` (`from_node_key`),
|
||||
KEY `idx_vcore_clientless_travel_edge_to` (`to_node_key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='Vcore AdventureBot travel graph edges';
|
||||
@@ -0,0 +1,14 @@
|
||||
-- Vcore C8.7: recorded geometry for bidirectional ground edges.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `vcore_clientless_travel_edge_point` (
|
||||
`edge_id` int(10) unsigned NOT NULL,
|
||||
`point_index` int(10) unsigned NOT NULL,
|
||||
`map` smallint(5) unsigned NOT NULL DEFAULT 0,
|
||||
`position_x` float NOT NULL DEFAULT 0,
|
||||
`position_y` float NOT NULL DEFAULT 0,
|
||||
`position_z` float NOT NULL DEFAULT 0,
|
||||
`orientation` float NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`edge_id`,`point_index`),
|
||||
KEY `idx_vcore_clientless_travel_edge_point_edge` (`edge_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='Recorded geometry for Vcore AdventureBot travel graph edges';
|
||||
@@ -0,0 +1,626 @@
|
||||
# Aktuell: Training, echte Gegner und Todesverhalten abgeschlossen
|
||||
|
||||
Stand 27.10.2026. Auf feature/clientless-player-core bleiben alle bisherigen
|
||||
Änderungen erhalten. Debug-Build mit -j10 erfolgreich installiert; alle 51
|
||||
Testskripte bestanden. Testserver PID 45545 läuft mit frisch geprüftem Ready
|
||||
und Port 8085. Nutzer hat den lokalen Commit aller Änderungen beauftragt; kein Push.
|
||||
|
||||
Neue AdventureCombatMgr und AdventureCombatPolicy überlagern den Adventure-
|
||||
Controller während Kampf und Tod. Tatsächlich angewandter Kreaturenschaden
|
||||
wird über eine threadsichere GUID-Queue geordnet an den Controller übergeben.
|
||||
Der erste Angreifer bleibt Fokus; weitere folgen nach dessen Tod. Abenteuer
|
||||
berücksichtigt Gegner am aktiven MMAP-Pfad, Kürschnerei nur Tiere bei bestehendem
|
||||
Profilrecht. Arthoran bleibt Bergbau/Schmied. Konservative Erstangriffsfilter:
|
||||
höchstens +2 Level, mindestens 60% HP und gegebenenfalls 30% Mana, keine Elites,
|
||||
Weltbosse oder Gegnergruppen. Andere Intents jagen nicht.
|
||||
|
||||
Migration 09 ergänzt leisure_training für 60–180 Sekunden an echten erreichbaren
|
||||
Puppen im lokalen 60-Yards-Umkreis. Bereits in Test-DB angewendet und trotz
|
||||
SQL-Ignore gezielt vorgemerkt. Ursprüngliche Intentfristen bleiben erhalten.
|
||||
Todesablauf: native Freigabe, gespeicherter Leichenzeitpunkt, MMAP-Punkte innerhalb
|
||||
39 Yards und native Aufnahmefrist. Ohne passenden Pfad nach 300 Sekunden native
|
||||
Friedhofsrückkehr und Wiederbelebung ohne Geistheiler-Mali.
|
||||
|
||||
Live erfolgreich geprüft:
|
||||
- Trainingsszene: MMAP-Anreise, native Angriffe und reguläres Ende nach 60 Sekunden.
|
||||
- Echter Bär, Entry 42336 / Spawn 300425, Stufe 58: besiegt, native Respawnzeile
|
||||
bestätigt. Tatsächlicher Gegentreffer löste den Selbstverteidigungsfokus aus.
|
||||
- Expliziter Testtod 1: Freigabe um 1793138872, kein akzeptierter Rückweg;
|
||||
volle 300 Sekunden tatsächlich abgewartet. Friedhofswiederbelebung, anschließend
|
||||
lebend gespeichert, keine Leiche oder Wiederbelebungskrankheit.
|
||||
- Expliziter Testtod 2 nahe Friedhof: tatsächlicher MMAP-Geisterlauf von 37,40
|
||||
Yards und native Leichenaufnahme. Danach HP 4340 gespeichert, keine Leiche
|
||||
oder Aura 15007. Kein natürlicher Kampftod behauptet.
|
||||
- Administrative Offline-Positionierung diente nur isolierten Tests; kein Beleg
|
||||
für Fernanreise. Mehrfachangreifer und Neustart während Geisterlauf bislang
|
||||
durch Produktionsadapter geprüft, nicht durch entsprechende Live-Abnahme.
|
||||
|
||||
Arthoran ist wieder angemeldet, ohne Fernauftrag am letzten Rücklaufpunkt:
|
||||
Karte 0, (-12187.9, -2603.74, 1.5777), Verwüstete Lande. Er reagiert auf Angreifer.
|
||||
Normales Lua-Profil bytegleich restauriert; kein temporärer Override vorhanden.
|
||||
Befehle: clientless combat train <guid> [seconds], attack <guid> <spawn-id>,
|
||||
testdeath <guid>, stop <guid>. Testdeath ist ein markierter nativer Diagnosetod
|
||||
für einen verwalteten Bot ohne zusätzlichen Haltbarkeitsverlust.
|
||||
|
||||
Belege: doc/clientless/checkpoints/2026-10-27-combat/.
|
||||
Logs: /tmp/vcore-reactive-combat-build-final.log und
|
||||
/tmp/vcore-reactive-tests-final.log. DB-Helfer: /tmp/vcore-instance-db.py,
|
||||
Modus combat_live_state. Vorherige Ausrüstung/Reparatur-WIP bleibt erhalten.
|
||||
Pfadfindungsüberarbeitung bleibt vertagt. Weitere Klassenrotationen und konkrete
|
||||
Spieler-/Bot-Interaktionsregeln sind noch auszuarbeiten.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Wiederaufnahme: Kampfausstattung und Reparaturtest
|
||||
|
||||
Stand 27.10.2026: Branch feature/clientless-player-core, bestehende Änderungen
|
||||
bewahren. Debug-Build erfolgreich, installiert; Testserver PID41714 frisch ready
|
||||
und Port8085 bestätigt. 48 Testskripte bestanden. Kein Push oder neuer Commit.
|
||||
|
||||
Arthoran26 trägt neun native Kopien von Allitester21 (Zorn und Ashkandi),
|
||||
26/26 native Waffen-Talentpunkte Baum746, stufengerechte Klassenfähigkeiten.
|
||||
Originalquelle unverändert, alte Ausrüstung in Taschen. Begrenzte Trainingsübung
|
||||
an echter Puppe314147 erfolgreich: native angenommene Fähigkeiten protokolliert.
|
||||
Phase169 ist Standard; keine Phasenänderungen. Ursprüngliches Problem war LOS.
|
||||
Volle autonome Kampf-/Todes-/Interaktionssteuerung bleibt zukünftige Umsetzung.
|
||||
Malusfreie Friedhofswiederbelebung nach5min ohne Pfad ist verbindliche Vorgabe.
|
||||
|
||||
NEU: economy_repair, Migration08 bereits Test-DB angewendet. Liveprüfung läuft:
|
||||
Arthoran ausgeloggt, nur seine neun Kopien auf halbe Haltbarkeit gesetzt,
|
||||
Position administrativ an poi_tele_954 (Handelsdistrikt), wieder angemeldet.
|
||||
Intent economy am Anker angekommen; Mikroaktion economy_repair gestartet,
|
||||
echter Händler1287/GUID1879, native MMAP-Anreise. Abschluss bestätigt: ECONOMY_REPAIR_COMPLETE; nach saveall alle neun Kopien
|
||||
wieder auf voller Haltbarkeit, Geld weiterhin0, Allitester unverändert.
|
||||
Ausgangswerte /tmp/vcore-repair-before.tsv.
|
||||
Normales Lua-Profil bytegleich restauriert, kein temporärer Override.
|
||||
|
||||
Werkzeuge /tmp/vcore-instance-db.py gear_verify (prüft auch Allitester-Hash),
|
||||
repair_test_prepare NICHT WIEDERHOLEN. Konsole saveall nach Reparaturabschluss,
|
||||
ECONOMY_REPAIR_COMPLETE in Server.log prüfen. Gegebenenfalls Szene beobachten.
|
||||
Build-/Testlogs /tmp/vcore-combat-preparation-{build,tests-final}.log.
|
||||
Migration08 wird von *.sql ignoriert, gezielt force-add für Erhalt erforderlich.
|
||||
Reparaturprüfung abgeschlossen; Arthoran darf den Wirtschaftsintent weiter ausführen.
|
||||
|
||||
---
|
||||
|
||||
# Neuer Arbeitsbereich: Kampf, Reaktionen und Interaktionen
|
||||
|
||||
Alle sieben Grundintents sind abgeschlossen und die bisherigen Änderungen
|
||||
lokal committet (e18a416bf4). Der Nutzer hat die visuelle Instanzabnahme erlassen.
|
||||
Jetzt Kampf, reaktives Verhalten, Bot-Spieler und Bot-Bot gemeinsam ausarbeiten.
|
||||
Neue Regeln/Vorprüfung in `combat-reactions.md` dauerhaft festgehalten.
|
||||
|
||||
Nutzer: Selbstverteidigung fokussiert erste tatsächlich schädigende Kreatur bis
|
||||
zu deren Tod; weitere Treffer wechseln den Fokus nicht. Erstangriffe wählen
|
||||
nächstgelegenes gültiges intentspezifisches Ziel: Abenteuer nahe Feindkreatur auf
|
||||
aktuellem Weg; Beruf/Lederjagd nahes geeignetes Tier. Stärkecheck verhindert
|
||||
leichtsinnige Angriffe auf deutlich stärkere Gegner. Exakte Grenzwerte noch offen.
|
||||
Tod: Leichenrücklauf als Geist, native Wiederbelebungsreichweite; ohne Pfad nach
|
||||
fünf Minuten Friedhofswiederbelebung. Native Handler/39-Yards-Radius vorhanden.
|
||||
Timerherkunft und weitere Randfälle als Auslegung/Vorschlag markieren.
|
||||
Arthoran bleibt mining/blacksmithing; keine stillschweigende skinning-Freigabe.
|
||||
Sammeln weiterhin performativ, neu gewünschter Kampf real.
|
||||
|
||||
PlayerAI.cpp gründlich geprüft. Viel vorhandene Klassen-/Zauberlogik, aber
|
||||
Charm-Steuerung muss entkoppelt werden. Technisch nicht ungenutzt: Unit::UpdateCharmAI
|
||||
und mehrere Bossskripte verwenden sie. Unit::DealDamage liefert UnitAI-Callbacks
|
||||
und UnitScript-OnDamage VOR endgültigem HP-Abzug: tatsächlichen Erstschaden
|
||||
sauber bestätigen, keine Nullschaden-/Godmode-Fokussierung.
|
||||
|
||||
Noch keine Kampfimplementierung oder Livekampftests in dieser Vorprüfung.
|
||||
Nur Dokumentation neu/uncommittet; keine weiteren Commits ohne konkreten Bedarf.
|
||||
Details zu Flucht, Zielverlust, verbleibenden Angreifern, Erstangriffsschwellen
|
||||
und konkreten Spieler-/Bot-Reaktionen noch nicht als Nutzerentscheidungen ausgeben.
|
||||
|
||||
---
|
||||
|
||||
# Aktuell: Instanzintent implementiert und technisch live geprüft
|
||||
|
||||
Stand 27.10.2026, letzter Testserverprozess PID **35865**, frisches Ready beim
|
||||
letzten Restart und Port 8085 geprüft. Nutzer beauftragte Umsetzung einschließlich
|
||||
zufälliger Verletzung (0–50 Prozent Max-HP) nach Rückkehr. Umsetzung fertig,
|
||||
Der Nutzer hat ausdrücklich auf eine weitere visuelle Abnahme verzichtet.
|
||||
Alle vorhandenen Änderungen sollen gemeinsam lokal committet werden; kein Push.
|
||||
Details: `instance-intent.md`.
|
||||
|
||||
Implementierung:
|
||||
- Intent `instance`, eigener Tagesplanwert (Default .5), feste Phasen statt
|
||||
zufälliger Innenraum-Mikroaktionen. Anreise verbraucht Blockzeit; zehn Sekunden
|
||||
Vorbereitung; tatsächlicher nativer Eintritt; Warten direkt dahinter; Rückkehr
|
||||
zu Blockende minus fünf Minuten; Nachruhe bis zum ursprünglichen Blockende.
|
||||
- Neue native Außenwelt-Aliase `instance_visit_at_<Trigger-ID>` und editierbare
|
||||
Ein-/Ausgangszuordnung. 108 Eingänge in Test-DB, insgesamt 2.973 Locations /
|
||||
3.966 Worldpoints. Innenräume bleiben reine native Karten/Graphknoten.
|
||||
- Charakterpersistenz enthält Phase, Trigger, Instanz-ID, absolute Frist,
|
||||
einmal gezogenen Verletzungswert und injury_applied. Gemeinsame Transaktion
|
||||
mit Player::SaveToDB über ASYNC-Worker, bestätigter Commit vor Fortschritt.
|
||||
- Optionales WorldScript in viano_bot_commands.cpp meldet nur gespeicherte
|
||||
Besucher beim Serverstart automatisch mit dem Adventure-Controller an.
|
||||
Wiederaufnahme hat Vorrang vor normalem Lua-Initialintent.
|
||||
- Getrennten Hinterausgang aus nativen Daten bevorzugen, expliziter Override
|
||||
möglich. Verborgene Dungeon-Durchquerung wird innen bis zum echten Ausgang
|
||||
abstrahiert, danach nativer Trigger. Fehlender Ausgang: Eingang. Keine Kämpfe,
|
||||
Beute/Inventar-/Geldänderung, keine DungeonBot-Abhängigkeit.
|
||||
|
||||
Geprüft:
|
||||
- Debug-Build -j10, installiert, **44 Testskripte im vollständigen abschließenden
|
||||
Lauf bestanden** (/tmp/vcore-instance-tests-final.log).
|
||||
- Beide additiven Migrationen angewendet. Tabellen-Collation unicode_ci passt
|
||||
zum bestehenden Schema; Dateien wegen *.sql-Ignore gezielt mit git add -f
|
||||
vorgemerkt, alle übrigen Änderungen uncommittet. Kein Push.
|
||||
- Verlies-Eingang 101, Ausgang 503, Karte34/Instanz-ID1 tatsächlich betreten.
|
||||
Echter Serverneustart während Phase3: automatischer Login, gleiche Instanz-ID1,
|
||||
ursprüngliche absolute Frist beibehalten. Normales Lua-Profil war restauriert.
|
||||
- Für schnelle Rückkehrprüfung wurde ausschließlich nach sauberem Serverstopp
|
||||
die Test-Besuchsfrist verkürzt. Original in
|
||||
/tmp/vcore-instance-live-original-deadline.tsv. Keine normale Codefrist geändert.
|
||||
- Native Rückkehr nach Karte0 (-8766.11,845.499,87.9952), zunächst zweimal echte
|
||||
0%-Würfe, nächster regulärer kurzer Testblock 17%: **2165/2609 HP**.
|
||||
Charakter-DB bestätigte Phase5, loss_percent17, injury_applied1 und HP2165.
|
||||
- Erneuter Logout/Login während Phase5: gleiche Frist, injuryApplied1, kein
|
||||
Neuwurf/keine zweite Verletzung. Aktuell Nachruhe vor dem Verlies bis
|
||||
Deadline1793128202; anschließend endet der manuelle Testauftrag. Zustand bei
|
||||
Wiederaufnahme neu prüfen; keinen weiteren Test automatisch starten.
|
||||
- Normales Profil in Quelle UND Installation bytegleich normal (SHA256
|
||||
26b11c3108e6ecc5dbc59d1852b4103ca4e818148603a34c02a470c969dc659b).
|
||||
Kein temporärer Lua-Override. Nach saveall Geld-/Inventar-SHA256 unverändert
|
||||
8d40931782d05219466ba9fd077ce7acd3e02bd53eb63f6e96115042c620d26a.
|
||||
|
||||
Wichtig: Fernanreise NICHT live erfolgreich verifiziert. Vorhandene Graph-
|
||||
Recovery-Schleifen führten erst nach Goldhain, dann durch Sturmwind. Nutzer hat
|
||||
Pfadfindung/Hinderniserkennung ausdrücklich auf später verschoben. Daher wurde
|
||||
für den isolierten Instanztest nur der ausgeloggte Testbot administrativ an den
|
||||
realen Außeneingang gestellt; anschließender lokaler MMAP-Anschluss und Eintritt
|
||||
waren regulär. Kein Instanzteleport als erfolgreicher Eintritt ausgegeben.
|
||||
Todesminen-Hinterausgang und zwei unabhängig gleichzeitig betretene Kopien nur
|
||||
produktive Adaptertests/Quellprüfung, noch kein entsprechender Livevergleich.
|
||||
|
||||
Erster Liveversuch fand meinen falschen SYNCH-Transaktionsweg; Debugserver
|
||||
beendete sich vor der Anreise. Fehler korrigiert auf AsyncCommitTransaction mit
|
||||
Commitresultat. Nachfolgende native Saves/Neustarts erfolgreich, Fehlerlog
|
||||
/tmp/vcore-instance-first-live-DBErrors.log erhalten. Nicht als aktuelles Problem
|
||||
missverstehen. Aktuell keine neuen Instanz-SQL-/Startfehler beobachtet.
|
||||
|
||||
Alle Schlaf-WIP-Änderungen von vorher erhalten. Bett-/Hinderniserkennung bleibt
|
||||
auf Nutzerwunsch zurückgestellt. Nur feature/clientless-player-core verwenden.
|
||||
|
||||
---
|
||||
|
||||
# Aktueller Auftrag: Instanzbesuche – Nutzervorgaben konkretisiert
|
||||
|
||||
Wirtschaftstest vom Nutzer als ausreichend beendet; nächster Intent sind
|
||||
Instanzbesuche. Details verbindlich in `instance-intent.md` festgehalten.
|
||||
Rest des gewählten Location-Zeitblocks, letzte fünf Minuten Nachruhe draußen.
|
||||
Beispiel 60 Minuten: 40 Anreise, 15 innen, 5 Nachruhe. Tatsächlicher Eintritt,
|
||||
Warten direkt hinter dem Eingang in nativer eigener Instanzkopie, keine
|
||||
Dungeon-Durchquerung/Kampf. Neustart: am Eingang innen wieder einloggen,
|
||||
ursprüngliche absolute Frist weiterverwenden. Rückkehr eigener Ausgang,
|
||||
sonst Eingang. Instanzinnenräume NICHT zu normalen Locations machen.
|
||||
|
||||
World-DB geprüft: areatrigger_teleport enthält 78 Deadmines Entrance Target,
|
||||
119 Exit Front Target, 121 Rear Exit Target. Alle sechs source/target-Knoten
|
||||
in vcore_clientless_travel_node vorhanden, Kommentare nur Triggernummern.
|
||||
Semantik aus nativen Namen und DBC-Quell-/DB-Zielkarten ableiten.
|
||||
|
||||
Noch keine Implementierung/Instanzbetretung in dieser Vorprüfung. Core-Befund:
|
||||
Online startet heute flüchtigen Behavior-Record/Profil neu; dauerhafte
|
||||
Besuchsphase/Frist und Wiederaufnahme müssen ergänzt werden. Native Instanz-ID,
|
||||
Solobindung und Instanzspeicherung für Restart berücksichtigen und testen.
|
||||
Eigener Ausgang hinten erfordert Rückkehrbehandlung ohne Dungeon-Durchquerung.
|
||||
Randfall Ankunft mit weniger als fünf Minuten: noch keine ausdrückliche
|
||||
Nutzerentscheidung, sinnvolle Ableitung ist Eintritt auslassen/Nachruhe.
|
||||
|
||||
Keine Code-/DB-/Serveränderung bei dieser Vorprüfung. Vorheriger Wirtschaftsintent
|
||||
kann auf dem Testserver weiterhin laufen; vor Implementierung Zustand prüfen.
|
||||
Schlaf-/Hindernisthemen bleiben ausdrücklich vertagt. Vorhandenes WIP bewahren.
|
||||
|
||||
---
|
||||
|
||||
# Aktueller Nutzerauftrag: freier Wirtschaftsintent im Handelsdistrikt
|
||||
|
||||
Bett-/Geometriesuche ausdrücklich vom Nutzer zurückgestellt. Ebenso spätere
|
||||
Überarbeitung der Pfadfindung/Hinderniserkennung (beobachtetes Durchlaufen von
|
||||
Zäunen und Erhöhungen). Diese offenen Themen sollen die weitere Entwicklung
|
||||
NICHT blockieren; jetzt daran nicht weiterarbeiten.
|
||||
|
||||
Arthoran GUID 26 hat auf Nutzerwunsch den autonomen Auftrag:
|
||||
`clientless adventure intent 26 economy poi_tele_954 3600`.
|
||||
`poi_tele_954` ist der vorhandene allgemeine Sturmwind-Anker im Handelsdistrikt
|
||||
(-8833.07,622.778,93.9317), Kategorie landmark; keine Händler-/Bank-/AH-Rollensperre
|
||||
wie bei den spezialisierten Testankern. Kein gezielter Mikroaktionszwang.
|
||||
INTENT_ARRIVED economy und selbst gewählter Start `economy_vendor_visit`
|
||||
gegen echten Händler Entry 277, GUID Low 1325, sind bestätigt. Szene läuft.
|
||||
Kein erneuter Build/Restart oder Lua-Profilwechsel für diesen Auftrag.
|
||||
|
||||
Vorher `saveall`; Geld-/Inventar-SHA256 weiterhin
|
||||
8d40931782d05219466ba9fd077ce7acd3e02bd53eb63f6e96115042c620d26a.
|
||||
Wirtschaften bleibt rein performativ: keine echten Transaktionen.
|
||||
Nutzer beobachtet nun die freie Ausführung im Spiel; keine neue visuelle
|
||||
Abnahme behaupten. Schlafboden am ersten Anker war vom Nutzer bestätigt.
|
||||
|
||||
Alle vorherigen WIP-Änderungen erhalten, Branch feature/clientless-player-core,
|
||||
kein Push. Normales Lua-Profil weiterhin unverändert. Schlaf-Testanker und
|
||||
bisheriger Ausbau bleiben erhalten, siehe historische Notizen unten.
|
||||
|
||||
---
|
||||
|
||||
# Neuer Liveauftrag: Suche bei Allitesters Position
|
||||
|
||||
Nach dem Flächenausbau wollte der Nutzer eine erneute Suche nahe den beiden
|
||||
Betten an seiner aktuellen Position. `saveall`, danach Allitester GUID 21:
|
||||
Map 0, (-8877.360, 673.489, 104.950), O=0.649831. Separater aktiver manueller
|
||||
Suchanker `gilded_rose_sleep_room_test` in Test-DB angelegt, Kategorie rest_sleep,
|
||||
Metadata von Sturmwind; bestehende Punkte nicht verschoben.
|
||||
|
||||
Neustart war nötig: adventure reload erneuert NICHT den Reisepunkt-Cache,
|
||||
weshalb der erste Anreiseversuch den neuen Punkt nicht fand und zurückfiel.
|
||||
Server jetzt PID 32004, frisches Ready nach elf Sekunden, Port 8085 geprüft.
|
||||
Einmaliges Loginprofil rest/room_test danach bytegleich restauriert, installierte
|
||||
Profilkopie ebenfalls normal. Arthoran erreichte den neuen Anker regulär.
|
||||
|
||||
Erneute Suche dort: beds=0 raised=0 floor=46 (erster Lauf floor=34).
|
||||
REST_CONFIRMED am Anker (-8877.360,673.489,104.950), O=.650, zuletzt 143 Sekunden.
|
||||
Die sichtbaren Betten werden also weiterhin NICHT als Bett/erhöhte Fläche erkannt;
|
||||
Ursache der konkreten geometrischen Ablehnung ist NICHT gemessen. Nicht behaupten,
|
||||
dass nur der bisher zu kleine Radius schuld war.
|
||||
|
||||
Die gewichtete Auswahl wählte zwischenzeitlich wieder den alten Schlafanker.
|
||||
Für den gezielten Versuch wurde NUR `gilded_rose_sleep_upstairs` kurz enabled=0
|
||||
gesetzt, Katalog geladen, micro rest_sleep ausgeführt, dann enabled=1 restauriert
|
||||
und Katalog erneut geladen. Kein Punkt blieb vorübergehend deaktiviert.
|
||||
DB-Helfer /tmp/vcore-sleep-room-test.py, Positionssnapshot daneben als JSON.
|
||||
Nutzer hat neuen Bodenplatz am alten Anker sichtbar bestätigt; Bettdarstellung
|
||||
und tatsächliche Bettnutzung weiterhin offen. Kein neuer Code/Build in diesem
|
||||
Folgeversuch. Vor weiterer Arbeit laufende Szene/Position neu prüfen.
|
||||
|
||||
---
|
||||
|
||||
# Aktuell: Schlafplatzsuche am 27.10.2026
|
||||
|
||||
Dieser Abschnitt hat Vorrang vor den historischen Checkpoints unten.
|
||||
Der Nutzer nahm den Schlaftest wieder auf, sah Arthoran mitten im oberen Stuhl
|
||||
und beauftragte eine Flächensuche: Betten/geeignete erhöhte Flächen bevorzugen,
|
||||
sonst freier Gasthausboden, auch für Gasthäuser ohne Betten.
|
||||
|
||||
Implementiert, gebaut (`-j10`), installiert und live getestet, noch uncommittet:
|
||||
`AdventureRestSpace.h`, Schlafadapter in `AdventureBehaviorMgr.cpp`, gespeichertes
|
||||
Szenenziel in `.h`; zwei neue Regressionen und erweiterter Ruhetest. Insgesamt
|
||||
39 Testskripte erfolgreich (38er-Lauf plus neuer nativer Adaptertest; danach
|
||||
betroffene erweiterte Tests erneut erfolgreich). Details: `rest-intent.md`.
|
||||
|
||||
Schlafanker sind jetzt Suchbereiche, keine ungeprüften Liegepunkte. Native
|
||||
Bettobjekte vor erhöhten Flächen mit abrupten Seitenkanten vor freiem Boden.
|
||||
Geometrie ist keine sichere Bettsemantik; passende Tische können ähnlich sein.
|
||||
Modellabhängige Liegefläche, Höhen-/Kollisionsraster, native Stuhlsperre,
|
||||
Spieler/Kreaturenbelegung, Innenraum und Stockwerksgrenze. Tatsächlicher
|
||||
MMAP-Endpunkt muss passen, kein Teleport/Klettern auf unerreichbare Möbel.
|
||||
Erneute Prüfung vor Hinlegen und alle zwei Sekunden. Keine neue SQL-Migration.
|
||||
|
||||
Live: Prozess 31446, frisches Ready nach elf Sekunden, Port 8085 bestätigt.
|
||||
Arthoran GUID 26 im Ruheauftrag `gilded_rose_sleep_upstairs`. Die neue Suche
|
||||
fand `beds=0 raised=0 floor=18`; er ging 4,03 Yards zu
|
||||
(-8868.534, 682.800, 104.949), Ausrichtung 3,740, Endpunktfehler null.
|
||||
`REST_CONFIRMED` für 243 Sekunden. Die sichtbare Abnahme des neuen Bodenplatzes
|
||||
ist offen, ebenso ein positiver Live-Betttest; Fixturetests decken Betten ab.
|
||||
Normales Lua-Profil in Quelle UND Installation bytegleich wiederhergestellt,
|
||||
mining/blacksmithing unverändert. Kein temporäres Override, kein Push.
|
||||
|
||||
Die zuvor bereits vorhandene Änderung an `rest-intent.md` zur ersten
|
||||
Schlafvorführung wurde erhalten und ergänzt. Branch ausschließlich
|
||||
`feature/clientless-player-core`. Build/Install/Testlogs: `/tmp/vcore-sleep-*.log`.
|
||||
Prozess-/Szenenzustand beim Fortsetzen neu prüfen. Nicht automatisch den
|
||||
abgeschlossenen Berufs-Ausbau oder die vertagte Instanzarbeit beginnen.
|
||||
|
||||
---
|
||||
|
||||
# Fortsetzung am 27.10.2026 – aktueller Stand hat Vorrang
|
||||
|
||||
Der unten erhaltene Sitzungswechsel-Checkpoint ist historisch. Der Berufs-Ausbau
|
||||
ist jetzt vollständig gebaut (`-j10`), auf dem Testserver installiert und die
|
||||
Migration `_05` ist auf der Test-World-DB angewendet. **37 Testskripte bestanden**.
|
||||
Keine Änderungen wurden gepusht. Branch bleibt `feature/clientless-player-core`.
|
||||
|
||||
Seit dem Checkpoint behoben:
|
||||
- Berufsarbeit an GOs nähert sich nach Verdrängung erneut, bevor weitere Gesten laufen.
|
||||
- Native unsichtbare Arbeitsplatzmarker verwenden VMAP-Sichtprüfung zur Arbeitsfläche
|
||||
(mindestens 1,5 Yards über dem Marker); Bodenmarker im Amboss blockierten zuvor die Szene.
|
||||
- Location-Abfrage liest numerische native Spalten ohne COALESCE-Widening. Debug verlor
|
||||
zuvor `is_area`/`faction`; Elwynn wird live jetzt korrekt als `area=1` geladen.
|
||||
|
||||
Zusätzliche Tests: echter Lua-5.4-Professionsparser mit Arthoran/generic und ungültigen
|
||||
Profilen; native Lock-/Station-/Kadaver-/Trainerklassifikation; Szene erst nach Ankunft,
|
||||
Profilentzug, Wiederannäherung; SQL-Fixtures mit erhaltenen Gewichten/Freigaben;
|
||||
erreichbare Gebietsknoten; progressive Suche und Uferbedingungen; echte Debug-Fieldgetter
|
||||
und VMAP-Sichtlinienadapter. Siehe `tests/clientless/test_adventure_profession_*.py`,
|
||||
`test_adventure_area_node.py` und erweiterte bestehende Harnesses.
|
||||
|
||||
Live bestätigt:
|
||||
- Frische Ready-Meldung, laufender Prozess und Port 8085 nach Installation.
|
||||
- Arthoran lädt zwei Hauptberufe; Profil ist bytegleich wiederhergestellt:
|
||||
`social` / `goldshire_tavern`, mining + blacksmithing. Kein temporäres Profil liegenlassen.
|
||||
- Reguläre Anreise zu `poi_guard_541` über Graph, Taxi und Bodenwege.
|
||||
- `smithing_show` wählt echtes Anvil-GO **201415**, Low **556**; Work-Emote **233**;
|
||||
`PROFESSION_WORK_COMPLETE` und `PROFESSION_VISIT_COMPLETE` nach Abschluss.
|
||||
- `profession_herbalism` live als nicht verfügbar zurückgewiesen. Die isolierte
|
||||
Profilprüfung auch bei vorhandener Pflanze ist durch den produktiven Zieltest belegt.
|
||||
- Nach `saveall` unveränderte Geld-/Inventar-Prüfsumme:
|
||||
`8d40931782d05219466ba9fd077ce7acd3e02bd53eb63f6e96115042c620d26a`.
|
||||
- Elwynn-Auftrag `profession poi_tele_338` lädt `area=1`, startet `travel_to_node`,
|
||||
erreicht mit bestehendem Free-flight-Fallback den Gebietsknoten und meldet `INTENT_ARRIVED`.
|
||||
Lokale `profession_search` absolvierte danach alle sechs progressiven MMAP-Wegpunkte
|
||||
(ca. 104 Yards, `LEISURE_COMPLETE`, legs=6).
|
||||
- Letzter geprüfter Testserverprozess: PID 28577, frische Ready-Meldung und Port 8085.
|
||||
Beim Wiederaufnehmen immer den tatsächlichen Zustand neu prüfen.
|
||||
|
||||
Offener Befund: Der erste Intentwechsel während aktiver Goldshire-Anreise geriet in
|
||||
Graph-Handover-/Recovery-Schleifen zum nächstgelegenen `portal_at_109_target`.
|
||||
Für die gezielten Tests wurde deshalb nur beim Login die Startvorgabe temporär
|
||||
geändert und danach bytegleich restauriert. Dieses Travel-Handover ist NICHT als
|
||||
behoben zu betrachten. Navigationslog enthält die Vorgänge ab 17:43.
|
||||
|
||||
Dokumentation: [profession-intent.md](profession-intent.md). Visuelle Abnahme bleibt
|
||||
beim Nutzer; Freizeit-Ausritt/Rundflug und Schlafdarstellung bleiben zurückgestellt.
|
||||
Alle ursprünglichen Regeln und fachlichen Festlegungen unten gelten weiterhin.
|
||||
|
||||
---
|
||||
|
||||
# Gesicherter Arbeitsstand – hier fortsetzen
|
||||
|
||||
Stand: 27.10.2026. Der Nutzer hat die Implementierung ausdrücklich für einen
|
||||
Codex-Sitzungswechsel unterbrechen lassen. Diese Notiz ist die maßgebliche
|
||||
Übergabe. Nicht bei null beginnen und keine vorhandenen Änderungen verwerfen.
|
||||
|
||||
## Sofort beim Wiederaufnehmen
|
||||
|
||||
1. `AGENTS.md` und diese Datei lesen; Branch und Working Tree prüfen.
|
||||
2. Ausschließlich `feature/clientless-player-core`, niemals `master`, kein Push.
|
||||
3. Der unten beschriebene Berufs-Ausbau ist **unfertig und NICHT installiert**.
|
||||
4. Der laufende Build wurde zur Sicherung geordnet mit SIGINT unterbrochen.
|
||||
Vor erneutem Bauen trotzdem nach verbleibendem CMake/Ninja-Prozess sehen.
|
||||
Keine zwei Builds gleichzeitig. Immer **`-j10`**, niemals `-j4`.
|
||||
5. Neueste Compiler-/Teststände prüfen und die untenstehenden offenen Arbeiten
|
||||
fortsetzen. Kein Installieren eines nur teilweise gebauten Standes.
|
||||
|
||||
## Aktueller Auftrag und verbindliche Nutzerentscheidungen
|
||||
|
||||
Wir arbeiten am Intent **Beruf (`profession`)**, nach Geselligkeit, Ruhe,
|
||||
Freizeit, Wirtschaften und dem Abenteuer-Erkundungsausbau. Danach folgen
|
||||
Instanzbesuche. Kampf kommt GANZ AM ENDE, gemeinsam mit reaktiver Selbstwehr
|
||||
(z. B. bei Angriff während einer Reise).
|
||||
|
||||
- Alle Berufsaktionen bleiben **dauerhaft rein performativ**. Es wird NICHT
|
||||
tatsächlich abgebaut, gesammelt, gekürschnert, produziert, gefangen oder
|
||||
geheilt. Keine Beute, Quellenerschöpfung, Inventar-/Materialänderung,
|
||||
Fertigkeitserhöhung oder tatsächliches Erlernen. Nicht „zunächst“ schreiben.
|
||||
- Hauptberufe dürfen NUR ausgeführt werden, wenn sie im Lua-Charakterprofil
|
||||
ausdrücklich eingetragen sind. Nebenberufe brauchen diese Freigabe nicht;
|
||||
Vorlieben werden später weiter über gewichteten Zufall ausgestaltet.
|
||||
- Der Nutzer hat die Rückfrage ausdrücklich beantwortet: **Arthoran hat
|
||||
Bergbau und Schmiedekunst**. In seinem Profil stehen deshalb dauerhaft
|
||||
`professions = { primary = { "mining", "blacksmithing" } }`.
|
||||
KEIN Kräutersammeln bei ihm erlauben, auch nicht vor vorhandenen Pflanzen.
|
||||
Das generische Profil enthält eine leere Hauptberufsliste.
|
||||
- Ort und Gebiet sind gleichberechtigte Ziele. Ein Bot soll z. B. das Gebiet
|
||||
Elwynn anreisen und dort lokal selbst nach passenden Ressourcen suchen.
|
||||
- **Hierarchie:** Tagesplan wählt Intent, dann passender importierter Ort,
|
||||
dann lokal mögliche Mikroaktion. Der Ortsbestand darf die Intentauswahl
|
||||
nicht vetoieren. Die Location-/Intent-Katalogzuordnung legt die Eignung fest.
|
||||
- Eine für `profession` geeignete Location (auch ein ganzes Gebiet) schaltet
|
||||
NICHT alle Berufsaktionen frei. Schmieden braucht einen echten nahen Amboss,
|
||||
Schmelzen eine Esse, Kräutersammeln eine tatsächliche Pflanze UND Profilrecht.
|
||||
- Gebietsanreise ist bereits vorhanden: `AdventureBehaviorMgr::AreaNode`
|
||||
sucht einen ERREICHBAREN Graphknoten im Zielgebiet, `Begin` reist über
|
||||
`travel_to_node`; die Ankunft wird gegen das Gebiet geprüft.
|
||||
- Abenteuer soll regulär draußen in passenden Weltgebieten stattfinden.
|
||||
Sturmwind ist nur Testgebiet; keine zusätzlichen Stadt-Sonderregeln bauen,
|
||||
sondern passende gespeicherte Locations/Intent-Gewichte verwenden.
|
||||
- Ausritte, Freizeit-Rundflüge und Schlafdarstellung sind auf Nutzerwunsch
|
||||
weiterhin für spätere visuelle Tests zurückgestellt. Jetzt nicht testen.
|
||||
|
||||
## Umgebung und Betriebszustand beim Sichern
|
||||
|
||||
- Source: `/home/wow_admin/wow_cata_server/source/TrinityCore`.
|
||||
- Build: `/home/wow_admin/wow_cata_server/build/debug`, Ninja, Debug.
|
||||
- Install: `/home/wow_admin/wow_cata_server/server/debug`.
|
||||
- Testserver: tmux `vcore-worldserver`, cwd `server/debug/bin`, `./worldserver`.
|
||||
- Vor dem Sichern lief **PID 19058**, letzter installierter Abenteuer-Ausbau.
|
||||
Diesen nicht blind wiederverwenden: Prozesszustand beim Fortsetzen prüfen.
|
||||
- Arthoran: Charakter GUID **26**, Account 6, aktuell Abenteuer am importierten
|
||||
Sturmwind-Ort `poi_tele_954`. Allitester GUID 21 kann als Zuschauer online sein.
|
||||
- Der BERUFS-Ausbau wurde noch nicht installiert; SQL-Migration `_05` wurde
|
||||
noch NICHT eingespielt. Der laufende Server ist daher der vorherige Stand.
|
||||
- Arthorans normale Startvorgabe im gespeicherten Lua-Profil ist wieder
|
||||
`social` / `goldshire_tavern`. Es gibt aktuell KEIN temporäres Login-Profil.
|
||||
- Der letzte Build wurde mit j10 unterbrochen, bei 749/751 Schritten (libgame.a gelinkt; letzte Linkschritte noch offen). Die nächste
|
||||
inkrementelle Ausführung kann normal weiterbauen; Objektdateien erhalten.
|
||||
- Erster Build hatte nur den Fehler `Creature::GetDeathState` statt
|
||||
`getDeathState`. Das wurde bereits korrigiert. Der daraufhin neu gestartete
|
||||
Build hatte bis zur Unterbrechung keine weiteren gemeldeten Compilerfehler.
|
||||
- CMake wurde mit den bestehenden Einstellungen neu ausgeführt, um die neue
|
||||
`AdventureProfessionTargets.cpp` einzusammeln (CollectSourceFiles ohne
|
||||
CONFIGURE_DEPENDS). Das löste einen größeren Build aus. Nicht grundlos
|
||||
erneut konfigurieren, nur mit j10 weiterbauen.
|
||||
|
||||
## Bereits geschriebene, noch unfertige Berufs-Implementierung
|
||||
|
||||
### Profil und Regeln
|
||||
|
||||
- `AdventureProfessionPolicy.h`: reine Regeln/Task-Spezifikationen, elf
|
||||
Hauptberufe, kanonische englische Bezeichner, Nebenberufe ohne Primärfreigabe.
|
||||
Hauptberufsrecht stammt aus dem Profil, NICHT aus `Player::HasSkill`.
|
||||
- `ClientlessAdventureProfile::PrimaryProfessions` und Lua-Parser für
|
||||
`professions.primary` als Array. Unbekannte Namen warnen und gewähren nichts.
|
||||
- `arthoran.lua`: mining + blacksmithing. `generic.lua`: leeres Array.
|
||||
- `Trainer.h`: nur neuer generischer, read-only Zugriff `GetSpells() const`.
|
||||
Kein Lernen/Trainer-Handler wird aufgerufen.
|
||||
|
||||
### Echte Ressourcen und Arbeitsplätze
|
||||
|
||||
- Neu: `AdventureProfessionTargets.{h,cpp}`.
|
||||
- Erz/Pflanzen: echte aktive CHΕST-GOs, native Lock-/Skill-Anforderungen aus
|
||||
`sLockStore` / `SkillByLockType`, nicht bloß Namen oder Locationkategorie.
|
||||
Nur sichtbare, phasenrichtige, bereite und erreichbare Ziele.
|
||||
- Kürschnerei: vorhandener toter BEAST-Kadaver im Zustand CORPSE mit nativem
|
||||
SKINNABLE-Flag. Kein Erzeugen/Töten eines Tiers. Kampf/Jagd später.
|
||||
- Arbeitsplätze: neuer editierbarer Katalog `vcore_adventure_workstation`
|
||||
mit GO-Templateentry, semantischer Rolle und enabled. Keine Bot-/Ort-ID-Liste.
|
||||
Native Fokuskennungen geprüft: 1 Amboss, 3 Esse, 4 Kochfeuer, 663 Alchemielabor,
|
||||
1589 Lexikon. 623/543 sind besondere Amboss-/Essenfokusse.
|
||||
- Native unsichtbare SPELL_FOCUS-Marker repräsentieren reale Kartenarbeitsplätze
|
||||
und dürfen dafür genutzt werden. Keine Aktivierung/Objektbenutzung.
|
||||
- Rollen ohne reale erkennbare Arbeitsplätze bleiben nicht verfügbar; keine
|
||||
beliebige Werkstatt-Location als Amboss behandeln.
|
||||
- Trainer: native Tradeskill-Trainer, deren native Spell-/SkillLine-Daten zu
|
||||
einem erlaubten Haupt- oder einem Nebenberuf passen. Reines Gespräch.
|
||||
|
||||
### Szenen und bestehende Legacy-Aktionen
|
||||
|
||||
- Wiederverwendete `AdventureSocialActions` mit `Cue::Work`, professionellen
|
||||
Zielprüfungen, nativen Emote-Zuständen, Abschlussbetrachtung und kurzem
|
||||
Wegtreten. Keine Harvest-/Craft-/Loot-/Teach-/Heal-Aufrufe.
|
||||
- Profil und Ziel werden auch während der Szene erneut geprüft.
|
||||
- Alte `mining_show` / `smithing_show` (Kind `work`, Requirement ore/forge)
|
||||
werden in `ResolvedAction` auf dieselben neuen gesperrten Szenen umgelegt.
|
||||
Es darf KEIN Legacy-Bypass der Profil- oder Arbeitsplatzprüfung verbleiben.
|
||||
- Nach vollständiger Sammeldarstellung wird `work:<GUID>` in der bestehenden
|
||||
Zielhistorie gespeichert. Kürzlich bearbeitete Ressourcen werden gemieden,
|
||||
damit die unverändert stehen bleibende Quelle nicht endlos wiederholt wird.
|
||||
Nur Erzbetrachtung (`ore_inspect`) setzt diese Bearbeitungssperre nicht.
|
||||
|
||||
### Gebietssuche / gemeinsame Erkundungssteuerung
|
||||
|
||||
- Neue Suche `profession_search`, Requirement `work_search`, Kind `outing`.
|
||||
- Wiederverwendete MMAP-Routensteuerung: progressive Hinwege, an erreichten
|
||||
Kontrollpunkten erneut mögliche Berufsarbeit prüfen und Suche dann beenden.
|
||||
- Bei Gebietsaufträgen wird der lokale Anker nach bestätigtem Suchfortschritt
|
||||
verschoben. Weiteres Durchsuchen bleibt über jeden MMAP-Punkt im Zielgebiet.
|
||||
- Gebiets-Abenteuerwege sind jetzt ebenfalls progressiv; normale Freizeitwege
|
||||
bleiben bestätigte Hin-/Rückwege. Keine Stadt-Sonderregel.
|
||||
- Zusätzliche native Uferprüfung für performatives Berufsangeln im Gebiet,
|
||||
ohne zwingenden speziellen Fishing-Location-Key. Ausgerüstete Angel bleibt
|
||||
nötig. Kein wirklicher Angelzauber/Fang. Noch nicht live getestet.
|
||||
|
||||
### Neue Migration
|
||||
|
||||
`sql/custom/world/2026_10_27_05_adventure_profession.sql` (noch NICHT angewendet):
|
||||
Arbeitsplatzrollen, neue Arbeits-/Such-/Nebenberufs-/Gesprächsaktionen,
|
||||
Berufsgewichtung für Gebiet/Wildnis/Siedlung, neue Texte. Native Fokusdaten
|
||||
haben Vorrang; Namen ergänzen nur erkennbare geeignete Props. Geänderte
|
||||
Gewichte/disabled-Rollen sollen bei Wiederholung erhalten bleiben.
|
||||
|
||||
## Offene Arbeiten – konkret hier weiter
|
||||
|
||||
1. Aktuellen C++-Diff kritisch prüfen; dies ist ein WIP, keine fertige Abnahme.
|
||||
Insbesondere Berufsszenen, Legacy-Auflösung, progressive Ankeraktualisierung,
|
||||
Ressourcen-Wiederholungsdämpfung und Uferprüfung gegen Nutzerregeln prüfen.
|
||||
2. `cmake --build /home/wow_admin/wow_cata_server/build/debug -j10` fortsetzen.
|
||||
Vorher prüfen, dass kein alter Build mehr läuft. Weitere Fehler beheben.
|
||||
3. Vollständige Tests erneut laufen lassen. Vor dem Berufs-Ausbau waren
|
||||
**32 Tests grün**. Seitdem gab es 7 Mock-/Harness-Anpassungsfehler, deren
|
||||
Fixes bereits TEILWEISE geschrieben sind. Alte Fehlerdateien sind historisch!
|
||||
- Economy/Exploration/Social-fire: neues Policy-Include und Profilfelder,
|
||||
Targets-Stub für zusätzlich mitkompilierte Zweige.
|
||||
- Social: Map-/Position-/Origin-Stubs und native Work-Emotes ergänzt;
|
||||
zuletzt nach INVALID_HEIGHT-Fix wieder grün.
|
||||
- Exploration und Leisure: nach Anpassungen zuletzt wieder grün.
|
||||
- Intent-state: neue Scene-Felder Progressive/Route/Step ergänzt;
|
||||
letzter Fehler fehlende Player::GetExactDist(Position const&). Der
|
||||
Überladungs-Fix ist bereits geschrieben, aber noch nicht erneut geprüft.
|
||||
- Rest-fire: PrimaryProfessions in Mock-Profil/-Kontext ergänzt;
|
||||
aktuellen Zustand durch erneuten Lauf prüfen.
|
||||
4. Neue aussagekräftige Berufs-Tests fehlen noch! Geplant:
|
||||
- tatsächlichen neuen Lua-Parser mit realem Lua 5.4 ausführen, inklusive
|
||||
Arthoran mining/blacksmithing, leeres/ungültiges Profil sperrt Hauptberufe;
|
||||
- Mining+Smithing darf vorhandene Kräuter NICHT bearbeiten, umgekehrt darf
|
||||
Herbalism+Alchemy keine Erz-/Schmiedearbeit; sekundäre Aktionen ohne Liste;
|
||||
- produktive native Zielklassifikation: Lock-Skills statt Namen, Amboss
|
||||
versus Esse versus bloße Workshop-/Gebietszuordnung, falsche Phase,
|
||||
despawnte/gelootete Quelle, Kadaverprüfung und passende Trainer;
|
||||
- native Arbeitsgeste erst NACH tatsächlicher Ankunft, Profilentzug während
|
||||
laufender Szene, keine Objektbenutzung/Casts/Inventaränderung, Abschluss;
|
||||
- Migration auf Schemafixtures ausführen, Idempotenz und bearbeitete
|
||||
Gewichte/Arbeitsplatzfreigaben erhalten;
|
||||
- Gebiets-Anreise über erreichbaren Graphnode und lokale progressive Suche
|
||||
innerhalb des Gebiets, Stopp bei gefundenem zulässigem Arbeitsplatz.
|
||||
5. Erst dann neue Migration auf TEST-DB anwenden. Noch kein profession_apply-
|
||||
Modus im gesicherten DB-Helfer! Ergänzen oder engen eigenen Helfer schreiben.
|
||||
6. Erfolgreichen Build nach sauberem Serverstopp installieren, neu starten und
|
||||
frische Ready-Meldung + Prozess + Port 8085 prüfen. AGENTS-Recovery beachten.
|
||||
7. Live prüfen: tatsächlicher Amboss in Sturmwind (z. B. importierter
|
||||
`poi_guard_541`, Schmiedebereich), dann Gebietsziel `poi_tele_338` = Elwynn,
|
||||
Gebiet 12, echtes travel_to_node und lokale Ressourcen-/Arbeitsplatzsuche.
|
||||
Kräuter muss Arthoran verweigern. Inventar/Geld und Ressourcen unverändert
|
||||
nachweisen. Keine gefälschten Ressourcen, Spawns oder Teleports.
|
||||
8. Berufs-Dokumentation schreiben, Katalog-/Standdokumente aktualisieren und
|
||||
offen gebliebene Live-/visuelle Prüfungen ehrlich benennen.
|
||||
|
||||
## Wichtige vorherige Ergebnisse – nicht neu implementieren
|
||||
|
||||
- Reisegraph: optionale virtuelle Exits regelmäßig (6 s) während Weiterbewegung
|
||||
prüfen, kein Abbruch nach fünf Versuchen, Kante nicht mitten darin umkehren.
|
||||
Free-flight-Fallback getrennt von künstlichen Normalreise-Auswahlregeln.
|
||||
- Ruhe/Feuer: gemeinsames natives Kochfeuer 818, neue Feuer nie in Gebäuden/
|
||||
Städten. Schlafdarstellung weiterhin vertagt.
|
||||
- Freizeit: Katze (Spell 10673, Creature 7385), Leine (Item 37460, Spell 48722),
|
||||
echte native Begleiter-/Itemverwendung. Kanal beim Gehen erhalten. Owned-only
|
||||
Cleanup, keine Veränderung fremder Begleiter. Nutzer hat sichtbare Katze,
|
||||
Leine, zusammenhängende Routen und flüssige Bewegung ausdrücklich abgenommen.
|
||||
- Native Follow-Fix: aktive Player-Splinegeschwindigkeit statt Run-Flag wählen;
|
||||
SetWalk setzt die Gait-Auswahl, nicht MOVEMENTFLAG_WALKING. Das beseitigte
|
||||
die ständigen Zwei-Meter-Pausen. Nicht wieder entfernen.
|
||||
- Native Spline-Kurzsegment-Fix: 0,11 Yards Mindestabstand beim Splitten.
|
||||
- Wirtschaften rein performativ; Händler/Bank/AH und Vergleich mit zwei GUIDs
|
||||
technisch live geprüft, Geld/Inventar danach bytegleich.
|
||||
- Importfehler behoben: SMALLINT maps über GetUInt16 statt GetUInt32, das in
|
||||
Debug Null ergab. Gezielte, idempotente `clientless adventure repairimport`
|
||||
reparierte 2.159 unveränderte abgeleitete Orte, ergänzte 217. Jetzt **2.864**
|
||||
aktive semantische Locations / 3.857 Worldpoints. 16 manuelle Orte unverändert.
|
||||
Vier Horde-Hauptstädte korrekt auf Karte/Fraktion zugeordnet. Nicht die
|
||||
originalen world-DB-Quellen ändern. Snapshots liegen bei dieser Übergabe.
|
||||
- Location-Zuordnung: kein versteckter Wirtschaften-Fallback mehr im Code;
|
||||
`_04` materialisiert ausdrückliche Kategorie-/Intent-Gewichte, inklusive
|
||||
begrenzter Freizeitgewichtung für Tavernen. Tagesplan-Intent unabhängig davon.
|
||||
- Abenteuer `_04`: native Objektuntersuchung ohne Use, Scout/Equipment,
|
||||
zusammenhängende Bodenwege. Zehn neue Aktionen, 32 Tests bestanden, technisch
|
||||
live in Sturmwind: Pestle's Apothecary 197117, Weller's Arsenal 197121,
|
||||
80-Yards-Erkundungsweg mit zehn bestätigten Hin-/Rückwegpunkten. Visuelle
|
||||
Abnahme und gefährliche offene Welt weiterhin separat.
|
||||
|
||||
## Werkzeuge, Logs und reproduzierbarer Betrieb
|
||||
|
||||
Dauerhafte Kopien für diese Übergabe:
|
||||
`doc/clientless/checkpoints/2026-10-27-profession/`.
|
||||
Darin Build-/Configurelogs, historische fehlgeschlagene Testausgaben,
|
||||
Ortskatalog-Snapshots und die bisherigen schmalen DB-Helfer. Diese Helfer lesen
|
||||
Verbindungsdaten aus der lokalen Testserverkonfiguration; keine Passwörter
|
||||
im Chat/Logs ausgeben. Sie enthalten keine fest codierten Zugangsdaten.
|
||||
Die Helfer bei Bedarf wieder nach `/tmp` kopieren; Pfade gelten für diesen Host.
|
||||
|
||||
Wichtige Live-Logs (normal und ohne vorsorgliche Elevation lesen):
|
||||
`/home/wow_admin/wow_cata_server/server/debug/bin/Server.log`,
|
||||
`adventurebot-navigation.log`, `DBErrors.log`. Server.log wird beim Start neu
|
||||
begonnen, Navigations-/DBErrorslogs können ältere Fehler enthalten. Bekannte
|
||||
alte Script-/Spell-Warnungen nicht mit neuem Startup-Versagen verwechseln.
|
||||
|
||||
Buildbefehle: `cmake --build .../build/debug -j10`, bestehende Installation
|
||||
mit `cmake --install .../build/debug`. Tool-Sandbox für Build/Install/tmux/DB
|
||||
beachten, aber normale Logs nicht vorsorglich eskalieren. Keine laufende
|
||||
Executable überschreiben. Kein Push.
|
||||
|
||||
Für gezielte Tests nach Restart wurde bisher nur beim Login die Startvorgabe
|
||||
in arthoran.lua temporär geändert, vorher byteweise gesichert, nach
|
||||
`[AdventureBot][Profile] loaded guid=26` exakt zurückgesetzt. Die jetzt dauerhaft
|
||||
vereinbarten Hauptberufe dabei unbedingt erhalten. Keine temporären Profile
|
||||
liegenlassen. Alternativ normalen Login abwarten und per Console Intent setzen;
|
||||
auf unerwünschte automatische Goldshire-Anreise achten.
|
||||
|
||||
Console-Beispiele ohne führenden Punkt:
|
||||
`clientless login 26`, `clientless adventure status 26`,
|
||||
`clientless adventure intent 26 profession poi_guard_541 3600`,
|
||||
`clientless adventure intent 26 profession poi_tele_338 3600`,
|
||||
`clientless adventure micro 26 <action_key>`, `saveall`.
|
||||
|
||||
Der Nutzer möchte vor allem konkrete, überprüfte Ergebnisse und wenig
|
||||
Bestätigungsfragen. Die Hauptberufs-Rückfrage ist bereits BEANTWORTET; nicht
|
||||
noch einmal stellen. Testservermanagement und lokale Commits sind autorisiert.
|
||||
@@ -0,0 +1,109 @@
|
||||
# Abenteuer: Erkundung und Untersuchung
|
||||
|
||||
Technischer Intent: `adventure`. Diese Ausbaustufe ergänzt den bisherigen
|
||||
Aufenthalt durch zusammenhängende Erkundungswege und beobachtende Szenen.
|
||||
Echte Monsterjagd, Flucht und Todesbewältigung bleiben spätere Ausbaustufen.
|
||||
Vorhaben, Ortsauswahl und tatsächliche Mikroaktion bleiben getrennt: Die
|
||||
Location-/Intent-Zuordnung entscheidet, ob ein Ort zum Abenteuer passt;
|
||||
Umgebung und Erreichbarkeit bestimmen die dort möglichen Aktionen.
|
||||
|
||||
Migration: `sql/custom/world/2026_10_27_04_adventure_exploration.sql`.
|
||||
|
||||
## Aktionen
|
||||
|
||||
| Schlüssel | Darstellung |
|
||||
|---|---|
|
||||
| `adventure_explore` | Einen zusammenhängenden nativen MMAP-Weg erkunden und zurückkehren. |
|
||||
| `adventure_patrol` | Einen kürzeren Wegabschnitt abschreiten; dieselbe geprüfte Routenfähigkeit. |
|
||||
| `adventure_view` | Im Außenbereich die Umgebung von der aktuellen Position aus betrachten. |
|
||||
| `adventure_inspect` | Ein tatsächlich vorhandenes erreichbares Objekt aufsuchen und betrachten. |
|
||||
| `adventure_inspect_detail` | Nach der Ankunft genauer betrachten, eine Fragegeste zeigen und auf das Objekt weisen. |
|
||||
| `adventure_point` | Zu einem passenden Objekt gehen und darauf zeigen. |
|
||||
| `adventure_scout` | Innehalten, nach links und rechts Ausschau halten. |
|
||||
| `adventure_equipment` | Eine kurze Ausrüstungsprüfung mit nativer Benutzungs-/Vorbereitungsgeste darstellen. Keine Inventaränderung. |
|
||||
| `adventure_entrance` | Am gewählten Ruinen-, Höhlen-/Minen- oder Dungeon-Ort umsehen und Vorbereitung darstellen. Kein Instanzeintritt. |
|
||||
| `adventure_comment` | Selten einem tatsächlich anwesenden freundlichen Gegenüber eine Entdeckung kommentieren. |
|
||||
|
||||
Bestehende Fähigkeiten liefern Gespräche mit freundlichen NPCs, native
|
||||
Sitzplätze, Essen, Trinken und Feuerrast. Nach einem Erkundungsweg erhalten
|
||||
verfügbare Rastaktionen bei der folgenden Auswahl mehr Gewicht. Die
|
||||
bestehenden Verbote für neue Feuer in Gebäuden und Städten gelten weiter.
|
||||
|
||||
## Ausführung und Grenzen
|
||||
|
||||
Die Fußwege verwenden den bereits für Spaziergänge geprüften lokalen
|
||||
Routenplaner und Bewegungsexecutor: genau einen vollständigen MMAP-Korridor
|
||||
wählen, Kontrollpunkte folgen, am Wendepunkt pausieren und dieselben Punkte
|
||||
zurückverfolgen. Es gibt keine zufälligen einzelnen Nahziele und keine neuen
|
||||
Reit-/Flugtests. Der Standard der alten winzigen Zufallsbewegung `explore`
|
||||
wird nur für Abenteuer deaktiviert; angepasste Gewichte und ihre Verwendungen
|
||||
bei anderen Intents bleiben erhalten.
|
||||
|
||||
Wegpunkte bleiben innerhalb des Aufenthaltsgebiets beziehungsweise der Zone.
|
||||
Es gelten native vollständige Pfade, plausible Bodenhöhen und der begrenzte
|
||||
Aufenthaltsradius. Zeitende veranlasst einen Rückweg entlang bereits erreichter
|
||||
Punkte. Fehlgeschlagene Ankünfte werden niemals als Erfolg ausgegeben.
|
||||
|
||||
Objekte werden im tatsächlich geladenen Umfeld gesucht (60 Yards), nicht aus
|
||||
festen Objekt-IDs oder durch erzeugte Test-Spawns. Sichtbare generische Props,
|
||||
Schilder, Bücher und Goober-Objekte sind zulässig. Kisten/Ressourcen, Fallen,
|
||||
Türen, Knöpfe, Transportmittel und Möbel werden hierfür nicht gewählt.
|
||||
Spawnzustand, Phase, Sichtbarkeit, Sichtlinie und erreichbarer Gesprächs-/
|
||||
Betrachtungspunkt werden geprüft. Ein nicht erreichbares Objekt wird durch
|
||||
einen weiteren echten Kandidaten ersetzt; gibt es keinen, startet die Szene
|
||||
nicht. Verschwundene oder nicht mehr sichtbare Ziele beenden den Ablauf.
|
||||
|
||||
Diese Fähigkeit ruft **keine Objektbenutzung, keine Beuteerzeugung und keine
|
||||
Quest-/Gegenstandsinteraktion** auf. Die verwendeten Gesten erzeugen weder
|
||||
Objekte noch Zauberwirkungen. Ausrüstungsprüfung ist eine Darstellung.
|
||||
|
||||
Umsehen verwendet zwei feste Blickrichtungen relativ zur Startausrichtung,
|
||||
statt den Bot bei jedem Planungsschritt weiterzudrehen. Vorbereitung wird
|
||||
über die vorhandene Kategorie des Aufenthaltsorts freigegeben; eine genaue
|
||||
geometrische Erkennung einzelner Höhleneingänge ist nicht enthalten.
|
||||
Aussichtsszenen garantieren keine besondere Landschaftsqualität. Objekte,
|
||||
die nur Teil von WMO-/Karten-Geometrie sind, haben keine separate GO-GUID;
|
||||
sie werden durch ortsbezogenes Umsehen statt Objektinteraktion dargestellt.
|
||||
Kampf unterbricht die Tätigkeit über die bestehende Sicherheitsbehandlung.
|
||||
|
||||
## Location-Zuordnung
|
||||
|
||||
Die editierbaren `vcore_adventure_location_intent`-Einträge sind maßgeblich.
|
||||
Der bisherige Wirtschaften-Fallback im Code wird in ausdrückliche bestehende
|
||||
Kategorie-Zuordnungen überführt. Bearbeitete Gewichte einschließlich Null
|
||||
werden erhalten. Neue Kategorien benötigen ihre eigene Zuordnung. Tavernen
|
||||
erhalten eine geringe Freizeitgewichtung; Sitzaktionen sind weiterhin nur
|
||||
bei einer tatsächlich geeigneten erreichbaren Sitzgelegenheit verfügbar.
|
||||
Der Tagesplan wählt Intents weiterhin unabhängig vom vorhandenen Ortskatalog.
|
||||
|
||||
## Prüfung
|
||||
|
||||
Automatisierte Tests führen produktive Objektfilter, Verfügbarkeitsprüfungen
|
||||
und Gestensequenzen aus: Ankunft vor Gesten, verschwundene/unsichtbare Ziele,
|
||||
keine Objektbenutzung, zwei feste Blickrichtungen sowie korrekte Wiederverwendung
|
||||
der Bodenrouten. Der SQL-Test prüft Referenzen, ausdrückliche Kategoriezuordnung,
|
||||
Default-Upgrade und Erhalt bearbeiteter Gewichte bei Wiederholung.
|
||||
Eine erfolgreiche Kompilierung ersetzt die visuelle Ingame-Abnahme nicht.
|
||||
|
||||
## Technische Live-Prüfung am 27.10.2026
|
||||
|
||||
Build mit `-j10`, Installation und frischer Testserver-Neustart mit Ready-
|
||||
Meldung und Port 8085 erfolgreich. Alle 32 Clientless-Testskripte bestanden.
|
||||
Die temporäre Login-Vorgabe wurde nach dem Laden exakt zurückgesetzt.
|
||||
|
||||
Am gewöhnlichen importierten Sturmwind-Ort `poi_tele_954` wurden geprüft:
|
||||
|
||||
- Automatisch ausgewählte Untersuchung des tatsächlichen Apothekenschilds
|
||||
`Pestle's Apothecary` (GO 197117), native Ankunft und alle Betrachtungsgesten.
|
||||
- Detaillierte Untersuchung des Schilds `Weller's Arsenal` (GO 197121),
|
||||
native Ankunft sowie Blick-, Frage-, Zeige- und Wartephase. Ein anfangs
|
||||
manuell unterbrochener Durchlauf zählt nicht als Abschluss; der danach
|
||||
neu gestartete Durchlauf endete nach sämtlichen Gesten regulär.
|
||||
- Zusammenhängender Erkundungsweg: Ursprung `(-8802.90, 628.57, 94.46)`,
|
||||
Wendepunkt `(-8843.31, 559.53, 95.62)`, Abstand 80,01 Yards. Alle zehn
|
||||
Hin-/Rückwegankünfte und die tatsächliche Rückkehr wurden bestätigt.
|
||||
- Danach automatisch ausgewählte Trinkpause und Ausschauhalten.
|
||||
|
||||
Das ist eine technische Live-Prüfung in Sturmwind. Eine visuelle Abnahme
|
||||
durch den Nutzer, Erkundung in gefährlichen offenen Gebieten und die
|
||||
Vorbereitung an einem tatsächlichen Höhlen-/Dungeonort stehen noch aus.
|
||||
@@ -0,0 +1,305 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Ödland: Anleger ↔ Klippe, Trigger 6321/6322
|
||||
|
||||
Stand 26.10.2026. Laut Nutzer soll der Anleger ein erreichbares Bot-Reiseziel
|
||||
sein; diese Verbindung ist dafür wichtig. Beide gleichkartigen Übergänge sind
|
||||
im lokalen Testgraph aktiviert. Native Trigger und Ziele bleiben unverändert.
|
||||
|
||||
## Native Daten und Import
|
||||
|
||||
Beide Trigger liegen auf Karte 0, haben Radius 1.78776 und keine DBC-
|
||||
Phasenflags. Die lokale DB enthält keine eigenen AreaTrigger-Skripte und
|
||||
keine direkten Questzuordnungen über `areatrigger_involvedrelation` für diese
|
||||
IDs; in den untersuchten Core-/Skriptdateien gibt es keine Sonderbehandlung
|
||||
der IDs. Das ist keine pauschale Aussage über jede denkbare Zugangsbedingung.
|
||||
|
||||
Reproduktion über die Testserver-Konsole:
|
||||
|
||||
```text
|
||||
clientless portal import 6321
|
||||
clientless portal import 6322
|
||||
```
|
||||
|
||||
Der Import legt vier Nodes und zwei gerichtete Kanten an und lädt den Graph
|
||||
neu. Keine Höhenkalibrierung oder zusätzliche Migration erforderlich.
|
||||
|
||||
| Node | X | Y | Z | Funktion |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| portal_at_6321_source | -6518.680 | -4604.420 | 29.2335 | Anleger, hinauf |
|
||||
| portal_at_6321_target | -6547.880 | -4443.240 | 332.079 | Ankunft an der Klippe |
|
||||
| portal_at_6322_source | -6551.280 | -4446.460 | 332.829 | Klippe, hinunter |
|
||||
| portal_at_6322_target | -6519.820 | -4608.520 | 28.4842 | Ankunft am Anleger |
|
||||
|
||||
Portal-Kanten 1750 (6321_source → 6321_target) und 1751
|
||||
(6322_source → 6322_target), Kosten jeweils 1, unidirektional.
|
||||
|
||||
## Live-Test
|
||||
|
||||
Arthoran wurde nach Sicherung seiner Ausgangsdaten ausgeloggt am unteren
|
||||
Source-Node positioniert. Danach reguläre Reiseaufträge ohne weitere
|
||||
Positionsmanipulation während der Fahrt:
|
||||
|
||||
- 12:05:54: Trigger 6321, Anleger → Klippe, `EDGE_COMPLETE`,
|
||||
`arrivalError=0.00`, `recovery=0`.
|
||||
- Oben vollständig validierte MMAP-Brücke vom Ankunftspunkt zum Rücktrigger:
|
||||
4.75 Yards Pfadlänge, tatsächliche Bewegung, ohne Recovery.
|
||||
- 12:05:55: Trigger 6322, Klippe → Anleger, `EDGE_COMPLETE`,
|
||||
`arrivalError=0.00`, `recovery=0`.
|
||||
|
||||
Der zweite erfolgreiche Umlauf (12:06:18–12:06:19) ab der natürlichen unteren
|
||||
Ankunft bestätigte außerdem den Anlauf von `portal_at_6322_target` zu
|
||||
`portal_at_6321_source`. Alle vier Portalabschlüsse hatten Ankunftsfehler 0
|
||||
und Recovery 0. Arthoran wurde anschließend ausgeloggt; Ausgangsposition, Zone
|
||||
und Lua-Skript wurden wiederhergestellt.
|
||||
Die Portalreisen verwenden den normalen AreaTrigger-Handler mit
|
||||
Clientless-Near-ACK und Zielprüfung.
|
||||
|
||||
Es wurden keine Groundanschlüsse an das übrige Ödlandnetz aufgenommen oder
|
||||
getestet. Keine Coreänderung, kein Build und kein Serverneustart erforderlich.
|
||||
Finale Ingame-Abnahme durch den Nutzer steht aus.
|
||||
Sicherungen und Logs: `/tmp/vcore-badlands-test.0lkimsmi`.
|
||||
@@ -0,0 +1,60 @@
|
||||
TrinityCore rev. e18a416bf445+ 2026-10-27 20:10:13 +0100 (feature/clientless-player-core branch) (Unix, Debug, Static) (worldserver-daemon) ready...
|
||||
COMBAT_START guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' training=1 defending=0 until=1793138792
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0x000000000000001a Type: Player Low: 26' spell=6673
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=1464
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=1464
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=1464
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=1464
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=1464
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=1464
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' spell=78
|
||||
COMBAT_END guid=26 target='GUID Full: 0xf1307f9a0000050b Type: Creature Entry: 32666 Low: 1291' training=1
|
||||
COMBAT_START guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' training=0 defending=0 until=0
|
||||
COMBAT_END guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' training=0
|
||||
COMBAT_START guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' training=0 defending=1 until=0
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' spell=772
|
||||
COMBAT_END guid=26 target='GUID Full: 0xf130a56000000b17 Type: Creature Entry: 42336 Low: 2839' training=0
|
||||
DEATH_TEST_REQUEST guid=26
|
||||
DEATH_RELEASE guid=26
|
||||
DEATH_CEMETERY_REVIVE guid=26
|
||||
COMBAT_START guid=26 target='GUID Full: 0xf130b03f00000ae8 Type: Creature Entry: 45119 Low: 2792' training=0 defending=1 until=0
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0x000000000000001a Type: Player Low: 26' spell=6673
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae8 Type: Creature Entry: 45119 Low: 2792' spell=78
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae8 Type: Creature Entry: 45119 Low: 2792' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae8 Type: Creature Entry: 45119 Low: 2792' spell=7384
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae8 Type: Creature Entry: 45119 Low: 2792' spell=12294
|
||||
COMBAT_END guid=26 target='GUID Full: 0xf130b03f00000ae8 Type: Creature Entry: 45119 Low: 2792' training=0
|
||||
COMBAT_START guid=26 target='GUID Full: 0xf130b03f00000ae7 Type: Creature Entry: 45119 Low: 2791' training=0 defending=1 until=0
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae7 Type: Creature Entry: 45119 Low: 2791' spell=12294
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae7 Type: Creature Entry: 45119 Low: 2791' spell=772
|
||||
COMBAT_CAST guid=26 target='GUID Full: 0xf130b03f00000ae7 Type: Creature Entry: 45119 Low: 2791' spell=7384
|
||||
COMBAT_END guid=26 target='GUID Full: 0xf130b03f00000ae7 Type: Creature Entry: 45119 Low: 2791' training=0
|
||||
DEATH_TEST_REQUEST guid=26
|
||||
DEATH_RELEASE guid=26
|
||||
DEATH_CORPSE_RUN guid=26 path=37.40
|
||||
DEATH_RECLAIM guid=26
|
||||
@@ -0,0 +1,16 @@
|
||||
2026-10-27_23:05:32 INFO [server.adventurebot.navigation] NAV_PLAN seq=1 guid=26 name='Arthoran' map=0 segment=0 start=(-8744.788 319.742 100.549) target=(-8745.762 312.810 100.206) type=0x1 calculated=1 complete=1 suspicious=0 points=3 direct=7.01 path=7.02 maxSegment=4.00 maxZDelta=0.31 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_23:05:32 INFO [server.adventurebot.navigation] NAV_EXEC seq=1 guid=26 name='Arthoran' segment=1 splinePoints=3 splineLength=7.07 segmentEnd=(-8745.762 312.810 100.206) target=(-8745.762 312.810 100.206) walk=0
|
||||
2026-10-27_23:05:32 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8745.762 312.810 100.206) remaining=5.51 state=Moving
|
||||
2026-10-27_23:05:33 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=1 guid=26 segment=1 pos=(-8745.745 312.927 100.193) remaining=0.00 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_23:06:54 INFO [server.adventurebot.navigation] NAV_PLAN seq=2 guid=26 name='Arthoran' map=0 segment=0 start=(-11831.100 -2510.480 -20.070) target=(-11841.850 -2510.480 -20.025) type=0x1 calculated=1 complete=1 suspicious=0 points=4 direct=10.75 path=10.79 maxSegment=4.03 maxZDelta=0.46 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_23:06:54 INFO [server.adventurebot.navigation] NAV_EXEC seq=2 guid=26 name='Arthoran' segment=1 splinePoints=4 splineLength=10.85 segmentEnd=(-11841.850 -2510.480 -20.025) target=(-11841.850 -2510.480 -20.025) walk=0
|
||||
2026-10-27_23:06:54 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-11841.850 -2510.480 -20.025) remaining=9.25 state=Moving
|
||||
2026-10-27_23:06:55 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=2 guid=26 segment=1 pos=(-11838.028 -2510.480 -19.686) remaining=2.34 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_23:13:16 INFO [server.adventurebot.navigation] NAV_PLAN seq=3 guid=26 name='Arthoran' map=0 segment=0 start=(-12186.000 -2566.580 3.966) target=(-12187.900 -2603.740 1.578) type=0x1 calculated=1 complete=1 suspicious=0 points=11 direct=37.29 path=37.40 maxSegment=4.06 maxZDelta=0.68 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_23:13:16 INFO [server.adventurebot.navigation] NAV_EXEC seq=3 guid=26 name='Arthoran' segment=1 splinePoints=11 splineLength=37.40 segmentEnd=(-12187.900 -2603.740 1.578) target=(-12187.900 -2603.740 1.578) walk=0
|
||||
2026-10-27_23:13:16 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-12187.900 -2603.740 1.578) remaining=35.79 state=Moving
|
||||
2026-10-27_23:13:17 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=3 guid=26 segment=1 pos=(-12186.536 -2577.073 3.698) remaining=25.29 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_23:13:18 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=3 guid=26 segment=1 pos=(-12187.064 -2587.424 2.146) remaining=14.85 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_23:13:19 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=3 guid=26 segment=1 pos=(-12187.603 -2597.920 1.355) remaining=4.33 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_23:13:20 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=3 guid=26 segment=1 pos=(-12187.900 -2603.740 1.578) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_23:13:20 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=3 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
@@ -0,0 +1,8 @@
|
||||
Final Debug build -j10 and installation succeeded.
|
||||
51 tests/clientless/test_*.py scripts passed.
|
||||
Live native training: 60 seconds, valid real dummy, normal MMAP approach and regular end.
|
||||
Real combat: spawn300425 entry42336 level58; native hostile/LOS/phase/strength/path checks; creature killed with native respawn record.
|
||||
Death fixture1: explicit native testdeath, normal release at1793138872; no acceptable MMAP route; no accelerated clock; cemetery resurrection after1793139172 without sickness.
|
||||
Death fixture2: explicit native testdeath at nearby native ground point; ghost path37.40 yards; native reclaim; saved aliveHP4340, no corpse or sickness.
|
||||
Administrative offline positioning used for isolated tests, not evidence of long-distance travel.
|
||||
Native restarts during a ghost run and multi-attacker focus were exercised by production adapter tests, not live multi-actor gameplay.
|
||||
@@ -0,0 +1,339 @@
|
||||
# Vcore Development Environment
|
||||
|
||||
## Project
|
||||
|
||||
Vcore is a custom World of Warcraft Cataclysm 4.3.4 server based on TrinityCore.
|
||||
|
||||
This environment is a dedicated development and test server.
|
||||
|
||||
The current development focus is the Clientless Player Core and AdventureBot infrastructure.
|
||||
|
||||
## Repository and Git Rules
|
||||
|
||||
Repository:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/source/TrinityCore`
|
||||
|
||||
Authorized development branch:
|
||||
|
||||
`feature/clientless-player-core`
|
||||
|
||||
Rules:
|
||||
|
||||
- Work exclusively on the authorized development branch.
|
||||
- Never switch to, modify, reset, rebase, or merge `master`.
|
||||
- Never push to `master`.
|
||||
- Never push any branch without explicit user approval.
|
||||
- Local commits are permitted.
|
||||
- Never discard existing changes without approval.
|
||||
- Never force-push.
|
||||
- Check the current branch and working tree before making changes.
|
||||
- Stop and request clarification if the working tree contains unexpected changes.
|
||||
|
||||
## Development Permissions
|
||||
|
||||
Codex is authorized to:
|
||||
|
||||
- Read and modify Vcore source code.
|
||||
- Implement new features and fix bugs.
|
||||
- Run CMake and compile Vcore.
|
||||
- Investigate and resolve compilation errors.
|
||||
- Install compiled binaries into the testserver installation.
|
||||
- Start, stop, and restart the test worldserver.
|
||||
- Inspect logs and server output.
|
||||
- Modify test databases when required for an authorized task.
|
||||
- Execute local tests and create local commits.
|
||||
|
||||
Codex must never:
|
||||
|
||||
- Modify the production server.
|
||||
- Deploy changes to production.
|
||||
- Push changes without explicit approval.
|
||||
- Modify or merge the protected `master` branch.
|
||||
- Discard user changes without approval.
|
||||
|
||||
## Read-only Diagnostics
|
||||
|
||||
- Reading the development/test server logs and project files is already authorized.
|
||||
- Use direct read-only commands such as `rg`, `tail`, `sed`, `cat`, and `stat` inside the sandbox for ordinary file inspection. Do not request elevated execution preemptively for these reads.
|
||||
- Keep file inspection separate from tmux access, database queries, writes, and lifecycle actions so those actions do not unnecessarily escalate log reading.
|
||||
- Do not request blanket approval for Python, other interpreters, or shell execution to read logs.
|
||||
- If a read actually fails because of a technical sandbox restriction, follow the execution environment's escalation rules and request only the narrow access needed. Project authorization does not override the sandbox.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
Source:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/source/TrinityCore`
|
||||
|
||||
Build directory:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/build/debug`
|
||||
|
||||
Server installation:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/server/debug`
|
||||
|
||||
Worldserver executable:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/server/debug/bin/worldserver`
|
||||
|
||||
## Build and Installation
|
||||
|
||||
Use the existing CMake build configuration.
|
||||
|
||||
Inspect the build configuration before changing it.
|
||||
|
||||
Build directory:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/build/debug`
|
||||
|
||||
Install directory:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/server/debug`
|
||||
|
||||
After successful compilation, install the resulting binaries using the existing CMake installation configuration.
|
||||
|
||||
Do not overwrite running executables.
|
||||
|
||||
Stop the test worldserver cleanly before installing updated binaries.
|
||||
|
||||
Do not delete existing server configuration, logs, databases, or data files.
|
||||
|
||||
## Worldserver Management
|
||||
|
||||
The test worldserver runs inside a dedicated tmux session.
|
||||
|
||||
Session name:
|
||||
|
||||
`vcore-worldserver`
|
||||
|
||||
Working directory:
|
||||
|
||||
`/home/wow_admin/wow_cata_server/server/debug/bin`
|
||||
|
||||
Executable:
|
||||
|
||||
`./worldserver`
|
||||
|
||||
Codex is authorized to start, stop, restart, and recover the test worldserver autonomously.
|
||||
|
||||
### Starting the Worldserver
|
||||
|
||||
Before starting:
|
||||
|
||||
1. Check whether a worldserver instance is already running.
|
||||
2. Check whether the `vcore-worldserver` tmux session already exists.
|
||||
3. Never start a second worldserver instance while another instance is active.
|
||||
4. Remove stale tmux sessions only after verifying their state.
|
||||
|
||||
Start command:
|
||||
|
||||
```bash
|
||||
tmux new-session -d -s vcore-worldserver \
|
||||
-c /home/wow_admin/wow_cata_server/server/debug/bin \
|
||||
'./worldserver'
|
||||
```
|
||||
|
||||
### Startup Verification
|
||||
|
||||
A successfully created tmux session does not indicate successful worldserver startup.
|
||||
|
||||
The Vcore worldserver reports successful initialization with a final console message similar to:
|
||||
|
||||
```text
|
||||
World initialized in 0 minutes 10 seconds
|
||||
TrinityCore rev. <revision> (...) (worldserver-daemon) ready...
|
||||
```
|
||||
|
||||
The authoritative startup indicator is:
|
||||
|
||||
`(worldserver-daemon) ready...`
|
||||
|
||||
The revision, branch, build configuration, and initialization time may vary.
|
||||
|
||||
After starting the worldserver:
|
||||
|
||||
1. Monitor the worldserver process and console output.
|
||||
2. Wait for the `(worldserver-daemon) ready...` message.
|
||||
3. Verify that the worldserver process remains running.
|
||||
4. Check for critical startup errors.
|
||||
5. Verify that the configured worldserver port is listening.
|
||||
|
||||
Only report successful startup when these checks pass.
|
||||
|
||||
Capture console output from the beginning of the current startup attempt to avoid mistaking messages from an earlier run for current startup success.
|
||||
|
||||
If the worldserver exits, hangs, or fails to reach the ready state within a reasonable timeout, follow the startup failure recovery procedure.
|
||||
|
||||
|
||||
### Startup Failure Recovery
|
||||
|
||||
The test worldserver may occasionally fail to start because the remote authentication database on the VPS is temporarily unreachable.
|
||||
|
||||
When startup fails:
|
||||
|
||||
1. Capture relevant console output and logs.
|
||||
2. Determine whether the worldserver process is still running.
|
||||
3. Check whether the tmux session is still active.
|
||||
4. If the TrinityCore console is responsive, attempt a graceful shutdown.
|
||||
5. If the console is unavailable or unresponsive, terminate the failed worldserver process and its dedicated tmux session.
|
||||
6. Verify that the previous worldserver process has terminated.
|
||||
7. Ensure that no stale process remains before restarting.
|
||||
8. Wait briefly before retrying.
|
||||
9. Create a fresh tmux session and start the worldserver again.
|
||||
10. Repeat startup verification.
|
||||
|
||||
For startup recovery, Codex may terminate the dedicated test worldserver process and tmux session when graceful shutdown is impossible.
|
||||
|
||||
Do not terminate unrelated processes or tmux sessions.
|
||||
|
||||
### Retry Policy
|
||||
|
||||
Use a maximum of three startup attempts per restart operation.
|
||||
|
||||
Wait approximately 10 seconds between attempts.
|
||||
|
||||
If startup fails repeatedly:
|
||||
|
||||
- Stop retrying.
|
||||
- Preserve the relevant logs.
|
||||
- Report the observed errors.
|
||||
- Explain whether the failure appears related to database connectivity, configuration, compilation, or another cause.
|
||||
- Do not claim that the testserver is operational.
|
||||
|
||||
Do not attempt to repair the remote VPS authentication database or production infrastructure.
|
||||
|
||||
### TrinityCore Console Commands
|
||||
|
||||
Codex may execute TrinityCore console commands through tmux.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
tmux send-keys -t vcore-worldserver '.server shutdown 10' Enter
|
||||
```
|
||||
|
||||
Read console output:
|
||||
|
||||
```bash
|
||||
tmux capture-pane -p -t vcore-worldserver -S -100
|
||||
```
|
||||
|
||||
### Graceful Shutdown
|
||||
|
||||
For a normally running worldserver, use:
|
||||
|
||||
`.server shutdown 10`
|
||||
|
||||
Send the command through tmux:
|
||||
|
||||
```bash
|
||||
tmux send-keys -t vcore-worldserver '.server shutdown 10' Enter
|
||||
```
|
||||
|
||||
After issuing the command:
|
||||
|
||||
1. Wait for the worldserver to terminate.
|
||||
2. Verify that the process has stopped.
|
||||
3. Verify that the tmux session has ended.
|
||||
4. Only then install new binaries or start another worldserver instance.
|
||||
|
||||
If the console is unresponsive, Codex may terminate the dedicated test worldserver process.
|
||||
|
||||
Prefer SIGTERM before SIGKILL.
|
||||
|
||||
Use SIGKILL only when the process cannot be stopped normally.
|
||||
|
||||
### Restart Procedure
|
||||
|
||||
1. Verify the current worldserver state.
|
||||
2. If running normally, initiate graceful shutdown.
|
||||
3. If the console is unavailable, use the recovery shutdown procedure.
|
||||
4. Wait for complete process termination.
|
||||
5. Install successfully compiled binaries if required.
|
||||
6. Start a fresh tmux session.
|
||||
7. Verify successful worldserver initialization.
|
||||
8. If startup fails, follow the startup recovery procedure.
|
||||
9. Report the final server state.
|
||||
|
||||
### Safety
|
||||
|
||||
This is a dedicated development and test environment.
|
||||
|
||||
Codex is authorized to manage the test worldserver autonomously, including recovery from failed startup attempts.
|
||||
|
||||
Never terminate unrelated services or processes.
|
||||
|
||||
Never execute worldserver management commands on production infrastructure.
|
||||
|
||||
## AdventureBot Architecture
|
||||
|
||||
Preserve the existing Clientless Player Core architecture.
|
||||
|
||||
Important components include:
|
||||
|
||||
- ClientlessTravelMgr
|
||||
- ClientlessTravelGraphMgr
|
||||
- ClientlessActionExecutorMgr
|
||||
- Lua-based bot control
|
||||
- MMAP navigation
|
||||
- TravelGraph routing
|
||||
|
||||
Architecture principles:
|
||||
|
||||
- Clientless Player Core provides generic clientless player functionality.
|
||||
- AdventureBots are built on top of this infrastructure.
|
||||
- TravelGraph handles long-distance travel.
|
||||
- MMAP navigation handles local movement.
|
||||
- DungeonBots remain independent from AdventureBots.
|
||||
- AdventureBots must not become infrastructure dependencies for unrelated game systems.
|
||||
|
||||
Prefer extending the existing implementation over replacing it.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
For each development task:
|
||||
|
||||
1. Verify the current Git branch and working tree.
|
||||
2. Inspect the relevant existing implementation.
|
||||
3. Plan nontrivial changes before implementation.
|
||||
4. Implement the requested functionality.
|
||||
5. Compile the affected components.
|
||||
6. Resolve compilation errors.
|
||||
7. Install the new build when appropriate.
|
||||
8. Restart the test worldserver when necessary.
|
||||
9. Inspect logs and available test results.
|
||||
10. Report what changed, what was tested, and what remains unverified.
|
||||
11. Wait for user feedback before pushing changes.
|
||||
|
||||
Do not claim that gameplay functionality is verified solely because compilation succeeded.
|
||||
|
||||
The user performs final in-game acceptance testing.
|
||||
|
||||
## Rollback
|
||||
|
||||
When requested, restore the previous implementation without modifying `master`.
|
||||
|
||||
Prefer targeted reversions of the relevant development changes.
|
||||
|
||||
Never use destructive Git commands without checking whether unrelated work would be lost.
|
||||
|
||||
Database rollbacks must be limited to the changes associated with the development task.
|
||||
|
||||
## General Principles
|
||||
|
||||
- Preserve existing Vcore functionality.
|
||||
- Avoid unnecessary architectural rewrites.
|
||||
- Prefer targeted, maintainable changes.
|
||||
- Investigate root causes instead of masking symptoms.
|
||||
- Keep the test environment reproducible.
|
||||
- Clearly distinguish successful builds, automated tests, and verified gameplay behavior.
|
||||
|
||||
|
||||
## Saved session / Wiederaufnahme
|
||||
|
||||
Before starting new work, read `doc/clientless/SESSION-RESUME.md`. It records the
|
||||
user-requested checkpoint, unfinished profession intent, agreed Lua professions,
|
||||
build/test state and exact next steps. Preserve the saved WIP; do not restart or
|
||||
revert it. All development/server/branch rules above remain in force.
|
||||
@@ -0,0 +1,14 @@
|
||||
TrinityCore rev. 722b513ee01b+ 2026-10-27 17:02:01 +0100 (feature/clientless-player-core branch) (Unix, Debug, Static) (worldserver-daemon) ready...
|
||||
PROFILE_PROFESSIONS guid=26 primary=2
|
||||
ClientlessLua[26]: Arthoran ready; no automatic test journey queued
|
||||
INTENT_TRAVEL guid=26 intent='profession' location='poi_tele_338' area=1
|
||||
INTENT_ARRIVED guid=26 intent='profession' location='poi_tele_338'
|
||||
PROFESSION_WORK_COMPLETE guid=26 kind='profession_tools' target=''
|
||||
LEISURE_WALK_PLAN guid=26 kind='work_search' span=103.64 outbound=6 origin=(-8888.98 -0.54 94.39) goal=(-8978.85 -52.09 91.55)
|
||||
LEISURE_WAYPOINT guid=26 kind='work_search' reached=1/6
|
||||
LEISURE_WAYPOINT guid=26 kind='work_search' reached=2/6
|
||||
LEISURE_WAYPOINT guid=26 kind='work_search' reached=3/6
|
||||
LEISURE_WAYPOINT guid=26 kind='work_search' reached=4/6
|
||||
LEISURE_WAYPOINT guid=26 kind='work_search' reached=5/6
|
||||
LEISURE_WAYPOINT guid=26 kind='work_search' reached=6/6
|
||||
LEISURE_COMPLETE guid=26 kind='work_search' legs=6
|
||||
@@ -0,0 +1,44 @@
|
||||
from pathlib import Path
|
||||
import os,re,subprocess,sys
|
||||
config=Path('/home/wow_admin/wow_cata_server/server/debug/etc/worldserver.conf').read_text()
|
||||
h,port,u,password,db=re.search(r'^WorldDatabaseInfo\s*=\s*"([^"]+)"',config,re.M).group(1).split(';')
|
||||
args=['mysql','--protocol=TCP','--host='+h,'--port='+port,'--user='+u,'--database='+db,'--batch','--default-character-set=utf8mb4','--connect-timeout=10']
|
||||
env=os.environ.copy();env['MYSQL_PWD']=password
|
||||
op=sys.argv[1] if len(sys.argv)>1 else ''
|
||||
if op=='state':
|
||||
h,port,u,password,db=re.search(r'^CharacterDatabaseInfo\s*=\s*"([^"]+)"',config,re.M).group(1).split(';')
|
||||
args=['mysql','--protocol=TCP','--host='+h,'--port='+port,'--user='+u,'--database='+db,'--batch','--default-character-set=utf8mb4','--connect-timeout=10']
|
||||
env['MYSQL_PWD']=password
|
||||
if op=='state':
|
||||
query="SELECT guid,money FROM characters WHERE guid=26; SELECT item,bag,slot FROM character_inventory WHERE guid=26 ORDER BY bag,slot,item; SELECT guid,itemEntry,count FROM item_instance WHERE owner_guid=26 ORDER BY guid;"
|
||||
elif op=='workstation_inspect':
|
||||
query="""SELECT data0 AS focus_id,COUNT(*) AS n,LEFT(GROUP_CONCAT(DISTINCT name ORDER BY name SEPARATOR ', '),600) AS examples FROM gameobject_template WHERE type=8 GROUP BY data0 ORDER BY data0; SELECT entry,name,type,data0 FROM gameobject_template WHERE name REGEXP 'Alchemy|Alchemist|Workbench|Loom|Tanning|Sewing|Enchanter|Runeforge|Cooking Fire|Campfire' AND type IN (5,8,10) ORDER BY entry LIMIT 65; SHOW CREATE TABLE npc_trainer; SHOW CREATE TABLE trainer; SHOW CREATE TABLE creature_trainer;"""
|
||||
elif op=='profession_inspect':
|
||||
query="""SELECT t.entry,t.name,t.type,t.data0,t.data1 FROM gameobject_template t WHERE (t.type=8 AND (t.name REGEXP 'Anvil|Forge|Alchemy|Loom|Workbench|Enchant|Tanning|Cooking')) OR (t.type=3 AND t.name IN ('Copper Vein','Silverleaf','Peacebloom')) ORDER BY t.type,t.data0,t.entry LIMIT 90; SELECT w.point_key,a.display_name,w.category,w.map,w.position_x,w.position_y,w.position_z,a.is_area,a.area_id,a.zone_id FROM vcore_clientless_world_point w JOIN vcore_adventure_location a USING(point_key) WHERE w.enabled=1 AND (a.is_area=1 AND a.zone_id=12 OR w.category='workshop' AND a.zone_id=1519) ORDER BY w.point_key LIMIT 25;"""
|
||||
elif op=='exploration_inspect':
|
||||
query="""SELECT g.guid,g.id,t.name,t.type,g.position_x,g.position_y,g.position_z FROM gameobject g JOIN gameobject_template t ON t.entry=g.id WHERE g.map=0 AND g.position_x BETWEEN -9000 AND -8750 AND g.position_y BETWEEN 500 AND 750 AND t.type IN (5,9,10) ORDER BY g.id; SELECT w.point_key,a.display_name,w.category,w.map,w.position_x,w.position_y,w.position_z FROM vcore_clientless_world_point w JOIN vcore_adventure_location a USING(point_key) WHERE w.enabled=1 AND w.map=0 AND (a.display_name LIKE '%Northshire%' OR a.display_name LIKE '%Goldshire%' OR a.display_name LIKE '%Stonecairn%') ORDER BY a.display_name;"""
|
||||
elif op=='exploration_apply':
|
||||
query='START TRANSACTION;\n'+Path('/home/wow_admin/wow_cata_server/source/TrinityCore/sql/custom/world/2026_10_27_04_adventure_exploration.sql').read_text()+"\nSELECT a.action_key,a.kind,a.requirement,i.weight FROM vcore_adventure_action a JOIN vcore_adventure_action_intent i USING(action_key) WHERE a.action_key LIKE 'adventure_%' OR (a.action_key='explore' AND i.intent='adventure'); COMMIT;"
|
||||
elif op=='catalog':
|
||||
query="""SELECT w.point_key,w.category,w.map,w.position_x,w.position_y,w.position_z,w.orientation,w.enabled,COALESCE(w.comment,''),a.display_name,a.source_type,a.source_id,a.area_id,a.zone_id,a.region_key,a.is_area,a.faction FROM vcore_clientless_world_point w JOIN vcore_adventure_location a USING(point_key) ORDER BY w.point_key;"""
|
||||
elif op=='source_audit':
|
||||
query="""SELECT id,name,map,position_x,position_y,position_z FROM game_tele WHERE name IN ('Orgrimmar','ThunderBluff','Thunder Bluff','Undercity','SilvermoonCity','Darnassus','TheExodar','Ironforge','Stormwind'); SHOW COLUMNS FROM game_tele; SHOW COLUMNS FROM creature; SELECT c.id,t.name,c.map,c.position_x,c.position_y,c.position_z,COALESCE(NULLIF(c.npcflag,0),t.npcflag) AS flags,t.faction FROM creature c JOIN creature_template t ON t.entry=c.id WHERE t.name IN ('Innkeeper Gryshka','Innkeeper Pala','Innkeeper Allison','Auctioneer Thathung','Auctioneer Chilton') ORDER BY c.map,c.id;"""
|
||||
elif op=='audit':
|
||||
query="""SELECT COUNT(*) AS active_locations FROM vcore_clientless_world_point w JOIN vcore_adventure_location a USING(point_key) WHERE w.enabled=1 AND w.category NOT LIKE 'travel%'; SELECT a.source_type,w.category,a.faction,COUNT(*) AS n FROM vcore_adventure_location a JOIN vcore_clientless_world_point w USING(point_key) WHERE w.enabled=1 GROUP BY a.source_type,w.category,a.faction ORDER BY n DESC; SELECT w.point_key,a.display_name,w.category,a.region_key,a.area_id,a.zone_id,a.is_area,a.faction,w.map,w.position_x,w.position_y,w.position_z FROM vcore_adventure_location a JOIN vcore_clientless_world_point w USING(point_key) WHERE w.enabled=1 AND (a.display_name REGEXP 'Orgrimmar|Thunder Bluff|Undercity|Silvermoon|Darnassus|Exodar|Ironforge|Stormwind' OR (a.is_area=1 AND a.zone_id IN (1519,1637,1638,1497,1537,1657,3430,3487,3557))) ORDER BY a.is_area DESC,a.zone_id,w.point_key;"""
|
||||
elif op=='inspect':
|
||||
query="""SELECT c.guid,c.id,t.name,t.npcflag,c.position_x,c.position_y,c.position_z,c.orientation FROM creature c JOIN creature_template t ON t.entry=c.id WHERE c.map=0 AND c.position_x BETWEEN -9000 AND -8750 AND c.position_y BETWEEN 450 AND 850 AND (t.npcflag & (128|131072|2097152))<>0 ORDER BY c.id,c.guid; SHOW CREATE TABLE vcore_adventure_location; SHOW CREATE TABLE vcore_clientless_world_point; SELECT category,intent,weight FROM vcore_adventure_location_intent ORDER BY category,intent;"""
|
||||
elif op=='apply':
|
||||
query='START TRANSACTION;\n'+Path('/home/wow_admin/wow_cata_server/source/TrinityCore/sql/custom/world/2026_10_27_03_adventure_economy.sql').read_text()+"\nSELECT w.point_key,w.category,w.position_x,w.position_y,w.position_z FROM vcore_clientless_world_point w WHERE w.point_key LIKE 'stormwind_economy_%'; SELECT a.action_key,a.requirement,i.weight FROM vcore_adventure_action a JOIN vcore_adventure_action_intent i USING(action_key) WHERE i.intent='economy'; COMMIT;"
|
||||
else:raise SystemExit('inspect or apply only')
|
||||
r=subprocess.run(args,input=query,text=True,capture_output=True,env=env)
|
||||
if op=='catalog' and not r.returncode:
|
||||
import hashlib
|
||||
Path('/tmp/vcore-import-catalog-current.tsv').write_text(r.stdout)
|
||||
print('Catalog snapshot:',len(r.stdout.splitlines())-1,'records; SHA256',hashlib.sha256(r.stdout.encode()).hexdigest())
|
||||
elif op=='state' and not r.returncode:
|
||||
import hashlib
|
||||
snapshot=Path('/tmp/vcore-economy-state-current.txt');snapshot.write_text(r.stdout)
|
||||
print('Arthoran persisted money/inventory SHA256:',hashlib.sha256(r.stdout.encode()).hexdigest())
|
||||
else:print(r.stdout,end='')
|
||||
if r.stderr:print(r.stderr.replace(password,'[redacted]'),file=sys.stderr,end='')
|
||||
raise SystemExit(r.returncode)
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
2026-10-27_14:10:11 INFO [server.adventurebot.navigation] NAV_PLAN seq=4 guid=26 name='Arthoran' map=0 segment=0 start=(-8848.844 607.931 92.673) target=(-8864.850 595.939 92.645) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.00 path=20.00 maxSegment=4.00 maxZDelta=0.08 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:10:11 INFO [server.adventurebot.navigation] NAV_EXEC seq=4 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.00 segmentEnd=(-8864.850 595.939 92.645) target=(-8864.850 595.939 92.645) walk=1
|
||||
2026-10-27_14:10:11 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8864.850 595.939 92.645) remaining=18.50 state=Moving
|
||||
2026-10-27_14:10:12 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8850.817 606.453 92.631) remaining=16.03 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:13 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8852.901 604.891 92.583) remaining=13.43 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:14 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8854.906 603.389 92.532) remaining=10.93 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:15 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8856.899 601.895 92.520) remaining=8.43 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:16 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8858.903 600.394 92.525) remaining=5.93 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:17 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8860.908 598.892 92.562) remaining=3.43 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:18 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8862.903 597.398 92.603) remaining=0.93 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:19 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=4 guid=26 segment=1 pos=(-8864.850 595.939 92.645) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:10:19 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=4 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:10:19 INFO [server.adventurebot.navigation] NAV_PLAN seq=5 guid=26 name='Arthoran' map=0 segment=0 start=(-8864.850 595.939 92.645) target=(-8880.855 583.947 93.233) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.01 path=20.01 maxSegment=4.00 maxZDelta=0.16 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:10:19 INFO [server.adventurebot.navigation] NAV_EXEC seq=5 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.01 segmentEnd=(-8880.855 583.947 93.233) target=(-8880.855 583.947 93.233) walk=1
|
||||
2026-10-27_14:10:19 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8880.855 583.947 93.233) remaining=18.51 state=Moving
|
||||
2026-10-27_14:10:20 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8866.855 594.436 92.748) remaining=16.00 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:21 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8868.860 592.934 92.850) remaining=13.49 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:22 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8870.868 591.430 92.949) remaining=10.98 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:23 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8872.858 589.939 93.033) remaining=8.49 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:24 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8874.869 588.432 93.109) remaining=5.98 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:25 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8876.986 586.846 93.171) remaining=3.34 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:26 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8879.001 585.337 93.208) remaining=0.82 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:27 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=5 guid=26 segment=1 pos=(-8880.855 583.947 93.233) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:10:27 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=5 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:10:27 INFO [server.adventurebot.navigation] NAV_PLAN seq=6 guid=26 name='Arthoran' map=0 segment=0 start=(-8880.855 583.947 93.233) target=(-8896.861 571.956 93.007) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.00 path=20.01 maxSegment=4.01 maxZDelta=0.24 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:10:27 INFO [server.adventurebot.navigation] NAV_EXEC seq=6 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.01 segmentEnd=(-8896.861 571.956 93.007) target=(-8896.861 571.956 93.007) walk=1
|
||||
2026-10-27_14:10:27 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8896.861 571.956 93.007) remaining=18.50 state=Moving
|
||||
2026-10-27_14:10:28 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8882.869 582.439 93.283) remaining=15.99 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:29 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8884.861 580.946 93.305) remaining=13.50 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:30 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8886.878 579.435 93.286) remaining=10.98 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:31 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8888.862 577.948 93.161) remaining=8.50 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:32 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8890.875 576.440 93.029) remaining=5.98 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:33 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8892.880 574.939 92.978) remaining=3.47 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:34 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8894.883 573.438 92.976) remaining=0.97 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:35 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=6 guid=26 segment=1 pos=(-8896.861 571.956 93.007) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:10:35 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=6 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:10:35 INFO [server.adventurebot.navigation] NAV_PLAN seq=7 guid=26 name='Arthoran' map=0 segment=0 start=(-8896.861 571.956 93.007) target=(-8912.868 559.964 94.237) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.04 path=20.04 maxSegment=4.02 maxZDelta=0.35 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:10:35 INFO [server.adventurebot.navigation] NAV_EXEC seq=7 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.04 segmentEnd=(-8912.868 559.964 94.237) target=(-8912.868 559.964 94.237) walk=1
|
||||
2026-10-27_14:10:35 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8912.868 559.964 94.237) remaining=18.54 state=Moving
|
||||
2026-10-27_14:10:36 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8898.871 570.450 93.132) remaining=16.02 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:37 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8900.871 568.951 93.277) remaining=13.52 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:38 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8902.853 567.467 93.451) remaining=11.04 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:39 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8904.854 565.968 93.614) remaining=8.53 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:40 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8906.861 564.464 93.785) remaining=6.02 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:41 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8908.854 562.970 94.006) remaining=3.52 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:42 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8910.836 561.486 94.147) remaining=1.04 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:43 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8912.854 559.974 94.236) remaining=0.00 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:44 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=7 guid=26 segment=1 pos=(-8912.868 559.964 94.237) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:10:44 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=7 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:10:48 INFO [server.adventurebot.navigation] NAV_PLAN seq=8 guid=26 name='Arthoran' map=0 segment=0 start=(-8912.868 559.964 94.237) target=(-8896.861 571.956 93.007) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.04 path=20.04 maxSegment=4.02 maxZDelta=0.35 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:10:48 INFO [server.adventurebot.navigation] NAV_EXEC seq=8 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.04 segmentEnd=(-8896.861 571.956 93.007) target=(-8896.861 571.956 93.007) walk=1
|
||||
2026-10-27_14:10:48 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8896.861 571.956 93.007) remaining=18.54 state=Moving
|
||||
2026-10-27_14:10:49 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8910.871 561.460 94.149) remaining=16.04 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:50 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8908.852 562.973 94.006) remaining=13.52 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:51 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8906.845 564.476 93.783) remaining=11.00 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:52 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8904.964 565.885 93.622) remaining=8.64 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:53 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8902.808 567.501 93.447) remaining=5.94 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:54 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8900.805 569.002 93.271) remaining=3.43 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:55 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8898.807 570.499 93.128) remaining=0.93 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:56 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=8 guid=26 segment=1 pos=(-8896.861 571.956 93.007) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:10:56 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=8 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:10:56 INFO [server.adventurebot.navigation] NAV_PLAN seq=9 guid=26 name='Arthoran' map=0 segment=0 start=(-8896.861 571.956 93.007) target=(-8880.855 583.947 93.233) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.00 path=20.01 maxSegment=4.01 maxZDelta=0.24 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:10:56 INFO [server.adventurebot.navigation] NAV_EXEC seq=9 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.01 segmentEnd=(-8880.855 583.947 93.233) target=(-8880.855 583.947 93.233) walk=1
|
||||
2026-10-27_14:10:56 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8880.855 583.947 93.233) remaining=18.50 state=Moving
|
||||
2026-10-27_14:10:57 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8894.864 573.452 92.976) remaining=16.01 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:58 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8892.857 574.955 92.978) remaining=13.50 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:10:59 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8890.867 576.447 93.030) remaining=11.01 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:00 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8888.864 577.947 93.161) remaining=8.51 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:01 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8886.867 579.443 93.286) remaining=6.01 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:02 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8884.851 580.954 93.305) remaining=3.49 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:03 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8882.849 582.454 93.283) remaining=0.99 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:04 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=9 guid=26 segment=1 pos=(-8880.855 583.947 93.233) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:11:04 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=9 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:11:04 INFO [server.adventurebot.navigation] NAV_PLAN seq=10 guid=26 name='Arthoran' map=0 segment=0 start=(-8880.855 583.947 93.233) target=(-8864.850 595.939 92.645) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.01 path=20.01 maxSegment=4.00 maxZDelta=0.16 finalDistance=0.00 repaths=0 reason='ok'
|
||||
2026-10-27_14:11:04 INFO [server.adventurebot.navigation] NAV_EXEC seq=10 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.01 segmentEnd=(-8864.850 595.939 92.645) target=(-8864.850 595.939 92.645) walk=1
|
||||
2026-10-27_14:11:04 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8864.850 595.939 92.645) remaining=18.51 state=Moving
|
||||
2026-10-27_14:11:05 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8878.854 585.447 93.206) remaining=16.01 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:06 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8876.860 586.941 93.167) remaining=13.52 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:07 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8874.861 588.438 93.109) remaining=11.02 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:08 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8872.847 589.948 93.033) remaining=8.50 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:09 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8870.844 591.448 92.948) remaining=6.00 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:10 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8868.862 592.933 92.850) remaining=3.52 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:11 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8866.839 594.449 92.748) remaining=0.99 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:12 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=10 guid=26 segment=1 pos=(-8864.850 595.939 92.645) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:11:12 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=10 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
2026-10-27_14:11:12 INFO [server.adventurebot.navigation] NAV_PLAN seq=11 guid=26 name='Arthoran' map=0 segment=0 start=(-8864.850 595.939 92.645) target=(-8848.844 607.931 92.673) type=0x1 calculated=1 complete=1 suspicious=0 points=6 direct=20.00 path=20.00 maxSegment=4.00 maxZDelta=0.08 finalDistance=0.03 repaths=0 reason='ok'
|
||||
2026-10-27_14:11:12 INFO [server.adventurebot.navigation] NAV_EXEC seq=11 guid=26 name='Arthoran' segment=1 splinePoints=6 splineLength=20.00 segmentEnd=(-8848.844 607.931 92.642) target=(-8848.844 607.931 92.673) walk=1
|
||||
2026-10-27_14:11:12 INFO [server.adventurebot.navigation] NAV_START guid=26 name='Arthoran' map=0 target=(-8848.844 607.931 92.673) remaining=18.50 state=Moving
|
||||
2026-10-27_14:11:13 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8862.856 597.433 92.602) remaining=16.01 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:14 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8860.846 598.939 92.561) remaining=13.50 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:15 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8858.829 600.450 92.524) remaining=10.98 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:16 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8856.846 601.936 92.520) remaining=8.50 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:17 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8854.824 603.451 92.534) remaining=5.97 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:18 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8852.815 604.956 92.585) remaining=3.46 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:19 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8850.809 606.459 92.619) remaining=0.96 deviation=0.00 splineActive=1 repaths=0
|
||||
2026-10-27_14:11:20 DEBUG [server.adventurebot.navigation] NAV_SAMPLE seq=11 guid=26 segment=1 pos=(-8848.844 607.931 92.642) remaining=0.00 deviation=0.00 splineActive=0 repaths=0
|
||||
2026-10-27_14:11:20 INFO [server.adventurebot.navigation] NAV_COMPLETE seq=11 guid=26 name='Arthoran' remaining=0.00 repaths=0 segments=1 maxDeviation=0.00
|
||||
@@ -0,0 +1,34 @@
|
||||
LEISURE_WALK_PLAN guid=26 kind='pet_walk' span=80.02 outbound=4 origin=(-8848.84 607.93 92.67) goal=(-8912.87 559.96 94.24)
|
||||
COMPANION_START guid=26 spell=10673 summoned=1
|
||||
LEISURE_START guid=26 kind='pet_walk' waypoints=8
|
||||
COMPANION_CONFIRMED guid=26 pet='GUID Full: 0xf1301cd900000961 Type: Creature Entry: 7385 Low: 2401' entry=7385
|
||||
COMPANION_LEASH_REQUEST guid=26 item=37460 spell=48722
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_LEASH_CONFIRMED guid=26 spell=48722
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8864.85 595.94 92.65) pet=(-8862.91 597.40 92.59) distance=2.43 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=1/8
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8880.86 583.95 93.23) pet=(-8879.00 585.34 93.21) distance=2.32 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=2/8
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8896.86 571.96 93.01) pet=(-8894.87 573.45 92.98) distance=2.48 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=3/8
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8912.87 559.96 94.24) pet=(-8910.87 561.46 94.17) distance=2.50 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=4/8
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8896.86 571.96 93.01) pet=(-8898.80 570.51 93.12) distance=2.42 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=5/8
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8880.86 583.95 93.23) pet=(-8882.85 582.46 93.26) distance=2.49 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=6/8
|
||||
Player::_LoadSkills: Player 'Allitester' (GUID Full: 0x0000000000000015 Type: Player Low: 21, Race: 1, Class: 1) has forbidden skill 118 for his race/class combination
|
||||
CreatureAI::EngagementOver called even though creature is not currently engaged.
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8864.85 595.94 92.65) pet=(-8866.87 594.43 92.75) distance=2.52 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=7/8
|
||||
COMPANION_WALK_SAMPLE guid=26 owner=(-8848.84 607.93 92.64) pet=(-8850.84 606.44 92.59) distance=2.49 leashed=1
|
||||
LEISURE_WAYPOINT guid=26 kind='pet_walk' reached=8/8
|
||||
LEISURE_COMPLETE guid=26 kind='pet_walk' legs=8
|
||||
COMPANION_END guid=26
|
||||
MICRO_START guid=26 intent='leisure' location='stormwind_leisure_trade' action='leisure_view' durationMs=36000
|
||||
Received not handled opcode [CMSG_USED_FOLLOW 0x7912 (30994)] from [Player: Allitester GUID Full: 0x0000000000000015 Type: Player Low: 21, Account: 1]
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,10 @@
|
||||
from pathlib import Path
|
||||
import os,re,subprocess,sys
|
||||
c=Path('/home/wow_admin/wow_cata_server/server/debug/etc/worldserver.conf').read_text();v=re.search(r'^WorldDatabaseInfo\s*=\s*"([^"]+)"',c,re.M).group(1).split(';');h,port,u,p,d=v
|
||||
a=['mysql','--protocol=TCP','--host='+h,'--port='+port,'--user='+u,'--database='+d,'--batch','--default-character-set=utf8mb4','--connect-timeout=10'];env=os.environ.copy();env['MYSQL_PWD']=p
|
||||
q="SELECT entry,name FROM creature_template WHERE entry IN (7385,7386); SELECT name,map,position_x,position_y,position_z,orientation FROM game_tele WHERE name IN ('TradeDistrict','CathedralSquare'); SELECT action_key,kind,requirement FROM vcore_adventure_action WHERE action_key LIKE 'social%';"
|
||||
if sys.argv[1:]==['apply']:
|
||||
q='START TRANSACTION;\n'+Path('/home/wow_admin/wow_cata_server/source/TrinityCore/sql/custom/world/2026_10_27_02_adventure_leisure.sql').read_text()+"\nSELECT a.action_key,a.kind,a.requirement,i.weight FROM vcore_adventure_action a JOIN vcore_adventure_action_intent i USING(action_key) WHERE i.intent='leisure'; SELECT w.point_key,w.position_x,w.position_y,w.position_z FROM vcore_clientless_world_point w WHERE w.point_key='stormwind_leisure_trade'; COMMIT;"
|
||||
elif sys.argv[1:]!=['inspect']:raise SystemExit('inspect or apply only')
|
||||
r=subprocess.run(a,input=q,text=True,capture_output=True,env=env);print(r.stdout,end='');print(r.stderr.replace(p,'[redacted]'),file=sys.stderr,end='') if r.returncode else None
|
||||
raise SystemExit(r.returncode)
|
||||
@@ -0,0 +1,777 @@
|
||||
[1/751] cd /home/wow_admin/wow_cata_server/source/TrinityCore && /usr/bin/cmake -DBUILDDIR="/home/wow_admin/wow_cata_server/build/debug" -P /home/wow_admin/wow_cata_server/source/TrinityCore/cmake/genrev.cmake /home/wow_admin/wow_cata_server/build/debug
|
||||
[2/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessPerceptionMgr.cpp.o
|
||||
[3/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureProfessionTargets.cpp.o
|
||||
[4/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessRouteRecorderMgr.cpp.o
|
||||
[5/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessPlayerMgr.cpp.o
|
||||
[6/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessCompanionMgr.cpp.o
|
||||
[7/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessLuaEngine.cpp.o
|
||||
[8/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessFlightMgr.cpp.o
|
||||
[9/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessTransportMgr.cpp.o
|
||||
[10/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessActionExecutorMgr.cpp.o
|
||||
[11/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessWorldPointMgr.cpp.o
|
||||
[12/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessTravelMgr.cpp.o
|
||||
[13/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessTravelGraphMgr.cpp.o
|
||||
[14/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/gen_scriptloader/static/ScriptLoader.cpp.o
|
||||
[15/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/WorldStates/WorldStateMgr.cpp.o
|
||||
[16/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Battlefield/battlefield_script_loader.cpp.o
|
||||
[17/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Battlefield/BattlefieldTB.cpp.o
|
||||
[18/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_achievement.cpp.o
|
||||
[19/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_ahbot.cpp.o
|
||||
[20/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Battlefield/BattlefieldWG.cpp.o
|
||||
[21/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_arena.cpp.o
|
||||
[22/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_bf.cpp.o
|
||||
[23/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_account.cpp.o
|
||||
[24/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_ban.cpp.o
|
||||
[25/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_cast.cpp.o
|
||||
[26/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_cheat.cpp.o
|
||||
[27/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_deserter.cpp.o
|
||||
[28/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_character.cpp.o
|
||||
[29/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_event.cpp.o
|
||||
[30/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_disable.cpp.o
|
||||
[31/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_gm.cpp.o
|
||||
[32/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_honor.cpp.o
|
||||
[33/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_group.cpp.o
|
||||
[34/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_debug.cpp.o
|
||||
[35/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_guild.cpp.o
|
||||
[36/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_gobject.cpp.o
|
||||
[37/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_go.cpp.o
|
||||
[38/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_instance.cpp.o
|
||||
[39/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_learn.cpp.o
|
||||
[40/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_lfg.cpp.o
|
||||
[41/751] Building CXX object src/server/game/CMakeFiles/game.dir/World/World.cpp.o
|
||||
[42/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_message.cpp.o
|
||||
[43/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_list.cpp.o
|
||||
[44/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_mmaps.cpp.o
|
||||
[45/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_lookup.cpp.o
|
||||
[46/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_modify.cpp.o
|
||||
[47/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_pet.cpp.o
|
||||
[48/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_script_loader.cpp.o
|
||||
[49/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_misc.cpp.o
|
||||
[50/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_quest.cpp.o
|
||||
[51/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_rbac.cpp.o
|
||||
[52/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_npc.cpp.o
|
||||
[53/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_reset.cpp.o
|
||||
[54/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_send.cpp.o
|
||||
[55/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Custom/custom_script_loader.cpp.o
|
||||
[56/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_server.cpp.o
|
||||
[57/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_titles.cpp.o
|
||||
[58/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_reload.cpp.o
|
||||
[59/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_ticket.cpp.o
|
||||
[60/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_tele.cpp.o
|
||||
[61/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Commands/cs_wp.cpp.o
|
||||
[62/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/arathi_highlands.cpp.o
|
||||
[63/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Custom/vcore_diagnostics.cpp.o
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/vcore_diagnostics.cpp:236:39: warning: ‘std::optional<std::__cxx11::basic_string<char> > VCoreDiagnostics::DisplayTextColumn(const std::string&, const std::string&)’ defined but not used [-Wunused-function]
|
||||
236 | static std::optional<std::string> DisplayTextColumn(
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
[64/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/eastern_kingdoms_script_loader.cpp.o
|
||||
[65/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_dun_morogh.cpp.o
|
||||
[66/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_blasted_lands.cpp.o
|
||||
[67/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp.o
|
||||
[68/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Custom/viano_adventurers.cpp.o
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_adventurers.cpp: In member function ‘void VianoAdventurers::npc_horde_adventurer_melee::npc_horde_adventurer_meleeAI::HandleOutOfCombatRecovery(uint32)’:
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_adventurers.cpp:310:49: warning: comparison of integer expressions of different signedness: ‘int32’ {aka ‘int’} and ‘uint32’ {aka ‘unsigned int’} [-Wsign-compare]
|
||||
310 | if (maxMana > 0 && me->GetPower(POWER_MANA) < maxMana)
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_adventurers.cpp: In member function ‘void VianoAdventurers::npc_horde_adventurer_tank::npc_horde_adventurer_tankAI::HandleOutOfCombatRecovery(uint32)’:
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_adventurers.cpp:861:57: warning: comparison of integer expressions of different signedness: ‘int32’ {aka ‘int’} and ‘uint32’ {aka ‘unsigned int’} [-Wsign-compare]
|
||||
861 | if (maxMana && me->GetPower(POWER_MANA) < maxMana)
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_adventurers.cpp: In member function ‘void VianoAdventurers::npc_horde_adventurer_healer::npc_horde_adventurer_healerAI::HandleOutOfCombatRecovery(uint32, Player*)’:
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_adventurers.cpp:1518:57: warning: comparison of integer expressions of different signedness: ‘int32’ {aka ‘int’} and ‘uint32’ {aka ‘unsigned int’} [-Wsign-compare]
|
||||
1518 | if (maxMana && me->GetPower(POWER_MANA) < maxMana)
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
|
||||
[69/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_duskwood.cpp.o
|
||||
[70/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_ghostlands.cpp.o
|
||||
[71/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_elwynn_forest.cpp.o
|
||||
[72/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_hinterlands.cpp.o
|
||||
[73/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_ironforge.cpp.o
|
||||
[74/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Custom/viano_bot_commands.cpp.o
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp: In function ‘bool VianoBotCommands::HandleClientlessLocationAdd(ChatHandler*, const char*)’:
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp:2062:20: warning: unused variable ‘loaded’ [-Wunused-variable]
|
||||
2062 | bool const loaded = sClientlessWorldPointMgr->Reload();
|
||||
| ^~~~~~
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp: In function ‘bool VianoBotCommands::HandleClientlessLocationMove(ChatHandler*, const char*)’:
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp:2099:20: warning: unused variable ‘loaded’ [-Wunused-variable]
|
||||
2099 | bool const loaded = sClientlessWorldPointMgr->Reload();
|
||||
| ^~~~~~
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp: In function ‘bool VianoBotCommands::HandleClientlessLocationRemove(ChatHandler*, const char*)’:
|
||||
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp:2123:20: warning: unused variable ‘loaded’ [-Wunused-variable]
|
||||
2123 | bool const loaded = sClientlessWorldPointMgr->Reload();
|
||||
| ^~~~~~
|
||||
[75/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_redridge_mountains.cpp.o
|
||||
[76/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_silverpine_forest.cpp.o
|
||||
[77/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_swamp_of_sorrows.cpp.o
|
||||
[78/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_stormwind_city.cpp.o
|
||||
[79/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_hillsbrad_foothills.cpp.o
|
||||
[80/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_tirisfal_glades.cpp.o
|
||||
[81/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_tol_barad.cpp.o
|
||||
[82/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_undercity.cpp.o
|
||||
[83/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_western_plaguelands.cpp.o
|
||||
[84/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/AlteracValley/alterac_valley.cpp.o
|
||||
[85/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/AlteracValley/boss_balinda.cpp.o
|
||||
[86/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_wetlands.cpp.o
|
||||
[87/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/AlteracValley/boss_drekthar.cpp.o
|
||||
[88/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_twilight_highlands.cpp.o
|
||||
[89/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/AlteracValley/boss_galvangar.cpp.o
|
||||
[90/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/zone_westfall.cpp.o
|
||||
[91/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/AlteracValley/boss_vanndar.cpp.o
|
||||
[92/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BaradinHold/instance_baradin_hold.cpp.o
|
||||
[93/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BaradinHold/boss_alizabal.cpp.o
|
||||
[94/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BaradinHold/boss_occuthar.cpp.o
|
||||
[95/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BaradinHold/boss_pit_lord_argaloth.cpp.o
|
||||
[96/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.cpp.o
|
||||
[97/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp.o
|
||||
[98/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BastionOfTwilight/boss_halfus_wyrmbreaker.cpp.o
|
||||
[99/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BastionOfTwilight/boss_chogall.cpp.o
|
||||
[100/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/boss_beauty.cpp.o
|
||||
[101/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/blackrock_caverns.cpp.o
|
||||
[102/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/boss_ascendant_lord_obsidius.cpp.o
|
||||
[103/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BastionOfTwilight/boss_ascendant_council.cpp.o
|
||||
[104/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/boss_corla_herald_of_twilight.cpp.o
|
||||
[105/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BastionOfTwilight/boss_theralion_and_valiona.cpp.o
|
||||
[106/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/boss_karsh_steelbender.cpp.o
|
||||
[107/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/instance_blackrock_caverns.cpp.o
|
||||
[108/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockCaverns/boss_romogg_bonecrusher.cpp.o
|
||||
[109/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp.o
|
||||
[110/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp.o
|
||||
[111/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp.o
|
||||
[112/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp.o
|
||||
[113/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp.o
|
||||
[114/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp.o
|
||||
[115/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp.o
|
||||
[116/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp.o
|
||||
[117/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp.o
|
||||
[118/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp.o
|
||||
[119/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_gizrul_the_slavener.cpp.o
|
||||
[120/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp.o
|
||||
[121/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_halycon.cpp.o
|
||||
[122/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_gyth.cpp.o
|
||||
[123/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_highlord_omokk.cpp.o
|
||||
[124/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_lord_valthalak.cpp.o
|
||||
[125/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_mother_smolderweb.cpp.o
|
||||
[126/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_overlord_wyrmthalak.cpp.o
|
||||
[127/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_pyroguard_emberseer.cpp.o
|
||||
[128/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_quartermaster_zigris.cpp.o
|
||||
[129/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp.o
|
||||
[130/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp.o
|
||||
[131/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_the_beast.cpp.o
|
||||
[132/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_urok_doomhowl.cpp.o
|
||||
[133/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_warmaster_voone.cpp.o
|
||||
[134/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp.o
|
||||
[135/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.cpp.o
|
||||
[136/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp.o
|
||||
[137/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp.o
|
||||
[138/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_atramedes.cpp.o
|
||||
[139/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp.o
|
||||
[140/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_chimaeron.cpp.o
|
||||
[141/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_magmaw.cpp.o
|
||||
[142/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_maloriak.cpp.o
|
||||
[143/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp.o
|
||||
[144/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_omnotron_defense_system.cpp.o
|
||||
[145/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp.o
|
||||
[146/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp.o
|
||||
[147/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_nefarians_end.cpp.o
|
||||
[148/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp.o
|
||||
[149/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp.o
|
||||
[150/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp.o
|
||||
[151/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp.o
|
||||
[152/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_garr.cpp.o
|
||||
[153/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp.o
|
||||
[154/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_gehennas.cpp.o
|
||||
[155/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_lucifron.cpp.o
|
||||
[156/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp.o
|
||||
[157/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp.o
|
||||
[158/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp.o
|
||||
[159/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp.o
|
||||
[160/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp.o
|
||||
[161/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp.o
|
||||
[162/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp.o
|
||||
[163/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/boss_admiral_ripsnarl.cpp.o
|
||||
[164/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/boss_captain_cookie.cpp.o
|
||||
[165/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/boss_glubtok.cpp.o
|
||||
[166/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp.o
|
||||
[167/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/boss_vanessa_van_cleef.cpp.o
|
||||
[168/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/deadmines.cpp.o
|
||||
[169/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Gilneas/gilneas_chapter_1.cpp.o
|
||||
[170/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/instance_deadmines.cpp.o
|
||||
[171/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Deadmines/boss_helix_gearbreaker.cpp.o
|
||||
[172/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Gilneas/gilneas_chapter_2.cpp.o
|
||||
[173/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Gnomeregan/gnomeregan.cpp.o
|
||||
[174/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp.o
|
||||
[175/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/GrimBatol/boss_drahga_shadowburner.cpp.o
|
||||
[176/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/GrimBatol/boss_erudax.cpp.o
|
||||
[177/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/GrimBatol/grim_batol.cpp.o
|
||||
[178/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/GrimBatol/instance_grim_batol.cpp.o
|
||||
[179/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_curator.cpp.o
|
||||
[180/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/GrimBatol/boss_general_umbriss.cpp.o
|
||||
[181/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp.o
|
||||
[182/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/GrimBatol/boss_forgemaster_throngus.cpp.o
|
||||
[183/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_midnight.cpp.o
|
||||
[184/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_moroes.cpp.o
|
||||
[185/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_netherspite.cpp.o
|
||||
[186/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp.o
|
||||
[187/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp.o
|
||||
[188/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_nightbane.cpp.o
|
||||
[189/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/instance_karazhan.cpp.o
|
||||
[190/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp.o
|
||||
[191/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/bosses_opera.cpp.o
|
||||
[192/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Karazhan/karazhan.cpp.o
|
||||
[193/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp.o
|
||||
[194/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp.o
|
||||
[195/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp.o
|
||||
[196/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp.o
|
||||
[197/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp.o
|
||||
[198/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_2.cpp.o
|
||||
[199/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp.o
|
||||
[200/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp.o
|
||||
[201/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_5.cpp.o
|
||||
[202/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp.o
|
||||
[203/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp.o
|
||||
[204/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp.o
|
||||
[205/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp.o
|
||||
[206/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_herod.cpp.o
|
||||
[207/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp.o
|
||||
[208/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp.o
|
||||
[209/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp.o
|
||||
[210/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp.o
|
||||
[211/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_scorn.cpp.o
|
||||
[212/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp.o
|
||||
[213/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp.o
|
||||
[214/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp.o
|
||||
[215/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp.o
|
||||
[216/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp.o
|
||||
[217/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_illucia_barov.cpp.o
|
||||
[218/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_instructor_malicia.cpp.o
|
||||
[219/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_jandice_barov.cpp.o
|
||||
[220/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp.o
|
||||
[221/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp.o
|
||||
[222/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_kormok.cpp.o
|
||||
[223/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp.o
|
||||
[224/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp.o
|
||||
[225/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_the_ravenian.cpp.o
|
||||
[226/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/boss_vectus.cpp.o
|
||||
[227/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Scholomance/instance_scholomance.cpp.o
|
||||
[228/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/boss_baron_ashbury.cpp.o
|
||||
[229/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/boss_baron_silverlaine.cpp.o
|
||||
[230/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp.o
|
||||
[231/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/boss_apothecary_hummel.cpp.o
|
||||
[232/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/boss_commander_springvale.cpp.o
|
||||
[233/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp.o
|
||||
[234/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/boss_lord_godfrey.cpp.o
|
||||
[235/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ShadowfangKeep/boss_lord_walden.cpp.o
|
||||
[236/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_balnazzar.cpp.o
|
||||
[237/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp.o
|
||||
[238/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_baroness_anastari.cpp.o
|
||||
[239/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp.o
|
||||
[240/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp.o
|
||||
[241/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_nerubenkan.cpp.o
|
||||
[242/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp.o
|
||||
[243/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp.o
|
||||
[244/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp.o
|
||||
[245/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_postmaster_malown.cpp.o
|
||||
[246/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp.o
|
||||
[247/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/instance_stratholme.cpp.o
|
||||
[248/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp.o
|
||||
[249/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunkenTemple/sunken_temple.cpp.o
|
||||
[250/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Stratholme/stratholme.cpp.o
|
||||
[251/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp.o
|
||||
[252/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp.o
|
||||
[253/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp.o
|
||||
[254/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp.o
|
||||
[255/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp.o
|
||||
[256/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp.o
|
||||
[257/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/boss_muru.cpp.o
|
||||
[258/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/TheStockade/boss_hogger.cpp.o
|
||||
[259/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/TheStockade/boss_lord_overheat.cpp.o
|
||||
[260/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/TheStockade/boss_randolph_moloch.cpp.o
|
||||
[261/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp.o
|
||||
[262/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/TheStockade/instance_the_stockade.cpp.o
|
||||
[263/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ThroneOfTheTides/boss_commander_ulthok.cpp.o
|
||||
[264/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ThroneOfTheTides/boss_mindbender_gursha.cpp.o
|
||||
[265/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ThroneOfTheTides/boss_lady_nazjar.cpp.o
|
||||
[266/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ThroneOfTheTides/instance_throne_of_the_tides.cpp.o
|
||||
[267/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Uldaman/boss_ironaya.cpp.o
|
||||
[268/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Uldaman/boss_archaedas.cpp.o
|
||||
[269/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.cpp.o
|
||||
[270/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Uldaman/uldaman.cpp.o
|
||||
[271/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ThroneOfTheTides/boss_ozumat.cpp.o
|
||||
[272/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/Uldaman/instance_uldaman.cpp.o
|
||||
[273/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/boss_daakara.cpp.o
|
||||
[274/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/boss_halazzi.cpp.o
|
||||
[275/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/boss_hexlord.cpp.o
|
||||
[276/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/boss_nalorakk.cpp.o
|
||||
[277/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/boss_akilzon.cpp.o
|
||||
[278/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/instance_zulaman.cpp.o
|
||||
[279/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/zulaman.cpp.o
|
||||
[280/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulAman/boss_janalai.cpp.o
|
||||
[281/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_grilek.cpp.o
|
||||
[282/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_hazzarah.cpp.o
|
||||
[283/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_bloodlord_mandokir.cpp.o
|
||||
[284/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_renataki.cpp.o
|
||||
[285/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_jindo_the_godbreaker.cpp.o
|
||||
[286/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_wushoolay.cpp.o
|
||||
[287/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_high_priestess_kilnara.cpp.o
|
||||
[288/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_high_priest_venoxis.cpp.o
|
||||
[289/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/instance_zulgurub.cpp.o
|
||||
[290/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Events/childrens_week.cpp.o
|
||||
[291/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Events/events_script_loader.cpp.o
|
||||
[292/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/boss_zanzil.cpp.o
|
||||
[293/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/EasternKingdoms/ZulGurub/zulgurub.cpp.o
|
||||
[294/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Events/fireworks_show.cpp.o
|
||||
[295/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/kalimdor_script_loader.cpp.o
|
||||
[296/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_ashenvale.cpp.o
|
||||
[297/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_azuremyst_isle.cpp.o
|
||||
[298/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_desolace.cpp.o
|
||||
[299/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_bloodmyst_isle.cpp.o
|
||||
[300/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_durotar.cpp.o
|
||||
[301/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_moonglade.cpp.o
|
||||
[302/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_felwood.cpp.o
|
||||
[303/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_mulgore.cpp.o
|
||||
[304/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_northern_barrens.cpp.o
|
||||
[305/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_southern_barrens.cpp.o
|
||||
[306/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_mount_hyjal.cpp.o
|
||||
[307/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_silithus.cpp.o
|
||||
[308/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_tanaris.cpp.o
|
||||
[309/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_thunder_bluff.cpp.o
|
||||
[310/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_ungoro_crater.cpp.o
|
||||
[311/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_uldum.cpp.o
|
||||
[312/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/zone_winterspring.cpp.o
|
||||
[313/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp.o
|
||||
[314/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp.o
|
||||
[315/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp.o
|
||||
[316/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/BlackfathomDeeps/boss_kelris.cpp.o
|
||||
[317/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp.o
|
||||
[318/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp.o
|
||||
[319/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp.o
|
||||
[320/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp.o
|
||||
[321/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp.o
|
||||
[322/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp.o
|
||||
[323/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp.o
|
||||
[324/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp.o
|
||||
[325/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp.o
|
||||
[326/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp.o
|
||||
[327/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp.o
|
||||
[328/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp.o
|
||||
[329/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp.o
|
||||
[330/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp.o
|
||||
[331/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp.o
|
||||
[332/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp.o
|
||||
[333/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/DragonSoul/instance_dragon_soul.cpp.o
|
||||
[334/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EndTime/end_time.cpp.o
|
||||
[335/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EndTime/instance_end_time.cpp.o
|
||||
[336/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp.o
|
||||
[337/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EndTime/boss_murozond.cpp.o
|
||||
[338/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/CullingOfStratholme/npc_arthas.cpp.o
|
||||
[339/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp.o
|
||||
[340/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EndTime/boss_echo_of_jaina.cpp.o
|
||||
[341/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp.o
|
||||
[342/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp.o
|
||||
[343/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp.o
|
||||
[344/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/DragonSoul/boss_madness_of_deathwing.cpp.o
|
||||
[345/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp.o
|
||||
[346/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/HourOfTwilight/instance_hour_of_twilight.cpp.o
|
||||
[347/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp.o
|
||||
[348/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp.o
|
||||
[349/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp.o
|
||||
[350/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/WellOfEternity/instance_well_of_eternity.cpp.o
|
||||
[351/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp.o
|
||||
[352/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp.o
|
||||
[353/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/DireMaul/instance_dire_maul.cpp.o
|
||||
[354/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/firelands.cpp.o
|
||||
[355/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/boss_alysrazor.cpp.o
|
||||
[356/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/boss_baleroc.cpp.o
|
||||
[357/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/instance_firelands.cpp.o
|
||||
[358/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_ammunae.cpp.o
|
||||
[359/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/boss_majordomo_staghelm.cpp.o
|
||||
[360/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_anraphet.cpp.o
|
||||
[361/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/boss_lord_rhyolith.cpp.o
|
||||
[362/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp.o
|
||||
[363/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_isiset.cpp.o
|
||||
[364/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_rajh.cpp.o
|
||||
[365/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_setesh.cpp.o
|
||||
[366/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp.o
|
||||
[367/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Firelands/boss_ragnaros_firelands.cpp.o
|
||||
[368/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp.o
|
||||
[369/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/HallsOfOrigination/halls_of_origination.cpp.o
|
||||
[370/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/LostCityOfTheTolvir/boss_lockmaw_and_augh.cpp.o
|
||||
[371/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/LostCityOfTheTolvir/boss_general_husam.cpp.o
|
||||
[372/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp.o
|
||||
[373/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp.o
|
||||
[374/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.cpp.o
|
||||
[375/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp.o
|
||||
[376/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Maraudon/boss_landslide.cpp.o
|
||||
[377/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/LostCityOfTheTolvir/boss_siamat.cpp.o
|
||||
[378/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Maraudon/boss_noxxion.cpp.o
|
||||
[379/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Maraudon/boss_princess_theradras.cpp.o
|
||||
[380/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/Maraudon/instance_maraudon.cpp.o
|
||||
[381/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/OnyxiasLair/boss_onyxia.cpp.o
|
||||
[382/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RagefireChasm/instance_ragefire_chasm.cpp.o
|
||||
[383/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp.o
|
||||
[384/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp.o
|
||||
[385/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenDowns/boss_glutton.cpp.o
|
||||
[386/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp.o
|
||||
[387/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp.o
|
||||
[388/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp.o
|
||||
[389/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenDowns/razorfen_downs.cpp.o
|
||||
[390/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp.o
|
||||
[391/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RazorfenKraul/razorfen_kraul.cpp.o
|
||||
[392/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp.o
|
||||
[393/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp.o
|
||||
[394/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp.o
|
||||
[395/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp.o
|
||||
[396/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp.o
|
||||
[397/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp.o
|
||||
[398/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp.o
|
||||
[399/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp.o
|
||||
[400/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp.o
|
||||
[401/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp.o
|
||||
[402/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp.o
|
||||
[403/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp.o
|
||||
[404/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp.o
|
||||
[405/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp.o
|
||||
[406/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp.o
|
||||
[407/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp.o
|
||||
[408/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp.o
|
||||
[409/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp.o
|
||||
[410/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ThroneOfTheFourWinds/instance_throne_of_the_four_winds.cpp.o
|
||||
[411/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ThroneOfTheFourWinds/throne_of_the_four_winds.cpp.o
|
||||
[412/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/VortexPinnacle/boss_grand_vizier_ertan.cpp.o
|
||||
[413/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/VortexPinnacle/instance_vortex_pinnacle.cpp.o
|
||||
[414/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/VortexPinnacle/boss_altairus.cpp.o
|
||||
[415/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ThroneOfTheFourWinds/boss_conclave_of_wind.cpp.o
|
||||
[416/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ThroneOfTheFourWinds/boss_alakir.cpp.o
|
||||
[417/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_kresh.cpp.o
|
||||
[418/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/VortexPinnacle/boss_asaad.cpp.o
|
||||
[419/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_lady_anacondra.cpp.o
|
||||
[420/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_lord_cobrahn.cpp.o
|
||||
[421/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/VortexPinnacle/vortex_pinnacle.cpp.o
|
||||
[422/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_lord_pythas.cpp.o
|
||||
[423/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_lord_serpentis.cpp.o
|
||||
[424/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_skum.cpp.o
|
||||
[425/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/boss_verdan_the_everliving.cpp.o
|
||||
[426/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp.o
|
||||
[427/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/WailingCaverns/wailing_caverns.cpp.o
|
||||
[428/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ZulFarrak/boss_zum_rah.cpp.o
|
||||
[429/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/kezan.cpp.o
|
||||
[430/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ZulFarrak/instance_zulfarrak.cpp.o
|
||||
[431/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Kalimdor/ZulFarrak/zulfarrak.cpp.o
|
||||
[432/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/maelstrom_script_loader.cpp.o
|
||||
[433/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/zone_deepholm.cpp.o
|
||||
[434/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/Stonecore/instance_stonecore.cpp.o
|
||||
[435/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/Stonecore/boss_corborus.cpp.o
|
||||
[436/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/Stonecore/boss_slabhide.cpp.o
|
||||
[437/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/Stonecore/boss_ozruk.cpp.o
|
||||
[438/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/northrend_script_loader.cpp.o
|
||||
[439/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/Stonecore/boss_high_priestess_azil.cpp.o
|
||||
[440/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_crystalsong_forest.cpp.o
|
||||
[441/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Maelstrom/Stonecore/stonecore.cpp.o
|
||||
[442/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_dalaran.cpp.o
|
||||
[443/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_borean_tundra.cpp.o
|
||||
[444/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_icecrown.cpp.o
|
||||
[445/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_howling_fjord.cpp.o
|
||||
[446/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_dragonblight.cpp.o
|
||||
[447/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_grizzly_hills.cpp.o
|
||||
[448/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_sholazar_basin.cpp.o
|
||||
[449/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_wintergrasp.cpp.o
|
||||
[450/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp.o
|
||||
[451/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_storm_peaks.cpp.o
|
||||
[452/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/zone_zuldrak.cpp.o
|
||||
[453/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp.o
|
||||
[454/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp.o
|
||||
[455/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp.o
|
||||
[456/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp.o
|
||||
[457/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp.o
|
||||
[458/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp.o
|
||||
[459/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp.o
|
||||
[460/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp.o
|
||||
[461/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp.o
|
||||
[462/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp.o
|
||||
[463/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp.o
|
||||
[464/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp.o
|
||||
[465/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp.o
|
||||
[466/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp.o
|
||||
[467/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp.o
|
||||
[468/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp.o
|
||||
[469/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp.o
|
||||
[470/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp.o
|
||||
[471/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp.o
|
||||
[472/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp.o
|
||||
[473/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp.o
|
||||
[474/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp.o
|
||||
[475/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp.o
|
||||
[476/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp.o
|
||||
[477/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp.o
|
||||
[478/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/DraktharonKeep/boss_king_dred.cpp.o
|
||||
[479/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/DraktharonKeep/boss_novos.cpp.o
|
||||
[480/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp.o
|
||||
[481/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp.o
|
||||
[482/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp.o
|
||||
[483/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp.o
|
||||
[484/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp.o
|
||||
[485/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/DraktharonKeep/boss_tharon_ja.cpp.o
|
||||
[486/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/DraktharonKeep/boss_trollgore.cpp.o
|
||||
[487/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp.o
|
||||
[488/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp.o
|
||||
[489/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/HallsOfReflection/boss_horAI.cpp.o
|
||||
[490/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp.o
|
||||
[491/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp.o
|
||||
[492/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp.o
|
||||
[493/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp.o
|
||||
[494/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp.o
|
||||
[495/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp.o
|
||||
[496/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp.o
|
||||
[497/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp.o
|
||||
[498/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp.o
|
||||
[499/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Gundrak/boss_drakkari_colossus.cpp.o
|
||||
[500/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Gundrak/boss_eck.cpp.o
|
||||
[501/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp.o
|
||||
[502/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp.o
|
||||
[503/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp.o
|
||||
[504/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Gundrak/boss_gal_darah.cpp.o
|
||||
[505/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Gundrak/boss_moorabi.cpp.o
|
||||
[506/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Gundrak/boss_slad_ran.cpp.o
|
||||
[507/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Gundrak/instance_gundrak.cpp.o
|
||||
[508/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_festergut.cpp.o
|
||||
[509/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp.o
|
||||
[510/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp.o
|
||||
[511/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp.o
|
||||
[512/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp.o
|
||||
[513/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp.o
|
||||
[514/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_rotface.cpp.o
|
||||
[515/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp.o
|
||||
[516/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_professor_putricide.cpp.o
|
||||
[517/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp.o
|
||||
[518/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp.o
|
||||
[519/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_sindragosa.cpp.o
|
||||
[520/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp.o
|
||||
[521/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/icecrown_citadel.cpp.o
|
||||
[522/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_anubrekhan.cpp.o
|
||||
[523/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp.o
|
||||
[524/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IsleOfConquest/isle_of_conquest.cpp.o
|
||||
[525/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_faerlina.cpp.o
|
||||
[526/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/IcecrownCitadel/boss_the_lich_king.cpp.o
|
||||
[527/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_gluth.cpp.o
|
||||
[528/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_grobbulus.cpp.o
|
||||
[529/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_four_horsemen.cpp.o
|
||||
[530/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_heigan.cpp.o
|
||||
[531/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_gothik.cpp.o
|
||||
[532/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_loatheb.cpp.o
|
||||
[533/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_maexxna.cpp.o
|
||||
[534/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_noth.cpp.o
|
||||
[535/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_kelthuzad.cpp.o
|
||||
[536/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_patchwerk.cpp.o
|
||||
[537/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_razuvious.cpp.o
|
||||
[538/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/instance_naxxramas.cpp.o
|
||||
[539/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/naxxramas.cpp.o
|
||||
[540/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_thaddius.cpp.o
|
||||
[541/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/boss_anomalus.cpp.o
|
||||
[542/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/boss_commander_stoutbeard.cpp.o
|
||||
[543/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp.o
|
||||
[544/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Naxxramas/boss_sapphiron.cpp.o
|
||||
[545/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/boss_keristrasza.cpp.o
|
||||
[546/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/boss_magus_telestra.cpp.o
|
||||
[547/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp.o
|
||||
[548/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/boss_nexus_commanders.cpp.o
|
||||
[549/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/instance_nexus.cpp.o
|
||||
[550/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Nexus/boss_ormorok.cpp.o
|
||||
[551/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Oculus/boss_drakos.cpp.o
|
||||
[552/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Oculus/boss_urom.cpp.o
|
||||
[553/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Oculus/boss_eregos.cpp.o
|
||||
[554/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Oculus/boss_varos.cpp.o
|
||||
[555/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Oculus/instance_oculus.cpp.o
|
||||
[556/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp.o
|
||||
[557/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Nexus/Oculus/oculus.cpp.o
|
||||
[558/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp.o
|
||||
[559/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp.o
|
||||
[560/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfLightning/boss_general_bjarngrim.cpp.o
|
||||
[561/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp.o
|
||||
[562/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp.o
|
||||
[563/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp.o
|
||||
[564/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp.o
|
||||
[565/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp.o
|
||||
[566/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp.o
|
||||
[567/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_auriaya.cpp.o
|
||||
[568/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_freya.cpp.o
|
||||
[569/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp.o
|
||||
[570/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp.o
|
||||
[571/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_ignis.cpp.o
|
||||
[572/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp.o
|
||||
[573/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_hodir.cpp.o
|
||||
[574/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp.o
|
||||
[575/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_kologarn.cpp.o
|
||||
[576/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_razorscale.cpp.o
|
||||
[577/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp.o
|
||||
[578/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/instance_ulduar.cpp.o
|
||||
[579/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp.o
|
||||
[580/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp.o
|
||||
[581/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp.o
|
||||
[582/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_mimiron.cpp.o
|
||||
[583/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_xt002.cpp.o
|
||||
[584/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_thorim.cpp.o
|
||||
[585/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp.o
|
||||
[586/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp.o
|
||||
[587/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp.o
|
||||
[588/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp.o
|
||||
[589/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp.o
|
||||
[590/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp.o
|
||||
[591/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VaultOfArchavon/boss_emalon.cpp.o
|
||||
[592/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VaultOfArchavon/boss_archavon.cpp.o
|
||||
[593/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp.o
|
||||
[594/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VaultOfArchavon/boss_koralon.cpp.o
|
||||
[595/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VaultOfArchavon/boss_toravon.cpp.o
|
||||
[596/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp.o
|
||||
[597/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_lavanthor.cpp.o
|
||||
[598/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_erekem.cpp.o
|
||||
[599/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_cyanigosa.cpp.o
|
||||
[600/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_ichoron.cpp.o
|
||||
[601/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_moragg.cpp.o
|
||||
[602/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_xevozz.cpp.o
|
||||
[603/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/boss_zuramat.cpp.o
|
||||
[604/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/instance_violet_hold.cpp.o
|
||||
[605/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/OutdoorPvP/OutdoorPvPHP.cpp.o
|
||||
[606/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/OutdoorPvP/OutdoorPvPScriptLoader.cpp.o
|
||||
[607/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/OutdoorPvP/OutdoorPvPTF.cpp.o
|
||||
[608/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Northrend/VioletHold/violet_hold.cpp.o
|
||||
[609/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/OutdoorPvP/OutdoorPvPNA.cpp.o
|
||||
[610/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/boss_doomwalker.cpp.o
|
||||
[611/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/OutdoorPvP/OutdoorPvPSI.cpp.o
|
||||
[612/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/boss_doomlord_kazzak.cpp.o
|
||||
[613/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/OutdoorPvP/OutdoorPvPZM.cpp.o
|
||||
[614/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/outland_script_loader.cpp.o
|
||||
[615/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_blades_edge_mountains.cpp.o
|
||||
[616/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_nagrand.cpp.o
|
||||
[617/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_shattrath_city.cpp.o
|
||||
[618/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_hellfire_peninsula.cpp.o
|
||||
[619/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_zangarmarsh.cpp.o
|
||||
[620/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp.o
|
||||
[621/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_terokkar_forest.cpp.o
|
||||
[622/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp.o
|
||||
[623/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_shadowmoon_valley.cpp.o
|
||||
[624/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/zone_netherstorm.cpp.o
|
||||
[625/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/AuchenaiCrypts/instance_auchenai_crypts.cpp.o
|
||||
[626/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp.o
|
||||
[627/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp.o
|
||||
[628/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ManaTombs/instance_mana_tombs.cpp.o
|
||||
[629/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/SethekkHalls/boss_anzu.cpp.o
|
||||
[630/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp.o
|
||||
[631/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp.o
|
||||
[632/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp.o
|
||||
[633/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp.o
|
||||
[634/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp.o
|
||||
[635/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp.o
|
||||
[636/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp.o
|
||||
[637/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp.o
|
||||
[638/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.cpp.o
|
||||
[639/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp.o
|
||||
[640/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/black_temple.cpp.o
|
||||
[641/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_mother_shahraz.cpp.o
|
||||
[642/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_illidari_council.cpp.o
|
||||
[643/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_reliquary_of_souls.cpp.o
|
||||
[644/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_supremus.cpp.o
|
||||
[645/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_shade_of_akama.cpp.o
|
||||
[646/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_illidan.cpp.o
|
||||
[647/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_warlord_najentus.cpp.o
|
||||
[648/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/instance_black_temple.cpp.o
|
||||
[649/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp.o
|
||||
[650/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/BlackTemple/boss_teron_gorefiend.cpp.o
|
||||
[651/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp.o
|
||||
[652/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp.o
|
||||
[653/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp.o
|
||||
[654/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp.o
|
||||
[655/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp.o
|
||||
[656/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp.o
|
||||
[657/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp.o
|
||||
[658/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp.o
|
||||
[659/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp.o
|
||||
[660/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp.o
|
||||
[661/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheSlavePens/boss_mennu_the_betrayer.cpp.o
|
||||
[662/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheSlavePens/boss_quagmirran.cpp.o
|
||||
[663/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheSlavePens/boss_rokmar_the_crackler.cpp.o
|
||||
[664/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp.o
|
||||
[665/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheUnderbog/boss_hungarfen.cpp.o
|
||||
[666/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheUnderbog/boss_the_black_stalker.cpp.o
|
||||
[667/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheUnderbog/instance_the_underbog.cpp.o
|
||||
[668/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp.o
|
||||
[669/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/GruulsLair/boss_gruul.cpp.o
|
||||
[670/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/GruulsLair/boss_high_king_maulgar.cpp.o
|
||||
[671/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/GruulsLair/instance_gruuls_lair.cpp.o
|
||||
[672/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp.o
|
||||
[673/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp.o
|
||||
[674/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp.o
|
||||
[675/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp.o
|
||||
[676/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp.o
|
||||
[677/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp.o
|
||||
[678/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp.o
|
||||
[679/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp.o
|
||||
[680/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp.o
|
||||
[681/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp.o
|
||||
[682/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp.o
|
||||
[683/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp.o
|
||||
[684/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp.o
|
||||
[685/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp.o
|
||||
[686/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Eye/boss_alar.cpp.o
|
||||
[687/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp.o
|
||||
[688/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Eye/boss_astromancer.cpp.o
|
||||
[689/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Eye/boss_kaelthas.cpp.o
|
||||
[690/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Eye/boss_void_reaver.cpp.o
|
||||
[691/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Eye/the_eye.cpp.o
|
||||
[692/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Eye/instance_the_eye.cpp.o
|
||||
[693/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp.o
|
||||
[694/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp.o
|
||||
[695/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp.o
|
||||
[696/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp.o
|
||||
[697/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp.o
|
||||
[698/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/Mechanar/instance_mechanar.cpp.o
|
||||
[699/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/arcatraz/arcatraz.cpp.o
|
||||
[700/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp.o
|
||||
[701/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp.o
|
||||
[702/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp.o
|
||||
[703/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/arcatraz/boss_zereketh_the_unbound.cpp.o
|
||||
[704/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp.o
|
||||
[705/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp.o
|
||||
[706/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/botanica/boss_commander_sarannis.cpp.o
|
||||
[707/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/botanica/boss_laj.cpp.o
|
||||
[708/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp.o
|
||||
[709/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/botanica/instance_the_botanica.cpp.o
|
||||
[710/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Outland/TempestKeep/botanica/boss_warp_splinter.cpp.o
|
||||
[711/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_generic.cpp.o
|
||||
[712/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_mage.cpp.o
|
||||
[713/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_dk.cpp.o
|
||||
[714/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_hunter.cpp.o
|
||||
[715/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_paladin.cpp.o
|
||||
[716/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_script_loader.cpp.o
|
||||
[717/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_priest.cpp.o
|
||||
[718/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Pet/pet_shaman.cpp.o
|
||||
[719/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_pet.cpp.o
|
||||
[720/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_holiday.cpp.o
|
||||
[721/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_dk.cpp.o
|
||||
[722/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_hunter.cpp.o
|
||||
[723/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_druid.cpp.o
|
||||
[724/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_mage.cpp.o
|
||||
[725/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_priest.cpp.o
|
||||
[726/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_paladin.cpp.o
|
||||
[727/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_script_loader.cpp.o
|
||||
[728/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/achievement_scripts.cpp.o
|
||||
[729/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/action_ip_logger.cpp.o
|
||||
[730/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_quest.cpp.o
|
||||
[731/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_rogue.cpp.o
|
||||
[732/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/areatrigger_scripts.cpp.o
|
||||
[733/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_item.cpp.o
|
||||
[734/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_warrior.cpp.o
|
||||
[735/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_shaman.cpp.o
|
||||
[736/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/duel_reset.cpp.o
|
||||
[737/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_generic.cpp.o
|
||||
[738/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/guards.cpp.o
|
||||
[739/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/chat_log.cpp.o
|
||||
[740/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Spells/spell_warlock.cpp.o
|
||||
[741/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/mob_generic_creature.cpp.o
|
||||
[742/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/go_scripts.cpp.o
|
||||
[743/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/item_scripts.cpp.o
|
||||
[744/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/npc_innkeeper.cpp.o
|
||||
[745/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/world_map_scripts.cpp.o
|
||||
[746/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/world_script_loader.cpp.o
|
||||
[747/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/npc_professions.cpp.o
|
||||
[748/751] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/World/npcs_special.cpp.o
|
||||
[749/751] Linking CXX static library src/server/game/libgame.a
|
||||
ninja: build stopped: interrupted by user.
|
||||
@@ -0,0 +1,61 @@
|
||||
-- Detected 64-bit platform
|
||||
-- UNIX: Using default configuration directory
|
||||
-- UNIX: Configuring uninstall target
|
||||
-- UNIX: Created uninstall target
|
||||
-- UNIX: Detected compiler: /usr/bin/cc
|
||||
-- GCC: Minimum version required is 10.0.0, found 15.2.0 - ok!
|
||||
-- GCC: SFMT enabled, SSE2 flags forced
|
||||
-- GCC: All warnings enabled
|
||||
-- GCC: Debug-flags set (-g3)
|
||||
-- Found MySQL:
|
||||
-- Found MySQL: found components: binary
|
||||
-- Found MySQL executable: /usr/bin/mysql
|
||||
|
||||
* TrinityCore revision : 119d63ed1c37+ 2026-10-26 22:45:38 +0100 (feature/clientless-player-core branch)
|
||||
* TrinityCore buildtype : Debug
|
||||
|
||||
* Install core to : /home/wow_admin/wow_cata_server/server/debug
|
||||
|
||||
* Build world/auth : Yes (default)
|
||||
* Build with scripts : Yes (static)
|
||||
* Build map/vmap tools : No
|
||||
* Build unit tests : No (default)
|
||||
* Unity build enabled : No (default)
|
||||
* Build core w/PCH : Yes (default)
|
||||
* Build scripts w/PCH : Yes (default)
|
||||
* Show all warnings : Yes
|
||||
|
||||
*** WITH_COREDEBUG - WARNING!
|
||||
*** additional core debug logs have been enabled!
|
||||
*** this setting doesn't help to get better crash logs!
|
||||
*** in case you are searching for better crash logs use
|
||||
*** -DCMAKE_BUILD_TYPE=RelWithDebug
|
||||
*** DO NOT ENABLE IT UNLESS YOU KNOW WHAT YOU'RE DOING!
|
||||
* Use coreside debug : Yes
|
||||
* Show source tree : Yes (hierarchical)
|
||||
* Use GIT revision hash : Yes (default)
|
||||
|
||||
-- Found Readline library: /usr/lib/x86_64-linux-gnu/libreadline.so
|
||||
-- Include dir is: /usr/include
|
||||
|
||||
* Script configuration (static):
|
||||
|
|
||||
+- worldserver
|
||||
| +- Battlefield
|
||||
| +- Commands
|
||||
| +- Custom
|
||||
| +- EasternKingdoms
|
||||
| +- Events
|
||||
| +- Kalimdor
|
||||
| +- Maelstrom
|
||||
| +- Northrend
|
||||
| +- OutdoorPvP
|
||||
| +- Outland
|
||||
| +- Pet
|
||||
| +- Spells
|
||||
| +- World
|
||||
|
|
||||
|
||||
-- Configuring done (0.4s)
|
||||
-- Generating done (0.1s)
|
||||
-- Build files have been written to: /home/wow_admin/wow_cata_server/build/debug
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/tmp/vcore-economy-t0vuw0w2/test.cpp: In function ‘bool TargetVisible(Player*, WorldObject*, const std::string&)’:
|
||||
/tmp/vcore-economy-t0vuw0w2/test.cpp:61:57: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
61 | if (!AdventureEconomyPolicy::Economic(kind) && !AdventureProfessionPolicy::Recognized(kind)) return player->IsWithinLOSInMap(target);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_economy.py", line 101, in <module>
|
||||
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '-I', '/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/game/World', '/tmp/vcore-economy-t0vuw0w2/test.cpp', '-o', '/tmp/vcore-economy-t0vuw0w2/test']' returned non-zero exit status 1.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp: In static member function ‘static bool AdventureSocialActions::Available(Player*, const AdventureMicroAction&, AdventureSocialContext&)’:
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:50:9: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
50 | if (AdventureProfessionPolicy::Recognized(kind)) return c.Intent=="profession" &&
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:51:9: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
51 | AdventureProfessionPolicy::Allowed(kind,c.PrimaryProfessions) &&
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:51:51: error: ‘struct AdventureSocialContext’ has no member named ‘PrimaryProfessions’
|
||||
51 | AdventureProfessionPolicy::Allowed(kind,c.PrimaryProfessions) &&
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:52:10: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
52 | (AdventureProfessionPolicy::Untargeted(kind)?!p->IsInWater() && !p->IsFalling():!AdventureProfessionTargets::Find(p,kind,c).empty());
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:52:58: error: ‘struct Player’ has no member named ‘IsInWater’
|
||||
52 | (AdventureProfessionPolicy::Untargeted(kind)?!p->IsInWater() && !p->IsFalling():!AdventureProfessionTargets::Find(p,kind,c).empty());
|
||||
| ^~~~~~~~~
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:52:77: error: ‘struct Player’ has no member named ‘IsFalling’
|
||||
52 | (AdventureProfessionPolicy::Untargeted(kind)?!p->IsInWater() && !p->IsFalling():!AdventureProfessionTargets::Find(p,kind,c).empty());
|
||||
| ^~~~~~~~~
|
||||
/tmp/vcore-exploration-adul8yl4/test.cpp:52:90: error: ‘AdventureProfessionTargets’ has not been declared
|
||||
52 | (AdventureProfessionPolicy::Untargeted(kind)?!p->IsInWater() && !p->IsFalling():!AdventureProfessionTargets::Find(p,kind,c).empty());
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_exploration.py", line 60, in <module>
|
||||
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '-I', '/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/game/World', '/tmp/vcore-exploration-adul8yl4/test.cpp', '-o', '/tmp/vcore-exploration-adul8yl4/test']' returned non-zero exit status 1.
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/tmp/vcore-adventure-state-4s9vbnjn/test.cpp: In lambda function:
|
||||
/tmp/vcore-adventure-state-4s9vbnjn/test.cpp:82:22: error: ‘struct AdventureBehaviorMgr::Record::<unnamed>’ has no member named ‘Progressive’
|
||||
82 | if(r.Leisure.Progressive && !r.Leisure.Route.empty() && r.Leisure.Step>=r.Leisure.Route.size() &&
|
||||
| ^~~~~~~~~~~
|
||||
/tmp/vcore-adventure-state-4s9vbnjn/test.cpp:82:48: error: ‘struct AdventureBehaviorMgr::Record::<unnamed>’ has no member named ‘Route’
|
||||
82 | if(r.Leisure.Progressive && !r.Leisure.Route.empty() && r.Leisure.Step>=r.Leisure.Route.size() &&
|
||||
| ^~~~~
|
||||
/tmp/vcore-adventure-state-4s9vbnjn/test.cpp:82:75: error: ‘struct AdventureBehaviorMgr::Record::<unnamed>’ has no member named ‘Step’
|
||||
82 | if(r.Leisure.Progressive && !r.Leisure.Route.empty() && r.Leisure.Step>=r.Leisure.Route.size() &&
|
||||
| ^~~~
|
||||
/tmp/vcore-adventure-state-4s9vbnjn/test.cpp:82:91: error: ‘struct AdventureBehaviorMgr::Record::<unnamed>’ has no member named ‘Route’
|
||||
82 | if(r.Leisure.Progressive && !r.Leisure.Route.empty() && r.Leisure.Step>=r.Leisure.Route.size() &&
|
||||
| ^~~~~
|
||||
/tmp/vcore-adventure-state-4s9vbnjn/test.cpp:83:44: error: ‘struct AdventureBehaviorMgr::Record::<unnamed>’ has no member named ‘Route’
|
||||
83 | player->GetExactDist(r.Leisure.Route.back())<=2)
|
||||
| ^~~~~
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_intent_state.py", line 108, in <module>
|
||||
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '-I', '/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/game/World', '/tmp/vcore-adventure-state-4s9vbnjn/test.cpp', '-o', '/tmp/vcore-adventure-state-4s9vbnjn/test']' returned non-zero exit status 1.
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp: In member function ‘bool AdventureBehaviorMgr::LeisureAvailable(Player*, const Record&, const AdventureMicroAction&) const’:
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:166:95: error: ‘FishingDirection’ was not declared in this scope
|
||||
166 | return rod && rod->GetTemplate()->GetSubClass()==ITEM_SUBCLASS_WEAPON_FISHING_POLE && FishingDirection(p,direction);
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp: In member function ‘bool AdventureBehaviorMgr::StartLeisure(Player*, Record&, const AdventureMicroAction&)’:
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:199:17: error: ‘FishingDirection’ was not declared in this scope
|
||||
199 | if(!FishingDirection(p,direction))return false;
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:216:7: error: ‘struct AdventureBehaviorMgr::Record::LeisureScene’ has no member named ‘Progressive’
|
||||
216 | s.Progressive=s.Kind=="work_search" || (r.Intent=="adventure" && site->IsArea && foot);
|
||||
| ^~~~~~~~~~~
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:217:10: error: ‘struct AdventureBehaviorMgr::Record::LeisureScene’ has no member named ‘Progressive’
|
||||
217 | if(s.Progressive)s.Route.resize(s.OutboundSteps);
|
||||
| ^~~~~~~~~~~
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp: In member function ‘bool AdventureBehaviorMgr::UpdateLeisure(Player*, Record&, uint32)’:
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:356:37: error: ‘ProfessionWorkAvailable’ was not declared in this scope
|
||||
356 | if(s.Kind=="work_search" && ProfessionWorkAvailable(p,r))
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:367:20: error: ‘struct AdventureBehaviorMgr::Record::LeisureScene’ has no member named ‘Progressive’
|
||||
367 | r.Detail=s.Progressive?"area search reached next observation point":"leisure outing completed at starting point";
|
||||
| ^~~~~~~~~~~
|
||||
/tmp/vcore-leisure-l3qqdidj/test.cpp:373:14: error: ‘struct AdventureBehaviorMgr::Record::LeisureScene’ has no member named ‘Progressive’
|
||||
373 | if(s.Progressive) {s.Route.resize(s.Step);return false;}
|
||||
| ^~~~~~~~~~~
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_leisure.py", line 196, in <module>
|
||||
subprocess.run(['c++','-std=c++17',str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '/tmp/vcore-leisure-l3qqdidj/test.cpp', '-o', '/tmp/vcore-leisure-l3qqdidj/test']' returned non-zero exit status 1.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp: In member function ‘AdventureSocialContext AdventureBehaviorMgr::SocialContext(Player*, Record&)’:
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp:38:63: error: ‘struct Profile’ has no member named ‘PrimaryProfessions’
|
||||
38 | location?location->Point.Category:"",profile?profile->PrimaryProfessions:AdventureProfessionPolicy::Professions{}};
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp:38:82: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
38 | location?location->Point.Category:"",profile?profile->PrimaryProfessions:AdventureProfessionPolicy::Professions{}};
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp:38:120: error: expected ‘}’ before ‘{’ token
|
||||
38 | location?location->Point.Category:"",profile?profile->PrimaryProfessions:AdventureProfessionPolicy::Professions{}};
|
||||
| ^
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp:33:12: note: to match this ‘{’
|
||||
33 | return {r.Anchor,r.AnchorMap,location&&location->Point.Category=="festival",
|
||||
| ^
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp:38:120: note: probably missing a comma or an operator before
|
||||
38 | location?location->Point.Category:"",profile?profile->PrimaryProfessions:AdventureProfessionPolicy::Professions{}};
|
||||
| ^
|
||||
/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp:38:122: error: could not convert ‘{r.AdventureBehaviorMgr::Record::Anchor, r.AdventureBehaviorMgr::Record::AnchorMap, ((location != 0) && std::operator==<char, char_traits<char>, allocator<char> >(location->Location::Point.Location::<unnamed struct>::Category, ((const char*)"festival"))), ((profile != 0) ? std::__cxx11::basic_string<char>(profile->Profile::Locale) : std::__cxx11::basic_string<char>(((const char*)"enUS"), std::allocator<char>())), r.AdventureBehaviorMgr::Record::Intent, r.AdventureBehaviorMgr::Record::Random, r.AdventureBehaviorMgr::Record::TargetHistory, r.AdventureBehaviorMgr::Record::VariantHistory, <lambda closure object>AdventureBehaviorMgr::SocialContext(Player*, Record&)::<lambda(const Position&, float)>{((AdventureBehaviorMgr*)this), player, (* & r)}, (std::operator!=<char, char_traits<char>, allocator<char> >(r.AdventureBehaviorMgr::Record::Intent, ((const char*)"rest")) || ((location != 0) && std::operator==<char, char_traits<char>, allocator<char> >(location->Location::Point.Location::<unnamed struct>::Category, ((const char*)"rest_ground")))), (((location != 0) && std::operator==<char, char_traits<char>, allocator<char> >(r.AdventureBehaviorMgr::Record::Intent, ((const char*)"economy"))) ? AdventureEconomyPolicy::LocationRequirement(location->Location::Point.Location::<unnamed struct>::Category) : std::__cxx11::basic_string<char>(((const char*)""), std::allocator<char>())), ((location != 0) ? std::__cxx11::basic_string<char>(location->Location::Point.Location::<unnamed struct>::Category) : std::__cxx11::basic_string<char>(((const char*)""), std::allocator<char>())), <expression error>}’ from ‘<brace-enclosed initializer list>’ to ‘AdventureSocialContext’
|
||||
38 | location?location->Point.Category:"",profile?profile->PrimaryProfessions:AdventureProfessionPolicy::Professions{}};
|
||||
| ^
|
||||
| |
|
||||
| <brace-enclosed initializer list>
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_rest_fire.py", line 74, in <module>
|
||||
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '-I', '/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/game/World', '/tmp/vcore-rest-fire-policy-he3ktm09/test.cpp', '-o', '/tmp/vcore-rest-fire-policy-he3ktm09/test']' returned non-zero exit status 1.
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp: In function ‘std::vector<AdventureSocialFlow::Step> Steps(const std::string&, uint32)’:
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:100:13: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
100 | if (AdventureProfessionPolicy::Recognized(kind)) return AdventureProfessionPolicy::Steps(kind,duration);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:100:65: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
100 | if (AdventureProfessionPolicy::Recognized(kind)) return AdventureProfessionPolicy::Steps(kind,duration);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp: In static member function ‘static bool AdventureSocialActions::Update(Player*, AdventureSocialScene&, uint32, AdventureSocialContext&)’:
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:256:8: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
256 | if(AdventureProfessionPolicy::Recognized(s.Kind) && (c.Intent!="profession" || !AdventureProfessionPolicy::Allowed(s.Kind,c.PrimaryProfessions)))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:256:60: error: ‘struct AdventureSocialContext’ has no member named ‘Intent’
|
||||
256 | if(AdventureProfessionPolicy::Recognized(s.Kind) && (c.Intent!="profession" || !AdventureProfessionPolicy::Allowed(s.Kind,c.PrimaryProfessions)))return false;
|
||||
| ^~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:256:85: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
256 | if(AdventureProfessionPolicy::Recognized(s.Kind) && (c.Intent!="profession" || !AdventureProfessionPolicy::Allowed(s.Kind,c.PrimaryProfessions)))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:256:129: error: ‘struct AdventureSocialContext’ has no member named ‘PrimaryProfessions’
|
||||
256 | if(AdventureProfessionPolicy::Recognized(s.Kind) && (c.Intent!="profession" || !AdventureProfessionPolicy::Allowed(s.Kind,c.PrimaryProfessions)))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:272:12: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
272 | if(AdventureProfessionPolicy::Recognized(s.Kind) && !AdventureProfessionTargets::Valid(p,target,s.Kind,c))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:272:62: error: ‘AdventureProfessionTargets’ has not been declared
|
||||
272 | if(AdventureProfessionPolicy::Recognized(s.Kind) && !AdventureProfessionTargets::Valid(p,target,s.Kind,c))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:363:27: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
363 | auto task=AdventureProfessionPolicy::Find(s.Kind);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:364:30: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
364 | if(!task || !AdventureProfessionPolicy::Allowed(s.Kind,c.PrimaryProfessions))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:364:74: error: ‘struct AdventureSocialContext’ has no member named ‘PrimaryProfessions’
|
||||
364 | if(!task || !AdventureProfessionPolicy::Allowed(s.Kind,c.PrimaryProfessions))return false;
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:365:30: error: ‘EMOTE_STATE_USE_STANDING’ was not declared in this scope; did you mean ‘EMOTE_ONESHOT_USE_STANDING’?
|
||||
365 | uint32 emote=EMOTE_STATE_USE_STANDING;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| EMOTE_ONESHOT_USE_STANDING
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:368:26: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
368 | case AdventureProfessionPolicy::Motion::Mine:emote=EMOTE_STATE_WORK_MINING;break;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:368:72: error: ‘EMOTE_STATE_WORK_MINING’ was not declared in this scope
|
||||
368 | case AdventureProfessionPolicy::Motion::Mine:emote=EMOTE_STATE_WORK_MINING;break;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:369:26: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
369 | case AdventureProfessionPolicy::Motion::Chop:emote=EMOTE_STATE_WORK_CHOPWOOD;break;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:369:72: error: ‘EMOTE_STATE_WORK_CHOPWOOD’ was not declared in this scope
|
||||
369 | case AdventureProfessionPolicy::Motion::Chop:emote=EMOTE_STATE_WORK_CHOPWOOD;break;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:370:26: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
370 | case AdventureProfessionPolicy::Motion::Kneel:emote=EMOTE_STATE_KNEEL;break;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:370:73: error: ‘EMOTE_STATE_KNEEL’ was not declared in this scope; did you mean ‘EMOTE_STATE_DANCE’?
|
||||
370 | case AdventureProfessionPolicy::Motion::Kneel:emote=EMOTE_STATE_KNEEL;break;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
| EMOTE_STATE_DANCE
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:433:8: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
433 | if(AdventureProfessionPolicy::Recognized(s.Kind))
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:435:22: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
435 | if(auto task=AdventureProfessionPolicy::Find(s.Kind))
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:439:38: error: ‘struct Position’ has no member named ‘Relocate’
|
||||
439 | Position departure;departure.Relocate(p);
|
||||
| ^~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:440:29: error: ‘struct WorldObject’ has no member named ‘GetAngle’
|
||||
440 | float angle=target->GetAngle(p);
|
||||
| ^~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:441:19: error: ‘struct Position’ has no member named ‘m_positionX’; did you mean ‘Position’?
|
||||
441 | departure.m_positionX+=std::cos(angle)*2;departure.m_positionY+=std::sin(angle)*2;
|
||||
| ^~~~~~~~~~~
|
||||
| Position
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:441:60: error: ‘struct Position’ has no member named ‘m_positionY’; did you mean ‘Position’?
|
||||
441 | departure.m_positionX+=std::cos(angle)*2;departure.m_positionY+=std::sin(angle)*2;
|
||||
| ^~~~~~~~~~~
|
||||
| Position
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:442:25: error: ‘struct Player’ has no member named ‘GetMap’
|
||||
442 | float height=p->GetMap()->GetHeight(p->GetPhaseShift(),departure.GetPositionX(),departure.GetPositionY(),p->GetPositionZ()+3,true,8);
|
||||
| ^~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:442:48: error: ‘struct Player’ has no member named ‘GetPhaseShift’
|
||||
442 | float height=p->GetMap()->GetHeight(p->GetPhaseShift(),departure.GetPositionX(),departure.GetPositionY(),p->GetPositionZ()+3,true,8);
|
||||
| ^~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:442:74: error: ‘struct Position’ has no member named ‘GetPositionX’; did you mean ‘Position’?
|
||||
442 | float height=p->GetMap()->GetHeight(p->GetPhaseShift(),departure.GetPositionX(),departure.GetPositionY(),p->GetPositionZ()+3,true,8);
|
||||
| ^~~~~~~~~~~~
|
||||
| Position
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:442:99: error: ‘struct Position’ has no member named ‘GetPositionY’; did you mean ‘Position’?
|
||||
442 | float height=p->GetMap()->GetHeight(p->GetPhaseShift(),departure.GetPositionX(),departure.GetPositionY(),p->GetPositionZ()+3,true,8);
|
||||
| ^~~~~~~~~~~~
|
||||
| Position
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:443:19: error: ‘INVALID_HEIGHT’ was not declared in this scope
|
||||
443 | if(height>INVALID_HEIGHT+1 && std::fabs(height-p->GetPositionZ())<=2)
|
||||
| ^~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-test-cy2ndyrb/test.cpp:445:23: error: ‘struct Position’ has no member named ‘m_positionZ’; did you mean ‘Position’?
|
||||
445 | departure.m_positionZ=height;
|
||||
| ^~~~~~~~~~~
|
||||
| Position
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_social.py", line 190, in <module>
|
||||
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '-I', '/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/game/World', '/tmp/vcore-social-test-cy2ndyrb/test.cpp', '-o', '/tmp/vcore-social-test-cy2ndyrb/test']' returned non-zero exit status 1.
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/tmp/vcore-social-fire-swu4udr3/test.cpp: In static member function ‘static bool AdventureSocialActions::Available(Player*, const AdventureMicroAction&, AdventureSocialContext&)’:
|
||||
/tmp/vcore-social-fire-swu4udr3/test.cpp:79:9: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
79 | if (AdventureProfessionPolicy::Recognized(kind)) return c.Intent=="profession" &&
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-fire-swu4udr3/test.cpp:80:9: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
80 | AdventureProfessionPolicy::Allowed(kind,c.PrimaryProfessions) &&
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-fire-swu4udr3/test.cpp:80:51: error: ‘struct AdventureSocialContext’ has no member named ‘PrimaryProfessions’
|
||||
80 | AdventureProfessionPolicy::Allowed(kind,c.PrimaryProfessions) &&
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-fire-swu4udr3/test.cpp:81:10: error: ‘AdventureProfessionPolicy’ has not been declared
|
||||
81 | (AdventureProfessionPolicy::Untargeted(kind)?!p->IsInWater() && !p->IsFalling():!AdventureProfessionTargets::Find(p,kind,c).empty());
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/tmp/vcore-social-fire-swu4udr3/test.cpp:81:90: error: ‘AdventureProfessionTargets’ has not been declared
|
||||
81 | (AdventureProfessionPolicy::Untargeted(kind)?!p->IsInWater() && !p->IsFalling():!AdventureProfessionTargets::Find(p,kind,c).empty());
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Traceback (most recent call last):
|
||||
File "/home/wow_admin/wow_cata_server/source/TrinityCore/tests/clientless/test_adventure_social_fire.py", line 86, in <module>
|
||||
subprocess.run(['c++','-std=c++17','-I',str(root/'src/server/game/World'),str(cpp),'-o',str(binary)],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['c++', '-std=c++17', '-I', '/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/game/World', '/tmp/vcore-social-fire-swu4udr3/test.cpp', '-o', '/tmp/vcore-social-fire-swu4udr3/test']' returned non-zero exit status 1.
|
||||
@@ -0,0 +1,18 @@
|
||||
from pathlib import Path
|
||||
import os,re,subprocess,sys
|
||||
config=Path('/home/wow_admin/wow_cata_server/server/debug/etc/worldserver.conf').read_text()
|
||||
match=re.search(r'^WorldDatabaseInfo\s*=\s*"([^"]+)"',config,re.M)
|
||||
if not match:raise SystemExit('Test world database configuration not found')
|
||||
host,port,user,password,database=match.group(1).split(';')
|
||||
args=['mysql','--protocol=TCP','--host='+host,'--port='+port,'--user='+user,'--database='+database,'--default-character-set=utf8mb4','--batch','--connect-timeout=10']
|
||||
env=os.environ.copy();env['MYSQL_PWD']=password
|
||||
query="SELECT a.action_key,a.kind,a.min_seconds,a.max_seconds,a.requirement,i.intent,i.weight FROM vcore_adventure_action a JOIN vcore_adventure_action_intent i USING(action_key) WHERE a.action_key IN ('rest_fire','campfire_rest','social_fire'); SELECT point_key,category,map,position_x,position_y,position_z FROM vcore_clientless_world_point WHERE enabled=1 AND category='rest_ground' LIMIT 10;"
|
||||
if sys.argv[1:] == ['apply']:
|
||||
migration=Path('/home/wow_admin/wow_cata_server/source/TrinityCore/sql/custom/world/2026_10_27_01_adventure_rest_fire.sql').read_text()
|
||||
query='START TRANSACTION;\n'+migration+'\n'+query+'\nCOMMIT;'
|
||||
elif sys.argv[1:] != ['inspect']:raise SystemExit('Use inspect or apply')
|
||||
result=subprocess.run(args,input=query,text=True,capture_output=True,env=env)
|
||||
print(result.stdout,end='')
|
||||
if result.returncode:
|
||||
print(result.stderr.replace(password,'[redacted]'),file=sys.stderr,end='')
|
||||
raise SystemExit(result.returncode)
|
||||
@@ -0,0 +1,189 @@
|
||||
# Kampf, Reaktionen und Interaktionen – vereinbarte Grundlage
|
||||
|
||||
Stand 27.10.2026. Neue Nutzervorgaben nach Abschluss der sieben Grundintents.
|
||||
Historische Vereinbarungen und aktueller Umsetzungsstand; siehe Nachtrag unten.
|
||||
Kampf, reaktives Verhalten, Bot-Spieler- und Bot-Bot-Interaktion gehören für den
|
||||
Nutzer zusammen. Bestehende Intent-, Reise- und Szeneninfrastruktur erhalten;
|
||||
DungeonBots bleiben unabhängig. Allgemeine Hinderniserkennung bleibt vertagt.
|
||||
|
||||
## Verbindliche Zielregeln
|
||||
|
||||
- Selbstverteidigung: die Kreatur, die zuerst tatsächlich Schaden am Bot
|
||||
verursacht, wird Fokusziel. Weitere Angreifer verdrängen sie nicht. Fokus bis
|
||||
zum Tod dieser Kreatur beibehalten. Ein zufälliger Zielwechsel ist unerwünscht.
|
||||
- Proaktiver Angriff: nächstgelegenes gültiges und zum aktuellen Intent passendes
|
||||
Ziel wählen. Die Intentregeln bestimmen zuerst die zulässige Zielmenge.
|
||||
- Abenteuer: nahe feindliche Kreaturen auf dem aktuellen Weg berücksichtigen;
|
||||
keine wahllose Jagd auf alles im allgemeinen Umkreis.
|
||||
- Beruf/Lederjagd: ein nahes geeignetes Tier wählen. Die bestehende Freigabe des
|
||||
betreffenden Hauptberufs im Lua-Profil gilt weiter. Arthoran hat derzeit nur
|
||||
mining und blacksmithing; diese Absprache erteilt ihm nicht automatisch
|
||||
skinning. Das tatsächliche Sammeln/Kürschnern bleibt gemäß bisheriger Regel
|
||||
performativ; der neu beauftragte Kampf selbst ist real.
|
||||
- Vor einem eigenständigen Angriff Eignung/Stärke prüfen, insbesondere deutlich
|
||||
überlegene Gegner ausschließen. Exakte Level-, Distanz-, Gesundheits- und
|
||||
Ressourcen-Grenzen sind noch nicht vom Nutzer festgelegt.
|
||||
|
||||
Noch auszugestalten: Verhalten, wenn ein Fokusziel despawnt, phasen-/kartenfremd
|
||||
oder dauerhaft unerreichbar wird; Selbstverteidigung gegen überlegene Gegner;
|
||||
weitere verbleibende Angreifer nach Tod des Erstangreifers. Nicht als bereits
|
||||
vereinbarte Zielwechsel-/Fluchtregeln ausgeben.
|
||||
|
||||
## Vom Nutzer bestätigte Ergänzungen
|
||||
|
||||
- Bei Berufsarbeit einen nahen feindlichen Gegner berücksichtigen, der den
|
||||
unmittelbaren Zugang zur konkret gewählten Ressource/Arbeitsstelle blockiert.
|
||||
- Konservativer Erstangriffsfilter: native Angriffserlaubnis, lebendig, richtige
|
||||
Phase, lokaler erreichbarer Kampfplatz, kein Weltboss; Elites zunächst meiden.
|
||||
Zusätzlich Leveldifferenz, aktuelle HP/Ressourcen und nahe weitere Gegner
|
||||
berücksichtigen. Grenzwerte als anpassbare Regeln führen.
|
||||
- Geselligkeit, Ruhe, Freizeit, Wirtschaften und der abstrahierte Instanzaufenthalt
|
||||
begründen von sich aus keine Jagd. Selbstverteidigung ist eine überlagernde
|
||||
Reaktion und benötigt keinen Wechsel zum Abenteuerintent.
|
||||
|
||||
## Verbindlicher Todesablauf
|
||||
|
||||
Seele freigeben, als Geist vom Friedhof zurück zur eigenen Leiche laufen und
|
||||
sich wiederbeleben, sobald native Reichweite und übrige native Bedingungen
|
||||
vorliegen. Ist kein Pfad verfügbar, ist nach fünf Minuten die Wiederbelebung
|
||||
am Friedhof erlaubt. Ein langsamer, aber funktionierender Leichenrücklauf ist
|
||||
nicht allein wegen Überschreitens von fünf Minuten ein fehlender Pfad.
|
||||
|
||||
Technische Ableitung: nach erreichbaren Punkten innerhalb des erlaubten
|
||||
Leichenradius suchen, nicht nur nach einem Pfad zur exakten Leichenposition.
|
||||
Die fünf Minuten als absolute Frist ab Freigabe/Ankunft am Friedhof behandeln,
|
||||
nicht bei Pfadversuchen oder Neustart neu beginnen. Die genaue Timerauslegung
|
||||
ist eine Umsetzungsauslegung des Friedhof-Fallbacks, keine zusätzliche explizite
|
||||
Antwort des Nutzers. Nach Wiederbelebung ausstehendes Verhalten sicher fortsetzen;
|
||||
keinen Endzeitblock durch die Todesphase künstlich verlängern.
|
||||
|
||||
## Bestätigte Quellgrundlagen
|
||||
|
||||
- `AI/PlayerAI/PlayerAI.cpp` und `.h`: gemeinsame PlayerAI-Helfer für Rollen,
|
||||
bekannte Zauberränge, native Wirkprüfung, Autoangriffe und Formen. Die große
|
||||
Klassen-/Spezialisierungsauswahl liegt derzeit privat in SimpleCharmedPlayerAI.
|
||||
Sie enthält situative Unterbrechungen, DoTs, Kombopunkte und Schutzfähigkeiten.
|
||||
- SimpleCharmedPlayerAI ist technisch eine Charm-KI mit Charmer-Zielwahl und
|
||||
Unterstützung dieses Charmers. Der Core installiert sie in Unit::UpdateCharmAI;
|
||||
mehrere Bossskripte leiten davon ab. Also nicht als völlig ungenutzt behandeln.
|
||||
Wiederverwendung erfordert Entkopplung dieser konkreten Charm-Steuerung;
|
||||
keine Unterstellung, der Nutzer wolle sie unverändert übernehmen.
|
||||
- Unit::DealDamage ruft DamageTaken/DamageDealt bei vorhandener UnitAI sowie
|
||||
den UnitScript-OnDamage-Hook auf. Diese Aufrufe liegen VOR dem abschließenden
|
||||
HP-Abzug, und nachfolgende Bedingungen können Schaden verhindern. Für die
|
||||
Regel 'zuerst tatsächlich Schaden verursacht' genügt ein ungeprüftes
|
||||
Vorab-Ereignis daher nicht. Nullschaden/Godmode/abgebrochene Treffer dürfen
|
||||
keinen falschen Erstangreifer festschreiben.
|
||||
- WorldSession::HandleRepopRequestOpcode führt BuildPlayerRepop und
|
||||
RepopAtGraveyard aus. HandleReclaimCorpseOpcode prüft Geiststatus,
|
||||
GetCorpseReclaimDelay, gleiche Karte und CORPSE_RECLAIM_RADIUS (aktuell 39 Yards),
|
||||
dann native Wiederbelebung und Corpse-Bones. Keine eigene großzügigere Distanz.
|
||||
- Der Nutzer lehnt den normalen Geistheiler ausdrücklich ab: beim Fallback
|
||||
nach fünf Minuten keine Wiederbelebungskrankheit und kein zusätzlicher
|
||||
Haltbarkeitsverlust. Nicht HandleSpiritHealerActivateOpcode/SendSpiritResurrect
|
||||
verwenden. Die native ResurrectPlayer-Funktion ohne Sickness und die saubere
|
||||
Corpse-Bones-/Geistzustandsbereinigung können dafür wiederverwendet werden.
|
||||
Der normale Leichenrücklauf bleibt zuerst vorgesehen.
|
||||
- PlayerScript bietet Chat- und gerichtete Textemote-Ereignisse. Vorhandene
|
||||
AdventureSocialActions stellen bereits Begrüßung, Gespräch und Reaktionen dar.
|
||||
Konkrete Regeln für Spieler-/Bot-Interaktionen sind noch weiter auszugestalten.
|
||||
|
||||
In dieser Vorprüfung wurden keine Kampf-/Todesabläufe implementiert oder live
|
||||
getestet und keine Server-/DB-Zustände verändert.
|
||||
|
||||
|
||||
## Nachtrag: Reparaturbesuch und Kampfausstattung
|
||||
|
||||
Nutzerauftrag: zusätzliche Wirtschafts-Mikroaktion bei einem echten Händler mit
|
||||
Reparaturfähigkeit. Sichtbare Szene rein performativ, keine Händler-/Kauf-/
|
||||
Reparaturpakete, kein Geldabzug. Nach erfolgreich abgeschlossenem Besuch repariert
|
||||
Hintergrundlogik alle Ausrüstungsgegenstände auf volle Haltbarkeit. Dies ist die
|
||||
explizit gewünschte Ausnahme von der bisherigen reinen Darstellung wirtschaftlicher
|
||||
Besuche; keine Reparaturkosten-/Zustandsplanung nötig.
|
||||
|
||||
Arthoran soll Kopien von Allitesters angelegter Rüstung und Waffen erhalten,
|
||||
alle stufengerechten Klassenfähigkeiten lernen, Talentpunkte sinnvoll innerhalb
|
||||
der Stufe-60-Grenze verteilen und passende Angriffe vorführen. Allitesters
|
||||
Originale bleiben unverändert. Beide sind Krieger; Vorprüfung ergab Zorn-Set und
|
||||
Ashkandi, passend zu einem Waffen-Build. Quelle ist Stufe70, Arthoran bleibt60.
|
||||
Die native Level-60-Talenttabelle erlaubt 26 Punkte, keine überhöhte Freischaltung
|
||||
aller Talentbäume. Kampfübung an einer tatsächlich vorhandenen Stufe-60-Puppe;
|
||||
damit wird noch keine vollständige autonome Kampf-/Reaktions-KI behauptet.
|
||||
|
||||
## Technischer Umsetzungsstand nach Kampfausstattung
|
||||
|
||||
Reparaturaktion implementiert; native IsArmorer-Prüfung, erreichbare freundliche
|
||||
NPCs und bestehende Ankunfts-/Szenenprüfung. Einmal nach erfolgreichem Besuch
|
||||
DurabilityRepairAll(false, 1.0f, false), ohne Kosten oder Interaktionspakete.
|
||||
|
||||
Arthoran erhielt neun neue Iteminstanzen aus Allitesters angelegtem Zorn-Set
|
||||
und Ashkandi. Frühere Gegenstände bleiben im Inventar; Allitesters vollständiger
|
||||
Inventar-/Item-/Zauber-/Talentsnapshot blieb unverändert. Native Klassen- und
|
||||
Stufenprüfung, Plattenkompetenz und Haltungen sowie 26 Waffen-Talentpunkte
|
||||
über LearnTalent, Baum 746. Keine fremden Spezialisierungsfähigkeiten freischalten.
|
||||
|
||||
Begrenzte Trainingsübung über PlayerAI-Helfer; nur tatsächliche passende
|
||||
Trainingspuppen, native Sicht-/Phasen-/Angriffserlaubnis. Keine Phasenänderung.
|
||||
Phase169 ist DEFAULT_PHASE; die erste Fehlposition hatte fehlende Sichtlinie.
|
||||
Nach administrativer Offline-Positionierung vor der echten Puppe314147 waren
|
||||
Phase, Sichtbarkeit und Sichtlinie gültig. Live wurden unter anderem Heroischer
|
||||
Stoß78, Verwunden772, Tödlicher Stoß12294 und Überwältigen7384 von Spell::prepare
|
||||
mit SPELL_CAST_OK(255) angenommen. Das belegt die begrenzte Übung, keine
|
||||
fertige autonome Selbstverteidigungs-, Todes- oder Interaktionssteuerung.
|
||||
|
||||
Debug-Build erfolgreich installiert; 48 Testskripte erfolgreich.
|
||||
|
||||
Live-Reparatur erfolgreich: reguläre lokale MMAP-Anreise zu Marda Weller1287,
|
||||
vollständige Szene und ECONOMY_REPAIR_COMPLETE. Nach saveall alle neun zuvor
|
||||
halbierten Kopien wieder voll, Geld0 und Allitesters Snapshot unverändert.
|
||||
|
||||
## Ausbau: Training, Erstangriffe und Todesreaktion
|
||||
|
||||
AdventureCombatMgr überlagert den Lua-Adventure-Controller während Kampf/Tod.
|
||||
Generischer ClientlessPlayerMgr übergibt ausschließlich tatsächlich nach HP-Abzug
|
||||
entstandene Schäden als GUID-Ereignisse. Mutex-Queue trennt Map-Worker und
|
||||
World-Thread; andere Controller bleiben bei ihrer bisherigen Standardfunktion.
|
||||
Der erste tatsächliche Kreaturenangreifer wird festgehalten. Weitere Angreifer
|
||||
warten in Schadensreihenfolge, bis der Fokus tot ist. Phasenverlust/Despawn bzw.
|
||||
20 Sekunden unerreichbarer Fokus beenden eine nicht mehr ausführbare Verfolgung.
|
||||
Spieler und von Spielern kontrollierte Kreaturen sind nicht Gegenstand dieses Ausbaus.
|
||||
|
||||
Automatischer Erstangriff im Abenteuer nur auf nächstgelegenen passenden Gegner
|
||||
im lokalen20Yards-Umkreis und8Yards-Korridor des tatsächlichen aktiven MMAP-Wegs.
|
||||
Für Kürschnerei nur bei Profilrecht und lebendem BEAST mit nativer SkinLootId;
|
||||
Arthoran erhält dieses Recht weiterhin nicht. Andere Intents lösen keine Jagd aus.
|
||||
Vorläufiger konservativer Filter: höchstens+2Level, mindestens60%HP und bei
|
||||
Manaklassen30%Mana, keine Elites/Weltbosse, höchstens ein Gegner im12Yards-Umfeld,
|
||||
kein bereits fremd bekämpfter Gegner. Native Phase/Sicht/Angriffserlaubnis und
|
||||
vollständiger unverdächtiger MMAP-Anschluss bleiben Voraussetzung.
|
||||
|
||||
Kampf nutzt native Autoangriffe und für Krieger die stufengelernten Fähigkeiten,
|
||||
Ressourcen und Abklingzeiten. Keine künstlichen Ressourcen-/Schadenswerte.
|
||||
Andere Klassen erhalten hier zunächst Autoangriffe; eigene Rotationen folgen.
|
||||
Training ist Freizeit-Aktion leisure_training60–180Sekunden an echter erreichbarer
|
||||
Puppe im60Yards-Umkreis, begrenzt zusätzlich durch aktuelle Intentfrist.
|
||||
Echte Selbstverteidigung kann Training unterbrechen. Keine Dummy-Spawns/Phasenänderungen.
|
||||
|
||||
Tod über native Freigabe- und Leichenaufnahmehandler. Persistierter GhostTime
|
||||
bestimmt sowohl native Aufnahmefrist als auch Fünf-Minuten-Fallback; Charakter
|
||||
und Leichenzeitpunkt werden nach Freigabe gespeichert. Mehrere mögliche Ziele
|
||||
innerhalb39Yards werden geprüft. Gescheiterte Bewegungspunkte werden für diesen
|
||||
Leichenlauf gemieden. Bei funktionierendem Pfad keine pauschale Zeitbegrenzung.
|
||||
Fallback: erst nach300Sekunden ohne passenden Pfad native Friedhofsrückkehr,
|
||||
danach ResurrectPlayer(.5,false) und SpawnCorpseBones, keine Geistheiler-Interaktion,
|
||||
keine Wiederbelebungskrankheit oder zusätzliche Haltbarkeitsänderung. Normale
|
||||
Kampfschäden bleiben erhalten. Intent-Endzeiten werden durch Reaktionen nicht verlängert.
|
||||
|
||||
Diagnose: clientless combat train <guid> [seconds], attack <guid> <spawn-id>,
|
||||
testdeath <guid>, stop <guid>. Testdeath nutzt ausdrücklich einen nativen Testtod
|
||||
für einen verwalteten Bot, ohne zusätzlichen Haltbarkeitsverlust.
|
||||
51 Testskripte bestanden; Live-Ergebnisse separat ergänzen.
|
||||
|
||||
Live-Abschluss: Trainingsszene regulär nach60Sekunden beendet; Stufe58-Bär42336
|
||||
(spawn300425) nativ besiegt und Respawn registriert. Erster Testtod: mangels
|
||||
akzeptiertem MMAP-Rückweg volle300Sekunden gewartet, malusfreie Friedhofs-
|
||||
wiederbelebung bestätigt. Zweiter Testtod naheFriedhof: tatsächlicher37.40Yards-
|
||||
Geisterlauf und nativeLeichenaufnahme. NachLogout lebendHP4340 ohneLeiche oder
|
||||
Aura15007 gespeichert. KeineUhrabkürzung, keinNormalreisebeleg durchTestpositionierung.
|
||||
Belege: checkpoints/2026-10-27-combat/. Mehrfachangreifer undNeustart während
|
||||
Leichenlauf produktiv mitAdaptern geprüft, nochkeine entsprechendeLiveabnahme.
|
||||
@@ -0,0 +1,167 @@
|
||||
# Wirtschaften-Intent
|
||||
|
||||
Technischer Name: `economy`. Diese Ausbaustufe stellt wirtschaftliche Besuche
|
||||
dar: regulär anreisen, einen passenden Dienstleister aufsuchen, ruhig schauen,
|
||||
reden oder warten, sich verabschieden und den Schalter wieder verlassen.
|
||||
Es gibt keine tatsächlichen Käufe, Verkäufe, Auktionen, Gebote, Banktransfers
|
||||
oder Geldbewegungen. Es werden keine entsprechenden Interaktions- oder
|
||||
Transaktionshandler aufgerufen und keine wirtschaftlichen Fenster simuliert.
|
||||
|
||||
## Mikroaktionen
|
||||
|
||||
| Aktion | Ablauf |
|
||||
|---|---|
|
||||
| `economy_repair` | Einen echten reparaturfähigen Händler aufsuchen; nach abgeschlossener Szene sämtliche Ausrüstung kostenlos nativ reparieren. Keine Händlerinteraktion. |
|
||||
| `economy_vendor_visit` | Einen freundlichen erreichbaren Händler aufsuchen, kurz umsehen, verabschieden und zurücktreten. |
|
||||
| `economy_goods` | Beim Händler länger Waren betrachten. Die Darstellung richtet sich zum tatsächlichen Händler; eine passende Auslage ist keine Voraussetzung. |
|
||||
| `economy_trade` | Begrüßen, Handelsgespräch darstellen, zuhören, nicken und verabschieden. |
|
||||
| `economy_compare` | Zwei verschiedene erreichbare Händler nacheinander besuchen und Angebote betrachten. Ein einzelner Händler genügt nicht. |
|
||||
| `economy_auction_visit` | Einen tatsächlichen Auktionator aufsuchen und das Auktionshaus kurz besuchen. |
|
||||
| `economy_auctions` | Beim Auktionator eine längere ruhige Prüfphase darstellen. |
|
||||
| `economy_bank_visit` | Einen tatsächlichen Bankier aufsuchen und die Bank kurz besuchen. |
|
||||
| `economy_banking` | Am Bankschalter Gespräch und Prüfung darstellen. |
|
||||
| `economy_supplies` | Ruhige Prüfung der Vorräte darstellen, ohne Inventarzugriff oder Änderungen. |
|
||||
| `economy_wait` | Bei einem passenden Dienstleister auf Bedienung warten. Kein Warteschlangensystem. |
|
||||
| `economy_finish` | Einen zuvor besuchten, noch anwesenden Dienstleister verabschieden und den Schalter verlassen. |
|
||||
|
||||
## Ziele und Ausführung
|
||||
|
||||
Migration: `sql/custom/world/2026_10_27_03_adventure_economy.sql` nach den
|
||||
bisherigen Intent-Migrationen. Sie ergänzt Katalogeinträge mit `INSERT IGNORE`;
|
||||
bearbeitete Definitionen, Gewichte und Positionen bleiben erhalten.
|
||||
|
||||
Der Tagesplan entscheidet zuerst anhand des Profils über das Vorhaben. Erst
|
||||
anschließend wählt der Ortsplaner ein passendes vorhandenes importiertes Ziel.
|
||||
Ein fehlender Händler-Eintrag darf den Intent im Tagesplan nicht ausschließen.
|
||||
Siedlungen, Gebiete und bekannte Serviceorte werden für Wirtschaften höher
|
||||
gewichtet; auch andere importierte Orte sind grundsätzlich verwendbar.
|
||||
Ausdrücklich eingestellte Ortsgewichte einschließlich Null behalten Vorrang.
|
||||
Fraktionszuordnung und normale Reiseprüfungen bleiben bestehen.
|
||||
|
||||
`stormwind_economy_market`, `stormwind_economy_bank` und
|
||||
`stormwind_economy_auction` sind zusätzliche gezielte Testpunkte. Sie begrenzen
|
||||
weder die Ortswahl noch die Verfügbarkeit des Intents für andere Fraktionen.
|
||||
An jedem anderen passenden Ort findet der Bot die wirklichen Dienstleister
|
||||
über `ClientlessPerceptionMgr`: Suchradius 100 Yards, native Fähigkeiten,
|
||||
Freundlichkeit, Phase und anschließende geprüfte lokale Annäherung.
|
||||
Dafür müssen keine einzelnen Händler oder deren Aufenthaltsorte vorgegeben
|
||||
werden. Es wird kein Handels-NPC aus einer Datenbankposition nachgespielt.
|
||||
|
||||
Die vorhandenen sozialen Fähigkeiten bleiben gemeinsam genutzt. Zielwahl
|
||||
prüft die nativen Rollen `VENDOR`, `BANKER` oder `AUCTIONEER`, Freundlichkeit,
|
||||
Lebendigkeit, Kampfzustand, Phase und den Aufenthaltsbereich. Vor der Annäherung muss der Dienstleister
|
||||
noch nicht vom Ankunftspunkt aus sichtbar sein. Der mögliche Gesprächsplatz
|
||||
und die tatsächliche Szene benötigen eine native Sichtlinie auf Augenhöhe
|
||||
über den Schalter hinweg. Wände bleiben blockierend.
|
||||
Nur ausdrücklich spezialisierte Testpunkte grenzen die Rollen zusätzlich ein: Händler im Marktbereich,
|
||||
Bankiers in der Bank, Auktionatoren im Auktionshaus. Das gilt auch für
|
||||
Warte- und Abschiedsszenen. Andere Bots sind keine Dienstleister. Nicht erreichbare Schalter werden nicht
|
||||
als Besuch gezählt. Die Prüfung bleibt während der Szene aktiv. Händlervergleiche
|
||||
wechseln ausdrücklich zu einer anderen GUID. Wiederholungsdämpfung berücksichtigt
|
||||
Aktionen, Ziele und Textvarianten.
|
||||
|
||||
Nach dem Abschied läuft der Bot über MMAP zum Ankunftspunkt zurück. Nur die
|
||||
bestätigte tatsächliche Ankunft erzeugt `ECONOMY_VISIT_COMPLETE`; ein gescheiterter
|
||||
Rückweg täuscht keinen Abschluss vor. Fehlende Dienstleister lösen eine reguläre
|
||||
Suche nach einem anderen Wirtschaftsziel aus. Das gilt auch, wenn keine
|
||||
der möglichen Serviceannäherungen einen erreichbaren Gesprächsplatz findet. Kampf, Intentwechsel und Offline
|
||||
beenden die Szene über das bestehende Reset-Verfahren.
|
||||
|
||||
Der technische Intentname ist auch für manuelle Aufträge und neue Tagespläne
|
||||
verfügbar. `activity_affinity.economy` steuert die Tagesplangewichtung
|
||||
(Standard 0,5; Arthoran 0,45). Bereits gespeicherte vollständige Tagespläne
|
||||
werden nicht verändert. Lokale Servicewege werden im Gehmodus und innerhalb
|
||||
der Location-Zone ausgeführt. Die Intentauswahl fragt den Ortskatalog nicht ab.
|
||||
|
||||
Beispiel für die Testserverkonsole:
|
||||
|
||||
```
|
||||
clientless adventure intent 26 economy stormwind_economy_market 3600
|
||||
clientless adventure micro 26 economy_compare
|
||||
clientless adventure status 26
|
||||
```
|
||||
|
||||
Die gezielte Mikroaktion setzt einen bereits angekommenen sicheren Bot voraus.
|
||||
|
||||
## Prüfung
|
||||
|
||||
Automatisierte Prüfungen führen die produktive Rollen-/Umgebungswahl und
|
||||
Gestensequenzen aus, einschließlich Rollenverlust, zweitem Händler, verweigerter
|
||||
Navigation und bestätigter Abreise. Der Katalogtest führt die Migration aus und
|
||||
prüft Referenzen, Allianzgrenzen, native Servicevoraussetzungen und Idempotenz.
|
||||
Eine erfolgreiche Kompilierung allein ist keine Ingame-Abnahme.
|
||||
|
||||
## Live-Prüfung am 27.10.2026
|
||||
|
||||
Der Testserver wurde mit `-j10` gebaut, installiert und bis zur frischen
|
||||
Ready-Meldung mit lebendem Prozess und Port 8085 geprüft. Alle 29
|
||||
Clientless-Testskripte bestanden.
|
||||
|
||||
- Händlervergleich vollständig: Edna Mullby (1286) und Thurman Mullby (1285),
|
||||
unterschiedliche tatsächliche GUIDs, Gesprächspositionen und Gesten,
|
||||
`ECONOMY_COMPARE_NEXT`, Abreise und `ECONOMY_VISIT_COMPLETE visits=2`.
|
||||
- Auktionshaus vollständig: Auctioneer Chilton (8670), längere Prüfphase,
|
||||
Abschied, Abreise und bestätigter Abschluss.
|
||||
- Bank vollständig: Scott Westmill (43820) sowie ein automatisch ausgewählter
|
||||
weiterer Bankbesuch; tatsächliche Kundenseite, Abschied und bestätigter
|
||||
Rückweg. Die anfängliche Sichtprüfung auf den Körperpunkt hinter dem
|
||||
Schalter wurde durch geprüfte Annäherung und native Sicht auf Augenhöhe
|
||||
ersetzt. Dabei wird keine Kollisions- oder Sichtlinienprüfung umgangen.
|
||||
- Im finalen Stand wählte Arthoran nach dem Login selbstständig
|
||||
`economy_banking` bei Thomas Westmill (43822); lokale Wege liefen mit
|
||||
`walk=1`. Bank-, Händler- und Auktionshausrollen bleiben nach Location getrennt.
|
||||
- Gespeichertes Geld und vollständige Inventarzuordnung einschließlich
|
||||
Gegenstands-IDs und Stapelzahlen waren nach den drei Servicebereichen
|
||||
bytegleich zum Ausgangsstand. Temporäre Login-Profiländerungen wurden
|
||||
zurückgesetzt; der normale Initial-Intent bleibt unverändert.
|
||||
|
||||
Die technische Live-Prüfung ersetzt nicht die visuelle Ingame-Abnahme.
|
||||
Weitere Städte und eine Prüfung verschiedener gleichzeitig anwesender Bots
|
||||
sind noch nicht durchgeführt.
|
||||
|
||||
Auch der abschließende automatische Bankablauf im finalen Build endete mit
|
||||
`ECONOMY_VISIT_COMPLETE action=economy_banking visits=1`; anschließend
|
||||
begann selbstständig ein weiterer Besuch bei Newton Burnside (2456).
|
||||
|
||||
## Korrektur der Planungshierarchie und des Imports
|
||||
|
||||
Die anfängliche Einschränkung auf drei Wirtschaftstestpunkte und die davon
|
||||
abhängige Tagesplanauswahl waren falsch. Sie wurden entfernt. Der Ortsimport
|
||||
hatte bereits stattgefunden; zum Diagnosezeitpunkt gab es 2.647 aktive Orte.
|
||||
Ein separater Fehler las `SMALLINT`-Karten-IDs mit `GetUInt32`, was im Debug-Core
|
||||
Null ergab. Dadurch wurden unter anderem Kalimdor- und Scherbenweltorte
|
||||
fälschlich Karte 0 zugeordnet. Import und Katalogladen verwenden nun
|
||||
`GetUInt16`. Die Weltdatenbank-Quelldaten selbst werden nicht geändert.
|
||||
|
||||
`clientless adventure repairimport` ergänzt den normalen Import um eine
|
||||
gezielte Reparatur: Nur Datensätze, deren Quelle, Koordinaten, Kategorie und
|
||||
Metadaten noch den alten automatisch erzeugten Werten entsprechen, werden
|
||||
berichtigt. Manuelle Orte und abweichende Bearbeitungen bleiben erhalten.
|
||||
Karten-, Gebiets-, Regions- und Fraktionsdaten werden neu abgeleitet; bei
|
||||
Wachen-POIs dient ein naher nativer Höhenanker statt der obersten Dachfläche
|
||||
als Bezug. Der normale Import bleibt additiv.
|
||||
|
||||
Die gezielte Reparatur wurde auf dem Testserver zweimal ausgeführt. Sie
|
||||
berichtigte 2.159 bestehende automatisch erzeugte Datensätze und ergänzte
|
||||
217 nun verwertbare Quellorte (insgesamt 2.864 aktive Orte). Alle 16 manuellen
|
||||
Datensätze blieben vollständig unverändert. Der zweite Lauf war bytegleich
|
||||
zum ersten Ergebnis. Orgrimmar und Donnerfels liegen auf Karte 1, Unterstadt
|
||||
auf Karte 0, Silbermond auf Karte 530; alle vier sind als Horde-Orte zugeordnet.
|
||||
|
||||
Der abschließende Test nutzte ausschließlich den gewöhnlichen importierten
|
||||
Sturmwind-Ort `poi_tele_954`: Arthoran nahm über die generische Wahrnehmung
|
||||
einen etwa 68 Yards entfernten Bankier wahr, erreichte ihn über native
|
||||
Navigation im Gehmodus und begann selbstständig eine Bankgesprächsszene.
|
||||
Ein spezieller Bank-Testpunkt wurde für diesen Ablauf nicht verwendet.
|
||||
Build mit `-j10`, Installation und Neustart waren erfolgreich; alle 30
|
||||
Clientless-Testskripte bestanden. Eine Reise mit einem Horde-Bot ist dadurch
|
||||
noch nicht ingame geprüft.
|
||||
|
||||
Die anschließende Abenteuer-Migration überführt die allgemeinen Wirtschafts-
|
||||
gewichte in ausdrückliche Location-/Intent-Katalogeinträge. Ein im Code
|
||||
versteckter Kategorie-Fallback entfällt damit; vorhandene angepasste Gewichte
|
||||
einschließlich Null behalten Vorrang.
|
||||
|
||||
Ergänzung: `2026_10_27_08_adventure_repair.sql` ergänzt den Reparaturbesuch.
|
||||
Die vollständige Haltbarkeitswiederherstellung ist die ausdrücklich gewünschte
|
||||
Ausnahme von der rein performativen Wirtschaftsdarstellung.
|
||||
@@ -0,0 +1,226 @@
|
||||
# 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. Für den Rückfall bei fehlendem Bodenweg kann der tatsächliche sichere
|
||||
Aufenthaltsort als Abflugpunkt dienen; dabei gelten dieselben nativen Startprüfungen.
|
||||
|
||||
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.
|
||||
|
||||
## Optionale Straßenausstiege und Flug als Rückfall
|
||||
|
||||
Ein vom Planer vorgeschlagener virtueller Exit ist ein optionaler Anschluss.
|
||||
Die Ausführung behält die aufgezeichnete Kante bis zum nächsten regulären Node
|
||||
in ihrer gewählten Richtung bei, auch nach einem virtuellen Einstieg mitten auf
|
||||
der Kante. Alle sechs Sekunden prüft sie von der aktuellen Position den lokalen
|
||||
MMAP-Anschluss zum Reiseziel. Während einer negativen Prüfung läuft die bestehende
|
||||
Straßenspline weiter: kein Halt, kein Umdrehen, keine Sperre der Kante und kein
|
||||
Verbrauch der fünf Recovery-Versuche. Das gilt auch nach beliebig vielen negativen
|
||||
Prüfungen. Nur ein vollständiger Anschluss mit höchstens 500 Yards Pfadlänge und
|
||||
höchstens 1,5 Yards Zielabweichung löst den lokalen Ausstieg aus.
|
||||
|
||||
Scheitert ein bereits gestarteter lokaler Ausstieg, versucht die Ausführung den
|
||||
Wiedereinstieg am nächsten noch nicht passierten Straßenpunkt über MMAP. Den
|
||||
Fortschritt bestimmt der Index der laufenden Spline, nicht der geometrisch nächste
|
||||
Punkt, der auf sich kreuzenden Straßen hinter dem Bot liegen könnte. Ein tatsächlich
|
||||
nicht mehr erreichbarer Wiedereinstieg ist dagegen ein Bewegungsfehler und darf
|
||||
Recovery auslösen. Ein geplantes Flugziel ab einem virtuellen Exit bleibt eine
|
||||
optionale normale Flugalternative mit den üblichen Auswahlregeln.
|
||||
|
||||
Wird kein Exit nutzbar, erreicht der Bot den regulären Endnode. Erst dort wird die
|
||||
Fortsetzung neu geplant; das Erreichen dieses Nodes zählt nicht als Fehlversuch.
|
||||
Nach vollständig durchfahrener Kante wird deren erfolglose geometrische
|
||||
Ausstiegsannahme für diese Reiserichtung nicht erneut als gesicherte Zieloption
|
||||
geplant. Die Kante bleibt befahrbar und bei späteren Durchfahrten werden weiterhin
|
||||
Live-Prüfungen durchgeführt. So führen dieselben unbelegten Ausstiegsannahmen
|
||||
nicht zu endlosen Rundreisen zwischen den regulären Endnodes.
|
||||
Ein angeforderter Intentwechsel kann dort wie an anderen sicheren Nodes stattfinden.
|
||||
|
||||
Wenn keine reguläre Reise geplant werden kann, eine nutzbare Teilroute endet oder
|
||||
die tatsächliche Bewegungs-Recovery ausgeschöpft ist, prüft die Ausführung freien
|
||||
Flug zum Ziel auf derselben Karte. Für diesen Rückfall gelten weder die normale
|
||||
Mindestdistanz noch Zonenpräferenzen, Straßenkostenvorteile oder die normale
|
||||
20.000-Yards-Auswahlschranke. Flugberechtigung, gelernte Flugmounts, native
|
||||
Zauberprüfungen, Geometrie, sichere Landung und der Fußweg vom Landeplatz zum Ziel
|
||||
bleiben erforderlich. Eine erfolgreich gestartete Rückfalloption wird innerhalb
|
||||
derselben Reiseaktion nicht endlos erneut gestartet.
|
||||
|
||||
Die Diagnoseeinträge heißen `GROUND_EXIT_CHECK`, `GROUND_EXIT_ARRIVED`,
|
||||
`FLIGHT_FALLBACK_UNAVAILABLE` und `FLIGHT_FALLBACK_STARTED`.
|
||||
|
||||
Regressionstests:
|
||||
|
||||
```bash
|
||||
python3 tests/clientless/test_ground_exit_continuation.py
|
||||
python3 tests/clientless/test_free_flight_planner.py
|
||||
python3 tests/clientless/test_flight_policy.py
|
||||
python3 tests/clientless/test_adventure_graph_handover.py
|
||||
```
|
||||
|
||||
Sie führen produktive Methoden mit kontrollierten Bewegungs- und MMAP-Daten aus.
|
||||
Unter anderem bleiben bei zwanzig negativen Exitprüfungen Route, Straßenfahrt,
|
||||
Richtung, Sperrlisten und Recovery-Zähler erhalten; ein später gültiger Anschluss
|
||||
führt zum ursprünglichen Ziel. Das ersetzt keine visuelle Abnahme im Spiel.
|
||||
|
||||
Prüfstand vom 27.10.2026 für diese Korrektur: Alle 21 Skripte unter
|
||||
`tests/clientless/test_*.py` bestanden. Der bestehende Debug-Build wurde mit
|
||||
`cmake --build /home/wow_admin/wow_cata_server/build/debug -j10` erfolgreich
|
||||
gebaut und über die vorhandene CMake-Installation übernommen. Der frische
|
||||
Testserver-Start erreichte `(worldserver-daemon) ready...`; Prozess und Listener
|
||||
auf Port 8085 wurden danach bestätigt. Arthorans konkrete Hafen–Tor–Tavernenreise
|
||||
ist mit diesem Stand noch nicht im Spiel abgenommen.
|
||||
|
||||
## 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.
|
||||
Im normalen Flug wird die nächste Spline bis zu 600 ms vor dem Ende der laufenden
|
||||
Spline ab der aktuellen Position gestartet. Dadurch entsteht zwischen den
|
||||
Abschnitten kein regulärer Halt. Der neue Korridor wird vollständig geprüft;
|
||||
Landungen und die konservative Rückkehr über die Flugspur erreichen weiterhin
|
||||
ihre Endpunkte. Die Wegstrecke zählt tatsächlich geflogene Bewegung, nicht die
|
||||
überlappenden Längen der erteilten Bewegungsaufträge. `status` zeigt mit
|
||||
`handoffs` die Anzahl der Übergaben während einer noch laufenden Spline.
|
||||
|
||||
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
|
||||
python3 tests/clientless/test_flight_handoff.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.
|
||||
|
||||
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`.
|
||||
|
||||
## Sichtprüfung und Abschluss
|
||||
|
||||
Beim beobachteten Flug Goldhain → Nordhain fiel zunächst ein kurzes Anhalten
|
||||
zwischen den Abschnitten auf. Die vorzeitige Spline-Übergabe behebt diese Lücke.
|
||||
Der anschließende Rückflug Nordhain → Goldhain landete am 26.10.2026 um 18:09:14
|
||||
nach 36 Abschnitten mit Zielabweichung 0,00. Das Log bestätigt Übergaben während
|
||||
noch laufender Splines. Der Nutzer hat den Flug anschließend ausdrücklich als
|
||||
sauber und flüssig bestätigt.
|
||||
|
||||
Damit ist der Entwicklungsmeilenstein Navigation und Fernreisen einschließlich
|
||||
unabhängiger Flugreisen abgenommen. Die oben genannten Grenzen der begrenzten
|
||||
Flugnavigation bleiben bestehen; weitere Strecken können schrittweise ergänzt
|
||||
und geprüft werden. Mikroaktionen folgen als eigener Entwicklungsschritt.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,212 @@
|
||||
# Instanzbesuche
|
||||
|
||||
Stand: 27.10.2026. Verbindliche Nutzervorgaben und Umsetzung des Intents `instance`. Eigenständiger AdventureBot-Intent,
|
||||
getrennt vom offenen Abenteuer und von DungeonBots. Keine Kampf-KI nötig.
|
||||
|
||||
## Zeitmodell
|
||||
|
||||
Die Besuchsdauer ergibt sich aus dem verbleibenden Zeitblock, für den der
|
||||
Instanzeingang als Location gewählt wurde. Es gibt keine zusätzliche volle
|
||||
Aufenthaltsdauer ab Ankunft. Anreise und Vorbereitung verbrauchen Blockzeit.
|
||||
Die letzten fünf Minuten sind für Rückkehr, scheinbare Orientierung und Rast
|
||||
nach dem Besuch reserviert.
|
||||
|
||||
Nutzerbeispiel: ein Stundenblock, 40 Minuten Anreise, 15 Minuten Aufenthalt
|
||||
in der Instanz, anschließend fünf Minuten Orientierung/Rast draußen.
|
||||
Maßgeblich bleiben absolute Zeitpunkte: Blockende und Beginn der Nachruhe
|
||||
(Blockende minus 300 Sekunden). Serverausfall/Offlinezeit verlängern den Block
|
||||
nicht; ein Neustart startet den Besuch nicht erneut.
|
||||
|
||||
Noch technisch auszugestaltender Randfall: Ist bei Ankunft bereits die
|
||||
Nachruhephase erreicht, darf kein negativer oder künstlich verlängerter
|
||||
Instanzaufenthalt entstehen. Naheliegende Umsetzung: Eintritt auslassen und
|
||||
verbleibende Zeit zur Nachruhe nutzen. Das ist eine Implementierungsableitung,
|
||||
keine zusätzliche ausdrücklich beantwortete Nutzerentscheidung.
|
||||
|
||||
## Sichtbarer und verborgener Ablauf
|
||||
|
||||
Reguläre Anreise zum Eingang, kurze passende Vorbereitung, tatsächlicher
|
||||
bestätigter Eintritt über den vorhandenen Übergang. Fehlgeschlagener Eintritt
|
||||
startet keine verborgene Aufenthaltsphase.
|
||||
|
||||
Arthoran wartet direkt hinter dem Eingang in seiner nativen Instanzkopie.
|
||||
Er durchläuft den Dungeon nicht, kämpft nicht und simuliert keine Beute oder
|
||||
Erfolge. Unabhängige Spieler/Gruppen sollen ihn beim eigenen Eintritt nicht
|
||||
sehen. Native Instanzzuweisung und vorhandene Bindungen beachten; bloß die
|
||||
Karten-ID zu vergleichen genügt nicht, die Instanz-ID ist ebenfalls relevant.
|
||||
Keine gemeinsame Bot-Gruppe oder sonstige geteilte Bindung für diesen Solobesuch
|
||||
neu erzeugen. Bestehende DungeonBots bleiben unabhängig.
|
||||
|
||||
Beim Neustart loggt er am gespeicherten Instanzstandort wieder ein und wartet
|
||||
nur bis zum ursprünglichen Rückkehrzeitpunkt. Dazu müssen Besuchsphase,
|
||||
Blockende, Instanz-/Eingangs-/Ausgangszuordnung erhalten bleiben; ist der
|
||||
Zeitpunkt inzwischen verstrichen, folgt die Rückkehr ohne neue Wartezeit.
|
||||
|
||||
## Orte und Rückkehr
|
||||
|
||||
Die Instanzinnenräume werden keine normalen Aufenthaltslocations.
|
||||
Die vorhandenen Eingangs-/Ausgangsknoten des TravelGraph liefern die
|
||||
Übergänge; der Außenwelteingang ist das wählbare Reiseziel.
|
||||
|
||||
Hat die Instanz einen eigenen Ausgang, ergibt sich die Rückkehrposition aus
|
||||
diesem Ausgang. Fehlt ein gesonderter Ausgang, erfolgt die Rückkehr am Eingang.
|
||||
Kein willkürlicher Stadt-/Heimatteleport. Ein entfernter Hinterausgang benötigt
|
||||
bei abstrahiertem Aufenthalt eine ausdrückliche technische Rückkehrbehandlung;
|
||||
eine vollständige MMAP-Durchquerung des Dungeons ist nicht Teil des Auftrags.
|
||||
|
||||
## Bestätigte Daten und bestehender Core
|
||||
|
||||
Die Test-World-DB `areatrigger_teleport` enthält lesbare Bezeichnungen:
|
||||
|
||||
| Trigger | Name | Zielkarte | Zielposition |
|
||||
|---|---|---|---|
|
||||
| 78 | Deadmines Entrance Target | 36 | -14.5732, -385.475, 62.4561 |
|
||||
| 119 | Deadmines Exit Front Target | 0 | -11208, 1676.41, 24.5716 |
|
||||
| 121 | Deadmines Rear Exit Target | 0 | -11341, 1576.55, 93.7284 |
|
||||
|
||||
Alle sechs Knoten `portal_at_{78,119,121}_{source,target}` sind bereits in
|
||||
`vcore_clientless_travel_node` vorhanden. Ihre Kommentare enthalten derzeit
|
||||
nur `Auto-imported AreaTrigger <ID> source/target`. Die semantischen Namen
|
||||
bleiben in der nativen World-Tabelle verfügbar. Quelle der Triggerpositionen
|
||||
ist zusätzlich `AreaTrigger.dbc`; Quelle/Zielkarte dienen zur belastbaren
|
||||
Richtungszuordnung. Namen sind Hinweise, keine alleinige Zugangsfreigabe.
|
||||
|
||||
`MapManager::CreateMapForPlayer` verwendet vorhandene Spieler-/Gruppenbindungen
|
||||
und sonst eine neue Instanz-ID. Bei Login wird eine gespeicherte Instanz-ID
|
||||
nur mit verfügbarer Karte beziehungsweise passender Instanzspeicherung
|
||||
wiederhergestellt. `InstanceMap::AddPlayerToMap` erzeugt native Instanzspeicher
|
||||
und Solobindungen. Neustart und abgelaufene Instanzspeicherung müssen deshalb
|
||||
auch mit einem echten Wiederanmeldetest geprüft werden.
|
||||
|
||||
Vor diesem Ausbau erzeugte `AdventureBehaviorMgr::Online` einen neuen
|
||||
flüchtigen Record und startete gegebenenfalls das Lua-Initialintent. Jetzt
|
||||
hat die dauerhafte Wiederaufnahme des Besuchs davor Vorrang.
|
||||
|
||||
Der Phasen-/Persistenzplan und die gezielten Tests sind im folgenden
|
||||
Implementierungsabschnitt beschrieben. Der historische Datenbefund allein
|
||||
belegt keine Gameplay-Abnahme.
|
||||
|
||||
|
||||
## Implementierung und Bedienung
|
||||
|
||||
Der Verhaltensmanager führt feste Phasen statt zufälliger Dungeon-Mikroaktionen
|
||||
aus: Anreise, zehn Sekunden Vorbereitung am echten Eingang, Eintritt, Aufenthalt,
|
||||
Rückkehr und Nachruhe. Es gibt keine Kampf-/Beute-/Dungeon-Routenlogik.
|
||||
Eine zu späte Ankunft überspringt den Eintritt und nutzt die verbleibende Zeit
|
||||
zur Rast. Während eines Aufenthalts wird ein Intentwechsel erst nach der
|
||||
Rückkehr ausgeführt. Die ursprüngliche Besuchsfrist wird dadurch nicht verlängert.
|
||||
|
||||
`sql/custom/world/2026_10_27_07_adventure_instances.sql` erzeugt aus vorhandenen
|
||||
nativen Teleporten, Instanzvorlagen und Graphquellknoten Außenwelt-Eingangsorte
|
||||
`instance_visit_at_<Trigger-ID>` sowie einen editierbaren Zuordnungskatalog
|
||||
`vcore_adventure_instance`. Auf der Test-DB ergaben sich 108 Eingangsaliase.
|
||||
Die alten Portalpunkte/Graphknoten bleiben unverändert. Instanzkarten werden
|
||||
weiterhin nicht als normale Aufenthaltsorte ausgewählt.
|
||||
|
||||
`exit_trigger=0` lässt den Laufzeitadapter einen passenden nativen Ausgang zur
|
||||
Außenkarte des Eingangs suchen. Benannte Hinterausgänge haben Vorrang vor dem
|
||||
Vorderausgang; Quelle/Zielkarte und vorhandene Graphknoten werden geprüft.
|
||||
Eine ausdrückliche Triggerzuordnung im Katalog hat Vorrang vor der Namensheuristik.
|
||||
Native Zugangsbedingungen bleiben wirksam. Gruppierte Bots sowie bereits mit
|
||||
anderen Spielern oder Gruppen geteilte Instanzbindungen werden zurückgewiesen.
|
||||
|
||||
Die verborgene Durchquerung bis zu einem entfernten Ausgang wird abstrahiert:
|
||||
Am Rückkehrzeitpunkt wird innerhalb derselben Instanzkopie zum realen
|
||||
Ausgangstrigger umgesetzt und dessen nativer Handler ausgeführt. Das ist kein
|
||||
behaupteter MMAP-Lauf durch den Dungeon. Ohne Ausgang oder bei nativer
|
||||
Wiederanmelde-Rettung aus einer abgelaufenen Instanz wird die zugeordnete
|
||||
Außenposition verwendet. Ein verweigerter Ausgang gilt nicht als Rückkehr.
|
||||
|
||||
Nach bestätigter Rückkehr wird einmal ein bei Besuchsbeginn gezogener
|
||||
Zufallswert von 0–50 Prozent der maximalen HP dargestellt. Bei vorher voller
|
||||
Gesundheit bleiben 50–100 Prozent HP. Bereits vorhandene Verletzungen werden
|
||||
nicht geheilt; die Darstellung tötet den Bot nicht. Normale Regeneration bleibt
|
||||
aktiv. Der Wert wird gespeichert und beim Neustart nicht neu gewürfelt.
|
||||
|
||||
Die additive Charakter-Migration
|
||||
`sql/custom/characters/2026_10_27_00_adventure_instance_visit.sql` speichert
|
||||
Besuchsphase, absolute Frist, Trigger, Instanz-ID und Verletzungsmarker.
|
||||
Charakterzustand und Besuchsphase/Verletzungsmarker werden gemeinsam über die
|
||||
native asynchrone Transaktionsverbindung gespeichert. Erst deren bestätigter
|
||||
Abschluss erlaubt das Fortschreiten. Die synchrone Verbindung kann die
|
||||
ASYNC-only-Statements des nativen Charakterspeichers nicht ausführen.
|
||||
|
||||
Ein WorldScript im optionalen Adventure-Skript meldet beim Serverstart nur
|
||||
Charaktere mit gespeichertem Besuch erneut mit dem Adventure-Controller an.
|
||||
Die Wiederaufnahme hat Vorrang vor dem normalen Lua-Initialintent. Fehlt die
|
||||
Besuchstabelle, bleibt diese Wiederanmeldung inaktiv; andere Clientless-Systeme
|
||||
werden davon nicht abhängig.
|
||||
|
||||
Serverkonsole:
|
||||
|
||||
```text
|
||||
clientless adventure intent 26 instance instance_visit_at_101 3600
|
||||
clientless adventure status 26
|
||||
```
|
||||
|
||||
Trigger 101 ist das Verlies in Sturmwind, Trigger 78 die Todesminen.
|
||||
Der Tagesplan kennt `instance` mit eigener Intentgewichtung (Standard 0,5);
|
||||
bestehende gespeicherte Tagespläne werden nicht umgeschrieben.
|
||||
|
||||
Regressionen: `test_adventure_instance_begin.py` prüft die produktive Anreise
|
||||
über den vorhandenen Ortsplaner mit lokalem MMAP-Anschluss;
|
||||
`test_adventure_instance.py` führt den produktiven Phasenablauf
|
||||
mit nativen Übergangsadaptern aus; `test_adventure_instance_catalog.py` führt
|
||||
die Migrationen auf Schemafixtures aus; `test_adventure_instance_persistence.py`
|
||||
führt produktives Speichern/Wiederherstellen mit Transaktionsadapter aus;
|
||||
`test_adventure_instance_autoresume.py` führt das tatsächliche Startup-Skript aus.
|
||||
|
||||
|
||||
## Technischer Live-Test am 27.10.2026
|
||||
|
||||
- Debug-Build mit `-j10` und Installation erfolgreich. Abschließender vollständiger
|
||||
Lauf: **44 Testskripte bestanden**, Log `/tmp/vcore-instance-tests-final.log`.
|
||||
- Beide Migrationen auf Test-DB angewendet; Collation der neuen Tabellen stimmt
|
||||
mit `utf8mb4_unicode_ci` der vorhandenen Ortsdaten überein. 108 neue Aliase,
|
||||
insgesamt 2.973 geladene Locations / 3.966 Worldpoints.
|
||||
- Die anfängliche Instanzanreise über den isolierten Portalnode führte in
|
||||
vorhandene Graph-Recovery-Schleifen. Die Anreise verwendet jetzt den bestehenden
|
||||
Ortsplaner mit lokalem MMAP-Anschluss. Auch dort trat auf dieser Strecke eine
|
||||
bestehende Graphschleife auf. Dieses Reiseproblem wurde ausdrücklich nicht
|
||||
repariert. **Die reguläre Fernanreise ist nicht erfolgreich live verifiziert.**
|
||||
- Für den isolierten Instanztest wurde ausschließlich der ausgeloggte Testbot
|
||||
administrativ am echten Außenwelt-Knoten `portal_at_101_source` positioniert
|
||||
(-8761.85, 848.557, 87.8052). Danach liefen lokaler MMAP-Anschluss,
|
||||
zehn Sekunden Vorbereitung und der tatsächliche native Trigger 101 regulär.
|
||||
- `INSTANCE_ENTERED guid=26 map=34 instance=1` bestätigt das Verlies. Gespeicherter
|
||||
Charakterstand direkt hinter dem Eingang: (48.9849, 0.483882, -16.3942).
|
||||
- Echter geordneter Serverneustart während Phase 3. Der Startup-Hook meldete
|
||||
Arthoran automatisch mit normalem Lua-Profil wieder an; `INSTANCE_RESUME`
|
||||
bestätigte erneut Karte 34, **Instanz-ID 1**, dieselbe absolute Frist und
|
||||
unveränderten Verletzungsmarker. Keine manuelle Anmeldung für diesen Restart.
|
||||
- Für die zeitnahe Rückkehrprüfung wurde nach sauberem Serverstopp nur das
|
||||
gespeicherte Blockende des bestätigten Innenaufenthalts auf einen verkürzten
|
||||
Testblock gesetzt. Ursprünglicher Wert in
|
||||
`/tmp/vcore-instance-live-original-deadline.tsv`. Der Produktivablauf verlängert
|
||||
oder verkürzt normale Nutzerblöcke nicht.
|
||||
- Rückkehr über nativen Ausgang 503 auf Karte 0, Position
|
||||
(-8766.11, 845.499, 87.9952). Zuerst zweimal gültiger Zufallswert 0 Prozent;
|
||||
ein weiterer regulär gestarteter sechsminütiger Testblock ergab **17 Prozent**:
|
||||
`INSTANCE_RETURNED ... lossPercent=17 health=2165 maxHealth=2609`.
|
||||
Die Charakter-DB bestätigte gleichzeitig Phase 5, `injury_applied=1` und 2165 HP.
|
||||
- Erneute Anmeldung während der Nachruhe bestätigte `INSTANCE_RESUME phase=5`,
|
||||
dieselbe Frist und `injuryApplied=1`, ohne Neuwurf oder erneute Verletzung. Normale Gesundheitsregeneration
|
||||
bleibt aktiv. Nachruhe wird bei neuem explizitem Auftrag sauber beendet;
|
||||
die ersten beiden Nachruhen wurden für die weiteren Tests bewusst unterbrochen.
|
||||
- Normales Profil in Quelle und Installation ist bytegleich restauriert
|
||||
(SHA256 `26b11c3108e6ecc5dbc59d1852b4103ca4e818148603a34c02a470c969dc659b`).
|
||||
Keine temporären Lua-Overrides. Geld/Inventar nach abschließendem `saveall` unverändert: SHA256
|
||||
`8d40931782d05219466ba9fd077ce7acd3e02bd53eb63f6e96115042c620d26a`.
|
||||
|
||||
Beim ersten Liveversuch wurde ein falscher Transaktionsweg erkannt: nativer
|
||||
Charakterspeicher plus synchrone Verbindung führte zum Debug-Abbruch. Dieser
|
||||
Fehler ist behoben: `AsyncCommitTransaction` führt die native Transaktion auf der
|
||||
passenden Worker-Verbindung aus und liefert den bestätigten Abschluss zurück.
|
||||
Regression und nachfolgende echte Speicher-/Neustarttests bestanden. Historisches
|
||||
Fehlerlog: `/tmp/vcore-instance-first-live-DBErrors.log`.
|
||||
|
||||
Der Nutzer verzichtet ausdrücklich auf eine weitere visuelle Abnahme.
|
||||
Ein echter Todesminen-Hinterausgang und
|
||||
zwei voneinander unabhängige gleichzeitig betretene Instanzkopien wurden noch
|
||||
nicht live getestet; Quell-/Zielzuordnung, geteilte Bindungssperre, Hinterausgang
|
||||
und fehlender Ausgang sind durch produktive Adaptertests abgedeckt.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Sieben Grundintents der AdventureBots
|
||||
|
||||
Konzeptstand: 27.10.2026. Vom Nutzer aus dem vorangegangenen Gespräch
|
||||
rekonstruiert und bestätigt. Diese Festlegung erweitert die bisher nur drei
|
||||
Intents umfassenden Dokumente. Sie beschreibt das vereinbarte Verhalten,
|
||||
nicht eine bereits vollständig vorhandene Implementierung.
|
||||
|
||||
AdventureBots stellen glaubwürdige Abenteurer dar. Ein Intent beschreibt ein
|
||||
Vorhaben; Reise und kontextabhängige Mikroaktionen setzen es um. Eine
|
||||
Mikroaktion kann zu mehreren Intents passen, etwa Sitzen bei Geselligkeit
|
||||
oder Ruhe. Entscheidend ist der Zweck des Aufenthalts.
|
||||
|
||||
## Die sieben Grundintents
|
||||
|
||||
| Intent | Zweck und Beispiele |
|
||||
|---|---|
|
||||
| Geselligkeit | Tavernenbesuche, Essen und Trinken, Gespräche und gemeinsame soziale Szenen. |
|
||||
| Abenteuer | Erkundung, Untersuchung von Orten und Objekten, sichtbare Aktivitäten in der offenen Welt. Eine tatsächliche Kampf-KI bleibt eine spätere Ausbaustufe. |
|
||||
| Beruf | Zum Berufsprofil passende Arbeit darstellen, beispielsweise an Erzquellen, Pflanzen, Schmieden oder Werkbänken. Ressourcen und Inventar werden dabei nicht verändert. |
|
||||
| Instanzen | Eine Instanz performativ besuchen: zum Eingang reisen, die Instanz betreten und nach einiger Zeit wieder am Ausgang erscheinen. Der Bot muss die Instanz weder durchlaufen noch dort tatsächlich kämpfen. |
|
||||
| Ruhe | Erholung darstellen: sich an geeigneten Plätzen schlafen legen, sitzen und andere erholsame Tätigkeiten ausführen. |
|
||||
| Freizeit | Sich ohne konkretes Arbeits- oder Abenteuerziel bewegen, beispielsweise in Sturmwind spazieren gehen, ziellos umherlaufen, reiten oder fliegen. |
|
||||
| Wirtschaften | Wirtschaftliche Aktivitäten performativ darstellen: Händler, Auktionshaus oder Bank aufsuchen. Der Bot handelt dabei nicht tatsächlich. |
|
||||
|
||||
Instanzbesuche bilden einen eigenen Grundintent und werden nicht lediglich
|
||||
unter Abenteuer geführt. Freizeit ist ebenfalls ein eigenes Vorhaben;
|
||||
Fortbewegung dient dort dem Aufenthalt selbst und nicht nur der Anreise.
|
||||
Beruf bezeichnet die dargestellte Arbeit, Wirtschaften die dargestellten
|
||||
wirtschaftlichen Besuche und Aktivitäten.
|
||||
|
||||
## Implementierungsstand und offene Ausgestaltung
|
||||
|
||||
Der bestehende Verhaltensmanager kennt aktuell die technischen Intentnamen
|
||||
`social`, `adventure`, `profession`, `rest`, `leisure`, `economy` und `instance`. Der [Ruhe-Intent](rest-intent.md)
|
||||
ist ergänzt, ebenso der [Freizeit-Intent](leisure-intent.md) und der
|
||||
[Wirtschaften-Intent](economy-intent.md). Der [Abenteuer-Ausbau](adventure-intent.md)
|
||||
ergänzt Erkundung und Objektuntersuchung. Der [Berufs-Ausbau](profession-intent.md)
|
||||
ergänzt profilgebundene Arbeitsdarstellungen, echte Ressourcen-/Arbeitsplatzprüfung
|
||||
und progressive Gebietssuche. Der [Instanzintent](instance-intent.md) ergänzt bestätigten Eintritt,
|
||||
gespeicherten Aufenthalt, native Rückkehr und einmalige Verletzungsdarstellung. Der ausführliche bisherige
|
||||
[Mikroaktionskatalog](mikroaktions-katalog.md) bleibt als Grundlage erhalten.
|
||||
|
||||
Der Geselligkeitsausbau ist implementiert. Die Sitzposition auf nativen
|
||||
Stühlen wurde vom Nutzer auch visuell im Spiel geprüft und funktioniert.
|
||||
Eine Prüfung von Gesprächen zwischen mehreren AdventureBots setzt voraus,
|
||||
dass mehrere solche Bots vorhanden sind.
|
||||
|
||||
Weitere Einzelheiten des früheren Gesprächs sind durch diese Rekonstruktion
|
||||
nicht belegt und dürfen nicht als bereits vereinbart vorausgesetzt werden.
|
||||
@@ -0,0 +1,87 @@
|
||||
# Interaktive Portale: Live-Test Dunkles Portal → Sturmwind
|
||||
|
||||
Implementierung und Bedienung: [docs/interactive-portals.md](../../docs/interactive-portals.md).
|
||||
Stand 26.10.2026. Keine künstlichen Teleports, keine Änderungen an nativen
|
||||
GameObject- oder Zauberdefinitionen.
|
||||
|
||||
## Erfolgreicher Teststandort
|
||||
|
||||
| Merkmal | Wert |
|
||||
| --- | --- |
|
||||
| GameObject-Spawn | 170 |
|
||||
| Entry / Name | 195139 / Portal to Stormwind |
|
||||
| Standort | Scherbenweltseite beim Dunklen Portal |
|
||||
| Quelle | Karte 530, (-337.492, 962.619, 54.2885) |
|
||||
| Nativer Zauber | 17334, Teleporteffekt 0 mit TARGET_DEST_DB |
|
||||
| Ziel | Karte 0, (-8998.140, 861.254, 29.6206), Orientierung 2.25 |
|
||||
| Nodes | portal_go_170_source → portal_go_170_target |
|
||||
| Kante | 1755, portal_use, Kosten 1, unidirektional |
|
||||
|
||||
Gezielt importiert mit `clientless portal object import 170`. Arthoran
|
||||
(GUID 26) begann ausgeloggt acht Yards vor der nativen Objektposition; nach
|
||||
Login erhielt er einen normalen Reiseauftrag zum Zielnode. Während der Reise
|
||||
keine Positionsmanipulation:
|
||||
|
||||
- 13:28:36: MMAP-Anlauf, 8 Yards, vollständiger Pfad.
|
||||
- 13:28:38: Source erreicht; normaler CMSG_GAMEOBJ_USE-Handler für Spawn 170.
|
||||
- 13:28:39: `EDGE_COMPLETE`, `edgeType='portal_use'`, Karte 0,
|
||||
`arrivalError=0.00`, `recovery=0`, anschließend regulärer Reiseabschluss.
|
||||
|
||||
Das bestätigt serverseitig Anlauf, Objektbenutzung, nativen Portalzauber,
|
||||
Far-Teleport mit Clientless-ACK und Ankunft. Visuelle Ingame-Abnahme durch den
|
||||
Nutzer steht aus. Keine Rückrichtung erfunden, keine Groundanschlüsse
|
||||
aufgenommen und keine NPC-/Gossip-Portale als unterstützt behauptet.
|
||||
|
||||
## Untersuchte Shattrath-Verbindung
|
||||
|
||||
Erster Kandidat: Spawn 83, Entry 183325, `Shattrath Portal to Stormwind`,
|
||||
gleicher Zauber 17334, Quelle (-1894.190, 5387.940, -12.4283) auf Karte 530.
|
||||
Das native Zauberziel ist identisch zum erfolgreichen zweiten Standort.
|
||||
|
||||
Der Klick erreichte die normale native Zauberausführung, aber die Effekte
|
||||
wurden in `Spell::AddUnitTarget` nach `CheckEffectTarget` verworfen. Die
|
||||
zusätzliche Diagnose zeigte `resolved=1` für Arthoran und `no effects after
|
||||
target/LOS checks` für beide Effekte. Bei diesen Effekten ist dort die native
|
||||
Sichtlinienprüfung maßgeblich. Das trat an der Objektmitte und drei Yards davor
|
||||
auf. Der genaue geometrische Grund wurde nicht geändert oder abschließend
|
||||
vermessen. Die temporäre Zauberdiagnose wurde nach der Untersuchung entfernt.
|
||||
|
||||
Der Versuch scheiterte sowohl bei Level 20 als auch bei Level 60; niedriges
|
||||
Level erklärt diesen Befund daher nicht. Die Erhöhung auf Level 60 erfolgte
|
||||
mit dem konsolenfähigen nativen Befehl `character level Arthoran 60` im Rahmen
|
||||
der Nutzerfreigabe. `.levelup` ist in dieser Core-Kommandotabelle ingame-only.
|
||||
|
||||
Die erfolglose experimentelle Kante 1752 sowie ihre beiden Graphnodes und
|
||||
Weltpunkte sind jetzt deaktiviert. Ihre Definition bleibt zur Diagnose
|
||||
erhalten. Der veränderte Graph-Anlaufpunkt liegt bei X=-1897.190; native
|
||||
GO-Position und Zauberdaten sind unverändert. Beim Wiederholungsimport bleiben
|
||||
Anlaufposition und Deaktivierung erhalten. Der native Standort muss vor einer
|
||||
späteren Freigabe gesondert geprüft werden.
|
||||
|
||||
## Import- und Fehlertests
|
||||
|
||||
- Wiederholter Import: keine zusätzlichen Nodes/Kanten; bestehende Koordinaten
|
||||
und enabled-Flags werden nicht überschrieben.
|
||||
- Fehlgeschlagene native Ausführung: nach 10 Sekunden korrekt `Failed`, kein
|
||||
behaupteter Reiseerfolg und kein Ersatzteleport.
|
||||
- Shattrath → Quel’Danas, Spawn 47196 / Zauber 44876: Import sauber vor dem
|
||||
Anlegen von Nodes abgewiesen; Zauberkette statt direktem DB-Teleport.
|
||||
- Automatisierte Tests führen Produktionsmethoden mit Core-Doubles aus:
|
||||
direkte Zielauflösung, Objektprüfung, Klick, Near/Far/globaler ACK,
|
||||
Ablehnung, Timeout, falsches Ziel und ACK-Sequenzzähler.
|
||||
- Bestehende Portal-, Transport-, Grid-, Lua-Reload- und Taxi-Importer-Tests
|
||||
bestanden ebenfalls.
|
||||
|
||||
Build und Installation bestanden. Die tatsächlichen Portalversuche wurden
|
||||
mit installiertem Code ausgeführt. Anschließend wurde der endgültige Stand
|
||||
ohne zusätzliche temporäre Zauberdiagnose gebaut und installiert. Finale
|
||||
Build-ID: `613c4236bce2212d49788e771b66f490b617d8ca`.
|
||||
|
||||
Der letzte Start wurde anhand seiner vollständigen frischen Konsole geprüft:
|
||||
Ready-Meldung vorhanden, keine kritischen Startfehler im geprüften Output,
|
||||
Prozess 53332 läuft und Port 8085 lauscht. Keine weiteren Botaufträge beim
|
||||
finalen Start. Der ursprüngliche Loglevel gilt wieder.
|
||||
|
||||
Arthoran wurde nach dem Test ausgeloggt. Ausgangsposition, Zone und Lua sind
|
||||
wiederhergestellt; das freigegebene Level 60 bleibt erhalten. Vorherdaten,
|
||||
Diagnose und Testlogs liegen in `/tmp/vcore-interactive-portal.8vfrq7g2`.
|
||||
@@ -0,0 +1,64 @@
|
||||
27.10.2026 – Berufs-Ausbau fortgesetzt, gebaut und auf Testserver installiert.
|
||||
Migration _05 angewendet; 37 Testskripte bestanden. Native Arbeitsplatz-Sichtlinie
|
||||
und numerische Location-Feldtypen korrigiert. Live: echter Amboss 201415,
|
||||
Work-Emote 233, Abschluss/Wegtreten; Kräuteraktion verweigert; Geld/Inventar
|
||||
unverändert. Elwynn als Gebiet über travel_to_node erreicht, sechs lokale
|
||||
progressive Suchwegpunkte vollständig absolviert. Visuelle Abnahme und echtes
|
||||
Ressourcenziel in freier Wildbahn offen. Separater Travel-Handover-Loop dokumentiert.
|
||||
Details: profession-intent.md und SESSION-RESUME.md. Kein Push.
|
||||
|
||||
› OK stop, er findet ja den weg schon wieder nicht. Es sieht so aus, als würde er den virtuellen entry auf der Kante sturmwind Hafen - sturmwind gate verwenden. Er reitet diese auch lang aber nach einem Stück bricht er ab. Warum? Er mü…
|
||||
|
||||
1. Der Planer bewertet den restlichen Weg zur Taverne zunächst nur anhand der Luftlinienentfernung. Ob MMAP ihn tatsächlich laufen kann, prüft er erst am Ausstieg.
|
||||
2. Dort scheitert der lokale Anschluss mit PathRejected.
|
||||
3. Die Fehlerbehandlung sperrt nur diesen einzelnen Ausstiegspunkt. Deshalb wählt der Planer beim nächsten Versuch einen benachbarten Punkt derselben Kante – statt zuverlässig bis zum regulären Endknoten weiterzureisen.
|
||||
4. Nach fünf Fehlversuchen übernimmt der Adventure-Manager und wählt die Stadtbank als Ersatzort. Dadurch wird das ursprüngliche Tavernen-Ziel aufgegeben.
|
||||
|
||||
Das Weiterfahren bis zum echten Knoten fehlt hier als wirksame Rückfallstrategie. Sturmwind Gate und der Greifenmeister werden zwar im Suchlauf geprüft, aber nicht als zwingender nächster Schritt über die weiterhin nutzbare
|
||||
aufgezeichnete Kante angesteuert.
|
||||
|
||||
Beim Fliegen kommt eine zweite Einschränkung hinzu: Die aktuelle Konfiguration lässt gewöhnliche Flugstrecken erst ab 600 Yards zu. Die hier geplanten lokalen Anschlüsse liegen bei ungefähr 260–300 Yards und werden dadurch
|
||||
ausgeschlossen. Flugfähigkeit allein genügt der aktuellen Auswahl also nicht.
|
||||
|
||||
Die Korrektur muss deshalb an der Reiseplanung ansetzen: nach gescheitertem virtuellem Ausstieg die nutzbare Kante bis zum regulären Knoten weiterverfolgen und Flug als Alternative bei blockiertem Bodenweg berücksichtigen. Für die
|
||||
Taverne wäre dabei ein erreichbarer Landeplatz draußen mit anschließendem Fußweg erforderlich.
|
||||
|
||||
Worked for 1m 20s • 07:44
|
||||
|
||||
› Das Problem besteht also darin, wie unser Graphmanager alternativen wählt und mit fehlversuchen umgeht. Nach 5 gescheiterten virtuellen Exits die komplette Reise ab zu brechen ist natürlich Unsinn. Auch ist es unsinn, den Bot den
|
||||
virtuellen exit nur 5 Mal probieren zu lassen, eine bessere Alternative wäre, ihn diesen in einem regulärem Zeitabstand regelmäßig erneut prüfen zu lassen, während der prüfung reitet er weiter zum regulärem Node Ziel, er darf auch auf
|
||||
einer Kante nicht einfach mitten drinn umkehren, sondern muss zumindest zum nächsten NOde, virtuelle sind hier gleichberechtigt mit den anderen. SO verhindern wir, dass er auf der Strecke hin und herläuft weil er keinen virtuellen
|
||||
exit findet. In unserem konkreten Beispiel heißt das, Arthoran läuft die reguläre route zum Tor von Sturmwind und prüft regelmäig ob er den virtuellen exit nehmen kann, beim scheitern läuft er weiter bis er irgendwann einen gültigen
|
||||
virtuellen exit findet oder an der nächsten Node angekommen ist. Außerdem müssen wir bei der Auswahl des freien fliegens die Auswahlkriterien für eine normale Reise von einem Fallback für unerereichbare Ziele behandeln. Grundsätzlich
|
||||
gilt: der Bot versucht erstmal immer so nah wie er kann an sein Zeil heran zu kommen. Wenn er feststellt, das keine reguläre Route zum Ziel führt, oder die Reise abgebrochen ist und er nicht mehr weiter kommt, dann soll er natürlich
|
||||
auch das freie fliegen prüfen, ohn Regelen, die wir künstlich für normale Reisen gesetzt haben.
|
||||
|
||||
|
||||
• Ich ändere die Reiseausführung so, dass ein fehlgeschlagener virtueller Ausstieg die laufende Kante nicht mehr abbricht: Arthoran folgt ihr weiter zum nächsten Knoten und prüft unterwegs in festen Abständen neue Ausstiegsmöglichkeiten. Für den freien Flug trenne ich die normale Reisewahl vom Rückfall bei blockiertem Bodenweg; die nativen Flug-, Kollisions- und Landeprüfungen bleiben dabei erhalten.
|
||||
|
||||
• Ran git status --short --branch; cat src/server/game/World/ClientlessTravelGraphMgr.h | tail -150; cat src/server/game/World/ClientlessFlightMgr.h
|
||||
└ };
|
||||
#define sClientlessFlightMgr ClientlessFlightMgr::instance()
|
||||
#endif
|
||||
+ 217 lines (^t to expand)
|
||||
• Explored
|
||||
└ Read ClientlessActionExecutorMgr.cpp, ClientlessActionExecutorMgr.h
|
||||
Read ClientlessTravelGraphMgr.cpp
|
||||
Read ClientlessFlightMgr.cpp
|
||||
+ Show details
|
||||
■ Conversation interrupted - use /feedback if something went wrong
|
||||
|
||||
|
||||
› DU hast wohl Probleme mit der Internetverbindung, probier es nochmal
|
||||
|
||||
|
||||
■ Conversation interrupted - use /feedback if something went wrong
|
||||
|
||||
|
||||
› gut das klappt nicht, ich ahne auch warum. Speicher mal bitte den aktuellen Stand unserer Unterhaltungen und Konversationen so, dass du später ohne Probleme fortsetzen kannst.
|
||||
|
||||
|
||||
■ Conversation interrupted - use /feedback if something went wrong
|
||||
|
||||
|
||||
› A
|
||||
@@ -0,0 +1,289 @@
|
||||
# Freizeit-Intent
|
||||
|
||||
Technischer Name: `leisure`. Freizeit ist ein Aufenthalt mit Spaziergängen,
|
||||
Pausen und freiwilligen Ausflügen, keine Folge endloser Fernreiseaufträge.
|
||||
Migration: `sql/custom/world/2026_10_27_02_adventure_leisure.sql` nach den
|
||||
Geselligkeits- und Ruhe-Migrationen. Definitionen und bearbeitete Gewichte bleiben
|
||||
erhalten. Neue Tagespläne können Freizeit anhand `activity_affinity.leisure`
|
||||
auswählen (Standard 0,5); vorhandene gespeicherte Tagespläne bleiben bestehen.
|
||||
|
||||
## Mikroaktionen
|
||||
|
||||
| Schlüssel | Ablauf |
|
||||
|---|---|
|
||||
| `leisure_training` | Eine echte sichtbare und erreichbare Trainingspuppe im lokalen Umkreis aufsuchen und 60–180 Sekunden mit nativen Angriffen trainieren. |
|
||||
| `leisure_walk` | Zusammenhängender MMAP-Hinweg zu einem entfernten Außenpunkt, danach dieselben Wegpunkte zurück; Gehmodus und kurze Pause am Wendepunkt. |
|
||||
| `leisure_roam` | Eine lokale Spazierstrecke auswählen, vollständig verfolgen und auf demselben Weg zurückkehren. |
|
||||
| `leisure_pet_walk` | Eigenen Begleiter beschwören, gegebenenfalls anleinen, eine zusammenhängende Strecke entspannt hin und zurück gehen, zurückkehren und eigene Begleiterressourcen aufräumen. |
|
||||
| `leisure_ride` | Kurzer Rundritt mit Profil-Bodenmount; nur Außenwege, danach zurückkehren und absteigen. |
|
||||
| `leisure_flight` | Kurzer Rundflug mit nativen Start-, Kollisions- und Landeprüfungen; sichere Landung und Rückkehr vor Intentwechsel. |
|
||||
| `leisure_fish` | An einem markierten `leisure_fishing`-Platz mit ausgerüsteter Angel und geprüftem Wasser native Angelhaltung darstellen. Kein Fischfang, Beuteobjekt oder Inventarzugang. |
|
||||
| `leisure_view`, `leisure_linger` | Aussicht betrachten beziehungsweise ruhig verweilen. |
|
||||
|
||||
Gemeinsame Szenen ergänzen NPC-/Bot-Gespräche, Zuhören, native Sitzplätze,
|
||||
Essen, Trinken und Feuerrast. Tanz wird bei Freizeit nur an einer als `festival`
|
||||
klassifizierten Location angeboten. Neue Feuer bleiben in Gebäuden und Städten
|
||||
verboten. Freizeit verwendet vorhandene Fähigkeiten statt eigener Sitz-,
|
||||
Gesprächs- oder Feuerimplementierungen.
|
||||
|
||||
Geplante Fußspaziergänge bleiben höchstens 250 Yards vom Aufenthaltsanker entfernt; andere lokale Ausflüge höchstens 120 Yards.
|
||||
Stadtlocations mit `zone_id` und Gebietsaufträge behalten ihre native Gebietsgrenze;
|
||||
Bodenwege werden einschließlich Zwischenpunkten über MMAP geprüft. Reitwege
|
||||
müssen entlang der gesamten berechneten Bodenroute im Außenbereich bleiben.
|
||||
Bodenrunden wählen nahe Bodenhöhen mit höchstens drei Yards Abweichung zum
|
||||
Ausgangspunkt; erhöhte Dachpunkte werden nicht als Spaziergangziele verwendet.
|
||||
Nach einer Sitz-/Esspause im Gebäude bleiben Fußspaziergänge, Umherlaufen und
|
||||
Haustierausführen wählbar: Die normalen lokalen Wege führen wieder zu den
|
||||
geprüften Außenpunkten. Rückkehrort ist dann der äußere Freizeitanker statt
|
||||
des Innenraum-Sitzplatzes. Ausritte und Rundflüge benötigen weiterhin einen
|
||||
Außenstart; die Feuerverbote in Gebäuden und Städten bleiben bestehen.
|
||||
Kein unerreichter Wegpunkt zählt als Ankunft. Normale Ausflüge kehren zum
|
||||
Ausgangspunkt zurück; Zeitlimits, verlorene Begleiter oder Navigationsfehler
|
||||
beenden einen nicht mehr sicher ausführbaren Ablauf, ohne eine Rückkehr vorzutäuschen.
|
||||
|
||||
Fußspaziergänge (`walk`, `roam`, `pet_walk`) wählen vor dem Losgehen genau
|
||||
**eine** vollständige native Bodenroute mit mindestens 65 Yards Abstand zum
|
||||
Ausgangspunkt. Das Hinweg-Budget beträgt abhängig von der Mikroaktionsdauer
|
||||
100–220 Yards. Unvollständige Pfade, Shortcuts, übermäßige Umwege, fremde Gebiete
|
||||
und Innenraumstrecken werden verworfen. Etwa alle 20 Yards werden echte
|
||||
MMAP-Punkte als Kontrollpunkte gespeichert; lokale Navigation verbindet sie.
|
||||
Der Wendepunkt kommt nur einmal vor, danach folgen die Kontrollpunkte rückwärts
|
||||
bis zum Start. Es gibt keine regelmäßigen Pausen zwischen Kontrollpunkten;
|
||||
am Wendepunkt sind vier Sekunden vorgesehen. Die Begleiter-Abstandsprüfung
|
||||
bleibt unabhängig davon aktiv. Bei Zeitende oder einem gescheiterten Hinweg
|
||||
wird entlang tatsächlich erreichter Kontrollpunkte zurückgegangen, statt einen
|
||||
neuen geraden Rückweg oder weitere Zufallsziele zu wählen. Ein nicht möglicher
|
||||
Rückweg wird als Fehler beendet und niemals als Rückkehr ausgegeben.
|
||||
|
||||
`stormwind_leisure_trade` verwendet die vorhandene Bodenposition von
|
||||
`game_tele.TradeDistrict` als Freizeitanker. Dorthin wird regulär gereist, nicht
|
||||
teleportiert. Weitere Orte beziehungsweise Angelplätze müssen passend markiert
|
||||
und räumlich geprüft werden. Eine fehlende Angel oder ein fehlender geeigneter
|
||||
Angelplatz verhindert ausschließlich die Angelaktion.
|
||||
|
||||
## Katze und Haustierleine
|
||||
|
||||
Arthoran verwendet im `movement`-Profil:
|
||||
|
||||
```lua
|
||||
companion_spell = 10673, -- Bombay Cat, Kreatur 7385
|
||||
companion_leash_item = 37460, -- Rope Pet Leash, Gegenstandszauber 48722
|
||||
```
|
||||
|
||||
Diese IDs wurden in den geladenen nativen Spell-/SpellEffect-/Item-sparse-Daten
|
||||
und der Test-Weltdatenbank bestätigt. Der Controller stellt die im Profil
|
||||
gewählte nicht kämpfende Begleiterfähigkeit und die Leine einmalig als
|
||||
Bot-Ausstattung bereit. Bestehende Ausstattung wird wiederverwendet; ein volles
|
||||
Inventar verhindert keine unangeleinte Variante.
|
||||
|
||||
`ClientlessCompanionMgr` ist eine generische Clientless-Core-Fähigkeit ohne
|
||||
Abhängigkeit vom AdventureBot-Manager. Die Beschwörung ist ein normaler,
|
||||
nicht ausgelöster Spielerzauber. Erst ein tatsächlich vorhandener eigener
|
||||
Begleiter mit passendem Beschwörungszauber bestätigt die Beschwörung. Die
|
||||
Katze folgt mit dem nativen Folgegenerator. Für die eigens beschworene Katze
|
||||
wird ein Abstand von 1,5 Yards mit nativem Aufholen gewählt; ein bereits vorhandener
|
||||
Begleiter behält seine Bewegungskonfiguration. Es gibt keine Spielerteleports,
|
||||
künstliche Katzen-Spawns oder eine ersetzt implementierte Tier-KI.
|
||||
|
||||
Die Leine wird über den normalen Gegenstandszauber-Auftrag des Besitzers
|
||||
benutzt, mit tatsächlicher Gegenstands-GUID, Inventarposition und eigenem
|
||||
Minipet als Ziel. Dadurch bleiben native Gegenstands-, Zauber-, Ziel-,
|
||||
Abklingzeit- und Scriptprüfungen erhalten. Die Wirkung wird am tatsächlichen
|
||||
Begleiter bestätigt. Die native Leine ist ein beweglicher Kanalzauber. Der Clientless-Reisemanager
|
||||
erhält solche Kanäle beim Starten lokaler Bewegungen; nur bewegungsblockierende
|
||||
Zauber werden abgebrochen. Unbewegliche Kanäle werden nicht als Gehleine verwendet; eine nicht anwendbare Leine blockiert den Spaziergang nicht.
|
||||
|
||||
Der Besitzer beginnt erst nach bestätigter Beschwörung und abgeschlossener
|
||||
Leinenprüfung zu gehen. Bei aktiver Leine reagiert die Steuerung in jedem Weltupdate vor Erreichen der
|
||||
nativen Fünf-Yards-Reichweite: Ab vier Yards wartet Arthoran, bis die Katze wieder
|
||||
höchstens 3,25 Yards entfernt ist. Ohne Leine gilt eine Grenze von 15 Yards.
|
||||
Eine Wartephase dauert höchstens 20 Sekunden. Eine verlorene eigene Leinenwirkung
|
||||
kann höchstens zweimal über dieselbe normale Gegenstandsbenutzung neu angelegt werden. Beim Abschluss oder Abbruch werden nur die durch
|
||||
diese Szene aufgebrachte Leinenwirkung und eine von ihr beschworene Katze
|
||||
entfernt. Ein passender bereits vorhandener Begleiter kann benutzt werden und
|
||||
bleibt danach bestehen. Fremde Begleiter und Kampf-Pets werden nicht ersetzt.
|
||||
|
||||
## Diagnose und Tests
|
||||
|
||||
```text
|
||||
clientless adventure intent 26 leisure stormwind_leisure_trade 3600
|
||||
clientless adventure status 26
|
||||
clientless adventure micro 26 leisure_pet_walk
|
||||
clientless adventure micro 26 leisure_walk
|
||||
clientless adventure micro 26 leisure_ride
|
||||
clientless adventure micro 26 leisure_flight
|
||||
```
|
||||
|
||||
Gezielte Mikroaktionen benötigen den passenden laufenden Intent am Zielort und
|
||||
durchlaufen dieselben Voraussetzungen wie die automatische Auswahl.
|
||||
|
||||
Logereignisse: `LEISURE_START`, `LEISURE_WAYPOINT`, `LEISURE_COMPLETE`,
|
||||
`COMPANION_START`, `COMPANION_CONFIRMED`, `COMPANION_LEASH_REQUEST`,
|
||||
`COMPANION_LEASH_CONFIRMED`, `COMPANION_LEASH_UNAVAILABLE`,
|
||||
`COMPANION_WALK_SAMPLE` und `COMPANION_END`.
|
||||
|
||||
```bash
|
||||
python3 tests/clientless/test_adventure_leisure.py
|
||||
python3 tests/clientless/test_adventure_leisure_catalog.py
|
||||
python3 tests/clientless/test_clientless_companion.py
|
||||
```
|
||||
|
||||
Die Tests führen produktive Methoden mit kontrollierten Core-Adaptern aus:
|
||||
Rundwege, tatsächliche Ankunft, Gebietsgrenzen, Begleiterbereitschaft,
|
||||
Folgeabstand/Zeitlimit, Reitmodus, Fluglandung vor Intentwechsel, Angelvoraussetzungen,
|
||||
Besitzprüfung, native Gegenstandsziele, Leinenbestätigung, Wiederverwendung und
|
||||
Bereinigung. Die Migration wird auf wiederholbare Ergänzung, vorhandene gemeinsame
|
||||
Aktionen und Erhalt manueller Gewichte geprüft. Sichtprüfung von Katze, Leine,
|
||||
Spaziergängen, Ausritten, Flügen und Angelhaltung bleibt eine separate Ingame-Abnahme.
|
||||
|
||||
|
||||
## Testserverstand am 27.10.2026
|
||||
|
||||
- Additive Freizeit-Migration angewendet: 2.644 aktive Adventure-Locations,
|
||||
42 Aktionen und 56 Dialogzeilen. Vorhandene Definitionen wurden erhalten.
|
||||
- Bestehende Debug-Konfiguration nur für die neue Quelldatei neu eingelesen,
|
||||
mit `-j10` gebaut und in den gestoppten Testserver installiert. Alle
|
||||
25 Clientless-Regressionsskripte bestanden am abschließenden Stand.
|
||||
- Frischer Worldserver-Start mit `ready...`, fortlaufendem Prozess und
|
||||
Listener auf Port 8085 bestätigt. Keine Produktion und kein Push.
|
||||
- Arthoran reiste regulär von der Gilded Rose zum Freizeitanker im Handelsdistrikt.
|
||||
`INTENT_ARRIVED` und automatische Spaziergang-/Umherlauf-/Sitzszenen wurden
|
||||
beobachtet. Ein erster Ausritt erreichte einen Wegpunkt und wurde für den
|
||||
Katzentest unterbrochen; ein vollständiger Live-Rundritt ist damit nicht belegt.
|
||||
- Der erste Katzentest bestätigte die native Bombay-Katze und ihr Folgen.
|
||||
Er zeigte außerdem, dass die Leine ein beweglicher Kanalzauber ist. Der
|
||||
generische Reisemanager erhält diesen Kanal nun statt jeden Zauber pauschal
|
||||
abzubrechen. Nicht passende optionale Wegpunkte werden übersprungen; die
|
||||
tatsächliche Rückkehr bleibt verpflichtend. Hohe Dachpunkte sind für
|
||||
Bodenrunden ausgeschlossen.
|
||||
- Die native Leine hat fünf Yards Reichweite. Für die selbst beschworene Katze
|
||||
wird deshalb derselbe native Folgegenerator mit engerem Abstand verwendet;
|
||||
Abstandskontrolle läuft in jedem Weltupdate. Bestehende Begleiter behalten
|
||||
ihre eigene Bewegungskonfiguration.
|
||||
- Abschließender Live-Test: native Beschwörung von Kreatur 7385, normale
|
||||
Gegenstandsbenutzung von 37460 mit Zauber 48722 und
|
||||
`COMPANION_LEASH_CONFIRMED`. Zwei Bodenrunden mit 15 bestätigten Wegpunkten
|
||||
einschließlich Rückkehr. Alle 15 `COMPANION_WALK_SAMPLE`-Proben zeigten
|
||||
`leashed=1`, ohne `COMPANION_LEASH_LOST`; größte protokollierte Entfernung
|
||||
3,27 Yards. Rückkehr am 27.10.2026 um 12:57:49 mit `NAV_COMPLETE`, danach
|
||||
`LEISURE_COMPLETE ... legs=15` und `COMPANION_END`.
|
||||
- Nach dem Rundgang blieb Arthoran im Freizeit-Intent und wechselte zum
|
||||
ruhigen Verweilen. Sein Startprofil war nur für den Testlogin temporär auf
|
||||
Freizeit/Sturmwind gesetzt und ist wieder auf den bisherigen Sozialstart
|
||||
zurückgesetzt; Katze, Leine und Freizeit-Affinität bleiben im Profil konfiguriert.
|
||||
|
||||
Das ist eine serverseitige Bestätigung, keine visuelle Abnahme. Offen bleiben
|
||||
insbesondere das Aussehen der Katze an der Leine, vollständige Ausritte und
|
||||
Freizeit-Rundflüge sowie markierte Angelplätze und die Angelhaltung. Der zuvor
|
||||
verschobene visuelle Schlaftest bleibt davon unabhängig offen.
|
||||
|
||||
|
||||
### Allgemeine lokale Spline-Segmentierung
|
||||
|
||||
Beim anschließenden freien Umherlaufen trat der zuvor auch bei anderen Reisen
|
||||
beobachtete Fehler `_checkPathLengths()` für Arthoran auf. Ursache: Der
|
||||
Clientless-Reisemanager entfernte nur Abschnitte bis 0,05 Yards, während native
|
||||
Splines mindestens 0,1 Yards zwischen internen Punkten verlangen. Zusätzlich
|
||||
konnte das Kürzen bei 45 Yards einen zu kurzen letzten Rest erzeugen.
|
||||
|
||||
Die Segmentbildung verwendet jetzt 0,11 Yards Mindestlänge als Rundungsmarge
|
||||
und endet bei zu kurzem Rest am letzten wirklichen Pfadpunkt. Danach folgt die
|
||||
nächste reguläre lokale Teilstrecke. Die native Prüfung bleibt unverändert.
|
||||
`test_local_spline_segments.py` führt die produktive Segmentbildung gegen die
|
||||
produktive native Längenprüfung aus, einschließlich des gefundenen Restfalls
|
||||
und 1.000 gesampelter Pfade. Der ergänzte Stand besteht alle 26 Clientless-Tests
|
||||
und wurde mit `-j10` erfolgreich gebaut.
|
||||
|
||||
Nach Installation der Spline-Korrektur erreichte der Testserver erneut
|
||||
`ready...`; Prozess und Port 8085 wurden bestätigt. Der längere Live-Test
|
||||
`leisure_roam` durchlief acht bestätigte Wegpunkte einschließlich Rückkehr
|
||||
und endete am 27.10.2026 um 13:08:02 mit `NAV_COMPLETE` und
|
||||
`LEISURE_COMPLETE ... kind='roam' legs=8`. Dabei wurde auch eine native
|
||||
45-Yards-Teilstrecke erfolgreich abgeschlossen und regulär fortgesetzt.
|
||||
Im frischen Serverlog trat für GUID 26 kein `_checkPathLengths()` mehr auf.
|
||||
Das temporär geänderte Test-Startziel ist zurückgesetzt. Der anschließende
|
||||
Katzenspaziergang wird für die Sichtprüfung wieder über den normalen
|
||||
Mikroaktionsbefehl gestartet.
|
||||
|
||||
## Korrektur: Freizeit nach einer Innenraumpause
|
||||
|
||||
Der Nutzer beobachtete Arthoran wiederholt beim Sitzen statt beim Spazieren.
|
||||
Der laufende Auftrag war `leisure`, die letzten Szenen bestanden aber aus
|
||||
Sitzen, Essen und Trinken auf Sitzplätzen bei `(-8827,648,98)` beziehungsweise
|
||||
`(-8829,647,98)`. Die Auswahl sperrte bisher sämtliche Bewegungsaktionen im
|
||||
Innenbereich. Damit konnten Fußausflüge nach einer Innenraumpause nicht mehr
|
||||
angeboten werden.
|
||||
|
||||
Die Außenstart-Voraussetzung gilt jetzt nur noch für Ausritte und Rundflüge.
|
||||
Spazieren, Umherlaufen und Haustierausführen dürfen im Innenbereich beginnen;
|
||||
sie verwenden weiterhin geprüfte Außenwegpunkte und vollständige MMAP-Wege.
|
||||
Ihr Rückkehrort ist in diesem Fall der Außenanker statt des Innenraum-Sitzplatzes.
|
||||
Feuerverbote und übrige Umgebungsprüfungen bleiben bestehen.
|
||||
|
||||
Die Produktionsmethoden-Regression prüft ausdrücklich einen Innenraumstart,
|
||||
freigegebene Fuß-/Haustierausflüge, weiterhin gesperrtes Reiten/Fliegen und die
|
||||
Rückkehr zum Außenanker. Alle 26 Tests und der Build mit `-j10` bestanden.
|
||||
Die Korrektur ist installiert; der frische Testserver-Start erreichte `ready...`,
|
||||
Prozess und Port 8085 wurden bestätigt. Das nur für den Login geänderte
|
||||
Startprofil wurde zurückgesetzt.
|
||||
|
||||
Im laufenden Server wurden danach ein automatisch ausgewählter Katzenspaziergang
|
||||
mit 15 bestätigten Wegpunkten und durchgehend aktiver Leine sowie ein anschließend
|
||||
automatisch ausgewählter Spaziergang beobachtet. Gezielte Sitzszenen waren an
|
||||
den jeweiligen momentanen Rundwegpositionen nicht verfügbar; eine Live-Abnahme
|
||||
des exakten Innenraum-Sitzplatz-zu-Außenweg-Übergangs ist damit noch nicht belegt.
|
||||
Zur direkten Sichtprüfung wurde der Katzenspaziergang erneut gezielt gestartet.
|
||||
|
||||
## Zusammenhängende Fußrouten (27.10.2026)
|
||||
|
||||
Die oben dokumentierten früheren Live-Tests mit kleinen Kreisrouten sind
|
||||
historische Ergebnisse. Die neue Hin-/Rückwegplanung ersetzt diese Fußrouten.
|
||||
Der ausführbare C++-Regressionstest prüft Mindestreichweite, spiegelbildliche
|
||||
Rückwegpunkte, tatsächliche Ankunft, Rückkehr nach Zeitende und verweigerte
|
||||
MMAP-Verbindungen. Die sichtbare Natürlichkeit bleibt der Ingame-Abnahme
|
||||
vorbehalten.
|
||||
|
||||
Live-Test des neuen Stands: Arthoran ging mit Katze und bestätigter Leine
|
||||
von `(-8818.91, 614.20, 95.18)` zum 131,60 Yards entfernten Ziel
|
||||
`(-8891.75, 504.59, 94.09)`. Alle neun Hinweg- und neun Rückwegankünfte
|
||||
wurden bestätigt; die rückwärts besuchten Kontrollpunkte stimmten innerhalb
|
||||
eines Yards mit dem Hinweg überein. Die tatsächliche Rückkehr lag unter
|
||||
0,1 Yard vom Start entfernt. Alle 18 Begleiterproben bestätigten die aktive
|
||||
Leine. Danach wurde automatisch ein weiterer normaler Spaziergang geplant.
|
||||
Build mit `-j10`, Installation, Neustart, Ready-Meldung und Port 8085 waren
|
||||
erfolgreich; alle 26 Clientless-Testskripte bestanden. Das ist eine technische
|
||||
Live-Prüfung, keine abschließende visuelle Abnahme.
|
||||
|
||||
## Gleichmäßiges Tempo beim Haustierausführen
|
||||
|
||||
Die häufigen kurzen Stopps nach wenigen Yards wurden durch das native Folgen
|
||||
ausgelöst: `MoveSplineInit::SetWalk` bestimmt das Splinetempo, setzt aber nicht
|
||||
das Spielerflag `MOVEMENTFLAG_WALKING`. Der Folgegenerator las für Spieler
|
||||
bisher nur dieses Flag und sagte deshalb Laufbewegung voraus, obwohl Arthoran
|
||||
ging. Die Katze eilte voraus und die berechtigte Leinen-Abstandskontrolle
|
||||
unterbrach daraufhin den Besitzer.
|
||||
|
||||
Der generische native Folgegenerator verwendet jetzt bei einer aktiven
|
||||
Server-Spline deren tatsächliche Geschwindigkeit auch für Spieler. Ohne aktive
|
||||
Spline bleibt die Auswahl anhand der normalen Spielerbewegungsflags erhalten.
|
||||
Die Abstandsprüfung und der native Leinenzauber bleiben bestehen. Ein separater
|
||||
ausführbarer Regressionstest deckt servergesteuertes Gehen, explizite Tempi,
|
||||
Laufen, Kreaturen und normale Clientbewegung ab.
|
||||
|
||||
Live-Prüfung der Tempokorrektur: Die Katze begleitete Arthoran über acht
|
||||
jeweils etwa 20 Yards lange Wegstücke (80 Yards hinaus und zurück). Für
|
||||
alle acht gab es genau einen `NAV_START` und einen `NAV_COMPLETE`, keine
|
||||
Unterbrechungen mit erneutem Start derselben Strecke. Alle acht
|
||||
Begleiterproben bestätigten die aktive Leine; der Abstand lag bei etwa
|
||||
2,3–2,5 Yards. Die Pause am Wendepunkt blieb erhalten. Build mit `-j10`,
|
||||
Installation, Testserver-Neustart und alle 27 Clientless-Testskripte erfolgreich.
|
||||
Die abschließende visuelle Beurteilung erfolgt im Spiel.
|
||||
|
||||
Der Nutzer hat anschließend sowohl die zusammenhängenden Fußspaziergänge als
|
||||
auch das flüssige Haustierausführen nach der Tempokorrektur visuell bestätigt.
|
||||
Schlafdarstellung, Ausritte, Freizeitflüge und Angeln sind dadurch nicht abgenommen.
|
||||
|
||||
Training ergänzt Migration `2026_10_27_09_adventure_training.sql`. Es nutzt
|
||||
die Kampfreaktion, sucht höchstens 60 Yards lokal und respektiert das Ende des
|
||||
aktuellen Zeitblocks. Echte Angreifer unterbrechen das Training zugunsten der
|
||||
Selbstverteidigung. Kein Dummy-Spawn, Phasenwechsel oder künstlicher Schaden.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Lua im laufenden Testserver ändern
|
||||
|
||||
`.clientless luareload 26` liest Arthorans Profil und Adventure-Skript erneut von
|
||||
der Festplatte und führt das Verhalten einmal aus. In der Serverkonsole entfällt
|
||||
der führende Punkt. Der Befehl benötigt GM-Rechte und funktioniert für jeden
|
||||
eingeloggten, verwalteten clientlosen Spieler anhand seiner GUID.
|
||||
|
||||
Die Antwort enthält den tatsächlich verwendeten absoluten Skriptpfad. Es gelten
|
||||
weiterhin die vorhandenen Fallbacks: `adventure/profiles/<name>.lua` oder
|
||||
`adventure/profiles/generic.lua` sowie `adventure/overrides/<name>.lua` oder
|
||||
`adventure/generic.lua`. Die Engine hält keine kompilierten Skripte im Cache.
|
||||
|
||||
Für Entwicklung kann `worldserver.conf` direkt auf die Quelldateien zeigen:
|
||||
|
||||
```ini
|
||||
Clientless.ScriptRoot = "/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/clientless"
|
||||
```
|
||||
|
||||
Der Standard bleibt `scripts/clientless`, relativ zum Arbeitsverzeichnis des
|
||||
Worldservers. Eine nichtleere Umgebungsvariable `VCORE_CLIENTLESS_SCRIPT_DIR`
|
||||
hat Vorrang. Eine Änderung des Stammverzeichnisses erfordert einen Neustart;
|
||||
anschließende Lua-Dateiänderungen benötigen weder Build noch Installation oder
|
||||
Neustart. Die vorhandene Installation der Lua-Dateien bleibt für eigenständige
|
||||
Serverinstallationen erhalten.
|
||||
|
||||
Der Reload setzt einen untätigen Bot mit leerer Aktionswarteschlange voraus.
|
||||
Laufende Reisen, Flüge, Teleports und Passagiere auf Transportmitteln werden
|
||||
abgewiesen, ohne diese abzubrechen. Der Befehl hängt daher keine zusätzliche
|
||||
Reise an eine bereits laufende Reise an. Ein erfolgreicher Reload kann sofort
|
||||
die im geänderten Skript eingereihten Aktionen starten.
|
||||
|
||||
Profil und Verhalten werden zusammen geladen. Bei Lade- oder Laufzeitfehlern
|
||||
bleibt das bisherige Profil erhalten. Während des Reloads angeforderte Aktionen
|
||||
und Intent-Änderungen werden erst nach Erfolg übernommen. Lua-Logmeldungen
|
||||
können auch aus einem später fehlgeschlagenen Reload stammen. Fehlerdetails
|
||||
stehen im Serverlog; das Ergebnis wird zusätzlich als `LUA_RELOAD` im
|
||||
Navigationslog protokolliert. Lokale Variablen des alten Skriptaufrufs werden
|
||||
nicht fortgeführt; das entspricht dem bisherigen einmaligen Login-Aufruf.
|
||||
|
||||
Regressionstest: `python3 tests/clientless/test_lua_reload.py` (C++-Compiler und
|
||||
Lua-5.4-Entwicklungspaket erforderlich).
|
||||
@@ -0,0 +1,84 @@
|
||||
Wir hatten die Tagesroutinenplanung und die Mikroaktionen als zwei aufeinander aufbauende Systeme für die AdventureBots vorgesehen. Dabei war uns besonders wichtig, dass AdventureBots keine vollständig autonomen Spieler simulieren müssen, sondern vor allem glaubwürdige, sichtbare Abenteurer in der Spielwelt darstellen sollen.
|
||||
1. Tagesroutinenplanung
|
||||
Der Tagesroutinenplaner soll festlegen, was ein AdventureBot im Laufe seines Tages unternehmen möchte, ohne jeden einzelnen Handlungsschritt vorzugeben.
|
||||
|
||||
Wir hatten dafür serverseitige Lua-Skripte vorgesehen:
|
||||
- scripts/clientless/adventure/generic.lua als allgemeines Skript für AdventureBots mit abwechslungsreichem, teilweise zufälligem Tagesablauf.
|
||||
- Individuelle Overrides, beispielsweise overrides/arthoran.lua, um bestimmten Charakteren eigene Verhaltensweisen zu geben.
|
||||
- Einen getrennten Bereich für Testskripte.
|
||||
Ein Tagesablauf könnte beispielsweise beinhalten, dass Arthoran zunächst nach Eisenschmiede reist, dort eine Taverne besucht, später ein Abenteuer unternimmt und anschließend zu einem anderen Ort weiterzieht.
|
||||
|
||||
Die Tagesroutine beschreibt dabei lediglich die größeren Vorhaben, nicht jeden einzelnen Bewegungsschritt oder jede Animation.
|
||||
2. Intents als Verbindung zwischen Planung und Handlung
|
||||
Wir hatten ausdrücklich zwischen einem Intent (Absicht) und den daraus entstehenden Actions (Aktionen) unterschieden.
|
||||
|
||||
Die Lua-Schnittstelle sollte dafür eine semantische Anweisung wie intend anbieten.
|
||||
|
||||
Beispiele:
|
||||
Intent Bedeutung
|
||||
Eine Taverne in Eisenschmiede besuchen Dort einkehren und Bier trinken
|
||||
In die Todesminen gehen Ein Abenteuer erleben und gegen Gegner kämpfen
|
||||
Einen anderen Ort besuchen Dorthin reisen und eine entsprechende Tätigkeit ausüben
|
||||
|
||||
Lua beschreibt das Vorhaben. Der Core entscheidet, welche konkreten Aktionen zur Erfüllung erforderlich sind.
|
||||
|
||||
Die Lua-Skripte sollen also weder den Reiseweg selbst berechnen noch Animationen, Getränke, Kämpfe oder einzelne Interaktionsschritte manuell koordinieren müssen.
|
||||
3. Mikroaktionen während eines Intents
|
||||
Mikroaktionen sind die kleinen Handlungen, durch die der Bot sein übergeordnetes Vorhaben glaubwürdig ausführt.
|
||||
|
||||
Wir hatten insbesondere folgende Beispiele besprochen:
|
||||
Situation Mögliche Mikroaktionen
|
||||
Taverne besuchen Hinsetzen, trinken, essen, aufstehen
|
||||
Aufenthalt in einer Siedlung Sich umsehen, Emotes verwenden, mit NPCs oder anderen Bots sprechen
|
||||
Abenteuer unternehmen Auf Monster treffen, kämpfen, sich zwischendurch ausruhen
|
||||
Unterwegs sein Pausieren, rasten und situationsabhängige Handlungen ausführen
|
||||
|
||||
Der wichtige Grundsatz war, dass Mikroaktionen zum aktuellen Intent und zur Umgebung passen müssen.
|
||||
|
||||
Ein Bot, der eine Taverne besucht, soll dort nicht einfach nur stehen bleiben. Er soll durch passende Handlungen vermitteln, dass er tatsächlich eingekehrt ist.
|
||||
|
||||
Genauso soll ein Bot, der auf Abenteuerreise ist, nicht bloß von Location zu Location laufen, sondern auch entsprechende Aktivitäten ausführen können.
|
||||
4. Glaubwürdige Darstellung statt vollständiger Simulation
|
||||
Hier hatten wir eine wesentliche Einschränkung festgelegt:
|
||||
|
||||
AdventureBots sind in erster Linie RP-Darsteller, keine vollständig simulierten menschlichen Spieler.
|
||||
|
||||
Daraus ergeben sich unterschiedliche Anforderungen an die Ausführung.
|
||||
|
||||
Sichtbare Aktivitäten: Reisen, Tavernenszenen, Gespräche und andere Handlungen in der offenen Spielwelt sollen für echte Spieler möglichst glaubwürdig stattfinden.
|
||||
|
||||
Abstrahierte Aktivitäten: Nicht alles muss vollständig durchgespielt werden. Als Beispiel hatten wir die Todesminen besprochen: Ein AdventureBot könnte sichtbar den Dungeon betreten, sein Abenteuer anschließend intern abstrahiert absolvieren und später an einem plausiblen Ort wieder erscheinen.
|
||||
|
||||
Das bedeutet auch, dass ein Tavernengast nicht zwangsläufig ein vollständiges NPC-Handelssystem durchlaufen muss, nur um ein Bier zu trinken.
|
||||
|
||||
Bei Kämpfen gegen Monster hatten wir sie als Bestandteil von Abenteuer-Intents vorgesehen. Eine detaillierte Kampf-KI mit festgelegten Fähigkeiten, Taktiken und Entscheidungsregeln hatten wir in diesem Zusammenhang allerdings noch nicht ausgearbeitet.
|
||||
5. Dialoge und soziale Mikroaktionen
|
||||
Für Tavernenszenen hatten wir außerdem gemeinsame, lokalisierte Standarddialoge vorgesehen.
|
||||
|
||||
Ein Beispiel war:
|
||||
„Noch ein Bier bitte.“
|
||||
|
||||
Die Bots sollen solche Dialoge und passende Emotes situationsabhängig verwenden können, statt für jede Szene individuelle Texte zu benötigen.
|
||||
|
||||
Da sie echte clientlose Player verwenden, sind serverseitige Chatfunktionen grundsätzlich verfügbar.
|
||||
|
||||
Komplexere direkte Interaktionen mit menschlichen Spielern, etwa Gruppenspiel oder eine umfangreichere soziale KI, hatten wir ausdrücklich auf später verschoben.
|
||||
6. Entwicklungsreihenfolge
|
||||
Die Reihenfolge war ebenfalls klar:
|
||||
Clientless Player Core
|
||||
|
||||
Stabile Reiseplanung und Navigation
|
||||
|
||||
Intent-System und Tagesroutinen
|
||||
|
||||
Kontextabhängige Mikroaktionen
|
||||
|
||||
Das Navigationssystem ist dabei das Rückgrat. Es soll einen Bot zuverlässig zu den Orten bringen können, die seine Tagesroutine auswählt.
|
||||
|
||||
Erst darauf baut die eigentliche Verhaltenssteuerung auf.
|
||||
Zusammengefasst
|
||||
Unser bisheriges Konzept lautet:
|
||||
|
||||
Der Tagesroutinenplaner bestimmt, was der Bot unternehmen möchte. Ein Intent beschreibt das konkrete Vorhaben. Der Core organisiert die Umsetzung, und Mikroaktionen sorgen dafür, dass diese Tätigkeit in der Spielwelt glaubwürdig dargestellt wird.
|
||||
|
||||
Dabei müssen nur die für andere Spieler relevanten Aktivitäten tatsächlich sichtbar simuliert werden. Aufwendige Vorgänge können abstrahiert werden, wenn das dem Zweck der AdventureBots nicht widerspricht.
|
||||
@@ -0,0 +1,299 @@
|
||||
# Mikroaktionskatalog der sieben AdventureBot-Intents
|
||||
|
||||
Stand: 27.10.2026. Grundlage ist der [Intent-Katalog](intent-katalog.md) mit
|
||||
**sieben Grundintents**. Die bestehenden Detailkataloge für Geselligkeit,
|
||||
Abenteuer und Beruf werden hier um Instanzen, Ruhe, Freizeit und Wirtschaften
|
||||
ergänzt. Die neuen Detailvorschläge sind eine Arbeitsgrundlage zur Abstimmung.
|
||||
|
||||
Der bisherige Katalog vom 26.10.2026 beschreibt die vereinbarten Aktionen.
|
||||
Geselligkeitsaktionen sowie die Ausbaustufen für Ruhe, Freizeit, Wirtschaften
|
||||
und [Abenteuer-Erkundung](adventure-intent.md) sind implementiert. Der [Berufs-Ausbau](profession-intent.md) ergänzt profilgebundene, dauerhaft
|
||||
performative Arbeit an realen Zielen. Echte Kampfhandlungen bleiben eine spätere Ausbaustufe. Den geprüften Implementierungsstand
|
||||
beschreibt [autonomous-behavior.md](autonomous-behavior.md).
|
||||
|
||||
Die Aktionen werden nach den sieben Intents gewichtet und über
|
||||
Umgebungsbedingungen freigegeben. Einige Aktionen dürfen in mehreren
|
||||
Intent-Katalogen vorkommen, erhalten aber jeweils andere Gewichte und Varianten.
|
||||
|
||||
## Gemeinsame Grundfähigkeit: Lagerfeuer entzünden
|
||||
|
||||
Alle AdventureBots sollen selbst ein Lagerfeuer entzünden können. Diese
|
||||
Fähigkeit gehört unabhängig vom Berufsprofil zur gemeinsamen Grundausstattung;
|
||||
die Mikroaktionsauswahl prüft dafür weder Kochkunst noch eine Berufsstufe.
|
||||
Bei der Ausstattung der Bots wird der reguläre Spielerzauber **818 – Cooking
|
||||
Fire (Kochfeuer)** sichergestellt. Die ID wurde am 26.10.2026 in den vom
|
||||
Testserver geladenen nativen Zauberdaten bestätigt. Die SQL-Tabelle `spell_dbc`
|
||||
enthält hierfür keinen eigenen Datensatz; der Zauber stammt aus den DBC-Daten.
|
||||
|
||||
Ein Rastablauf kann damit lauten: geeigneten Rastplatz aufsuchen → vorhandenes
|
||||
Feuer nutzen oder selbst ein Lagerfeuer entzünden → hinsetzen → essen, trinken
|
||||
oder pausieren → weiterziehen. Vorhandene Feuer sind eine Möglichkeit, keine
|
||||
Voraussetzung. Neue Feuer dürfen nur außerhalb von Gebäuden und Städten
|
||||
entzündet werden; diese Grenze gilt für sämtliche Intents. Vorhandene geeignete
|
||||
Feuer bleiben nutzbar. Das eigene Feuer verwendet den normalen Zauber und dessen
|
||||
native Lebensdauer. Die Geselligkeitsumsetzung verwendet dafür den nativen Zauber und prüft
|
||||
das tatsächlich entstandene Feuerobjekt.
|
||||
|
||||
## Trinkfreude und Geselligkeit
|
||||
|
||||
Als Ergänzung ist das Ansprechen naher NPCs vorgesehen: Der Bot sucht einen
|
||||
nahen, freundlichen NPC, läuft über lokale Navigation auf Gesprächsabstand
|
||||
heran, richtet sich zu ihm aus und führt `/reden` aus. Anschließend bleibt er
|
||||
kurz stehen, zeigt gegebenenfalls eine weitere Gesprächsgeste und
|
||||
verabschiedet sich wieder. Der NPC muss dafür keine Antwort simulieren.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| **Trinken** | Ein Getränk trinken, anschließend eine Pause einlegen. In Tavernen besonders häufig. |
|
||||
| **Essen** | Eine kleine Mahlzeit darstellen, bevorzugt während eines längeren Aufenthalts. |
|
||||
| **Einen Sitzplatz aufsuchen** | Zu einer erreichbaren Sitzgelegenheit gehen und sich setzen. Falls keine geeignete vorhanden ist, stehen bleiben oder einen passenden Rastplatz verwenden. |
|
||||
| **Zum Tresen gehen** | Einen erreichbaren Platz beim Gastwirt aufsuchen und dort verweilen. |
|
||||
| **Ein Getränk bestellen** | Zum Gastwirt schauen, `/reden` ausführen und gelegentlich eine passende Bestellzeile sagen. Kein tatsächlicher Kauf erforderlich. |
|
||||
| **Mit einem NPC sprechen** | Zu einem nahen freundlichen NPC gehen, ausrichten und `/reden` ausführen. Gesprächspartner nicht ständig wechseln. |
|
||||
| **Einen anderen Bot ansprechen** | Wie beim NPC-Gespräch; zunächst ohne aufwendige gegenseitige Dialogsteuerung. |
|
||||
| **Jemanden begrüßen** | Bei einem passenden Gegenüber winken oder sich verbeugen. |
|
||||
| **Einem Gespräch zuhören** | Zum Gegenüber schauen und ruhig stehen bleiben, gelegentlich nicken. |
|
||||
| **Auf ein Gespräch reagieren** | Situationsabhängig lachen, zustimmen, eine Fragegeste oder eine nachdenkliche Geste zeigen. |
|
||||
| **Anstoßen oder jubeln** | Seltene gesellige Reaktion mit passendem Emote beziehungsweise kurzer Textzeile. |
|
||||
| **Sich im Raum umsehen** | Blickrichtung wechseln und andere Gäste oder den Raum betrachten. |
|
||||
| **Den Platz wechseln** | Eine kurze Strecke innerhalb der Location laufen und an einem anderen geeigneten Punkt verweilen. |
|
||||
| **Lagerfeuer entzünden** | An einem geeigneten Rastplatz mit dem gemeinsamen Grundzauber 818 ein eigenes Feuer entzünden; keine Kochkunst-Prüfung. |
|
||||
| **Am Feuer sitzen** | Ein vorhandenes geeignetes Feuer nutzen oder selbst eines entzünden, sich hinsetzen und rasten. |
|
||||
| **Tanzen** | Selten und bevorzugt bei Festen; in einer gewöhnlichen Taverne deutlich niedriger gewichtet. |
|
||||
| **Sich verabschieden** | Ein kurzer Abschiedsgruß vor dem Verlassen der Location oder nach einem Gespräch. |
|
||||
|
||||
Für den Tavernenaufenthalt sollten **Sitzen, Trinken, Essen und Gespräche** den
|
||||
Hauptanteil bilden. Tanzen, Jubeln und auffällige Emotes bleiben selten, damit
|
||||
der Bot nicht wie ein dauernd laufendes Animationsprogramm wirkt.
|
||||
|
||||
## Abenteuer
|
||||
|
||||
Hier wird zwischen Erkundung und späteren tatsächlichen Kampfhandlungen
|
||||
unterschieden.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| **Die Umgebung erkunden** | Unterschiedliche nahe Punkte über lokale Navigation aufsuchen. Bei Gebietszielen innerhalb des ausgewählten Gebiets bleiben. |
|
||||
| **Eine Aussicht betrachten** | An einem geeigneten Punkt stehen bleiben und den Blick über die Umgebung schweifen lassen. |
|
||||
| **Ein auffälliges Objekt untersuchen** | Sich einer Ruine, einem Denkmal, einem Wagen oder einem anderen geeigneten Objekt nähern und es betrachten. |
|
||||
| **Etwas genauer betrachten** | Zum Objekt ausrichten und eine passende Frage-, Zeige- oder Untersuchungsgeste ausführen. |
|
||||
| **Nach Gefahren Ausschau halten** | Kurz innehalten und mehrere Richtungen betrachten. Besonders passend bei Ruinen, Höhlen oder gefährlichen Gebieten. |
|
||||
| **Einen Wegabschnitt abschreiten** | Innerhalb des Aufenthaltsgebiets einige erreichbare Punkte nacheinander besuchen. |
|
||||
| **An einer Ruine oder Höhle verweilen** | Einen erreichbaren Punkt beim Eingang oder im sicheren Außenbereich untersuchen. |
|
||||
| **Einen freundlichen Reisenden ansprechen** | Zu einem passenden NPC gehen und `/reden` ausführen, etwa bei Wachen, Forschern oder anderen Abenteurern. |
|
||||
| **Auf etwas zeigen** | Ein sichtbares Objekt oder einen markanten Punkt mit einer Zeigegeste hervorheben. |
|
||||
| **Eine Entdeckung kommentieren** | Selten eine passende kurze Zeile sagen; vorzugsweise bei anwesenden Gesprächspartnern. |
|
||||
| **Eine Rast einlegen** | An einem geeigneten Punkt sitzen und pausieren. |
|
||||
| **Am Lagerfeuer rasten** | Ein vorhandenes Feuer nutzen oder am Rastplatz selbst eines entzünden, sitzen, essen oder trinken. |
|
||||
| **Proviant essen oder trinken** | Eine Pause während längerer Erkundungen darstellen. |
|
||||
| **Ausrüstung prüfen** | Eine kurze, ruhige Vorbereitungspause mit einer passenden verfügbaren Animation darstellen. |
|
||||
| **Vor einem Abenteuer vorbereiten** | Beim Dungeon- oder Höhleneingang verweilen, umsehen und gegebenenfalls einen kurzen Vorbereitungssatz sagen. |
|
||||
| **Nach einem Abenteuer ausruhen** | Nach Rückkehr eine längere Rast, Essen oder Trinken bevorzugen. |
|
||||
|
||||
### Spätere Kampferweiterung
|
||||
|
||||
| Aktion | Noch festzulegende Ausführung |
|
||||
|---|---|
|
||||
| **Ein geeignetes Monster jagen** | Ziel auswählen, annähern und tatsächlich kämpfen. |
|
||||
| **Einen Kampf abbrechen und fliehen** | Bei Überforderung einen erreichbaren Rückzugsort suchen. |
|
||||
| **Sich nach einem Kampf erholen** | Erst nach Ende der Gefahr rasten und regenerieren. |
|
||||
| **Eine Niederlage bewältigen** | Verhalten bei Tod und anschließender Rückkehr festlegen. |
|
||||
|
||||
**Monsterjagd sollte erst aktiviert werden, wenn diese zusammengehörigen
|
||||
Verhaltensweisen definiert sind.** Die Erkundungsaktionen können bereits vorher
|
||||
den Abenteuer-Intent tragen.
|
||||
|
||||
## Beruf
|
||||
|
||||
Berufsaktionen sollten sich nach dem Charakterprofil richten. Ein angehender
|
||||
Schmied besucht andere Orte und Objekte als ein Kräuterkundiger. Die eigentliche
|
||||
Arbeit bleibt dauerhaft rein performativ; Hauptberufe benötigen eine ausdrückliche Lua-Profilfreigabe.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| **Eine Arbeitsstelle aufsuchen** | Zu einem passenden erreichbaren Objekt oder Arbeitsplatz gehen. |
|
||||
| **Eine Erzquelle untersuchen** | An eine sichtbare Erzquelle herantreten und sie betrachten. |
|
||||
| **Erzabbau darstellen** | Zur Erzquelle ausrichten und die Bergbauanimation ausführen. Keine Beute, keine Erschöpfung oder Entfernung der Quelle. |
|
||||
| **Kräutersammeln darstellen** | Zu einer passenden Pflanze gehen und eine Sammelbewegung ausführen. Die Pflanze bleibt erhalten. |
|
||||
| **Holzarbeit darstellen** | An geeignetem Holz, einem Holzstapel oder Arbeitsplatz eine Arbeitsanimation zeigen. Keine Veränderung des Objekts. |
|
||||
| **An einer Schmiede arbeiten** | Einen erreichbaren Amboss oder eine Schmiedestelle aufsuchen und eine passende Arbeitsanimation ausführen. |
|
||||
| **Schmelzarbeit darstellen** | Bei einer geeigneten Esse beziehungsweise einem Ofen verweilen und Arbeit darstellen. |
|
||||
| **An einer Werkbank arbeiten** | Einen passenden Werkstattplatz aufsuchen und dort eine verfügbare Arbeitsanimation ausführen. |
|
||||
| **Alchemistische Arbeit darstellen** | Bei einem geeigneten Labortisch arbeiten; ohne Gegenstände oder Tränke zu erzeugen. |
|
||||
| **Schneider- oder Lederarbeit darstellen** | An einem passenden Arbeitsplatz eine geeignete Handarbeitsanimation verwenden, soweit sie verfügbar ist. |
|
||||
| **Angeln darstellen** | An einem erreichbaren Ufer mit geeignetem Wasser und einer passenden Darstellung angeln. Kein Fang und keine Veränderung des Inventars. |
|
||||
| **Werkzeug oder Material prüfen** | Den Arbeitsablauf durch eine kurze Prüfungspause unterbrechen. |
|
||||
| **Mit einem Ausbilder sprechen** | Zu einem passenden Berufsausbilder gehen und `/reden` ausführen. Kein tatsächliches Erlernen erforderlich. |
|
||||
| **Mit einem Händler sprechen** | Einen passenden Händler aufsuchen und ein kurzes Gespräch darstellen. Kein Kauf notwendig. |
|
||||
| **Die Arbeitsstelle wechseln** | Einen anderen passenden Arbeitsplatz oder eine andere nahe Ressource aufsuchen. |
|
||||
| **Eine Arbeitspause einlegen** | Sich umsehen, sitzen, essen oder trinken. |
|
||||
| **Die Arbeit abschließen** | Die Arbeitsanimation beenden, kurz das Ergebnis betrachten und sich vom Arbeitsplatz lösen. |
|
||||
|
||||
Bei Berufen sollten **nur Darstellungen freigegeben werden, für die eine passende
|
||||
Animation und Umgebung vorhanden sind**. Fehlt beispielsweise eine überzeugende
|
||||
Schneideranimation, kann der Bot dort zunächst untersuchen, mit dem Ausbilder
|
||||
sprechen und pausieren.
|
||||
|
||||
## Kleine Abläufe statt einzelner zufälliger Gesten
|
||||
|
||||
Manche Mikroaktionen benötigen einen kurzen zusammenhängenden Ablauf.
|
||||
|
||||
**Gespräch:** Gesprächspartner wählen → hinlaufen → ausrichten → `/reden` →
|
||||
kurz zuhören → verabschieden.
|
||||
|
||||
**Arbeit:** Arbeitsobjekt wählen → hinlaufen → ausrichten → arbeiten →
|
||||
Ergebnis betrachten → Pause.
|
||||
|
||||
Der gewichtete Zufall wählt solche Abläufe und ihre Varianten. Während eines
|
||||
begonnenen Ablaufs würfelt der Bot nicht unvermittelt eine unpassende andere
|
||||
Handlung aus. Zusätzlich werden Wiederholungen von **Aktionsart, Variante und
|
||||
Zielobjekt beziehungsweise Gesprächspartner** gedämpft. Dadurch geht Arthoran
|
||||
beispielsweise nicht nach jedem zweiten Getränk wieder zum selben NPC.
|
||||
|
||||
## Priorisierung des Ausbaus
|
||||
|
||||
Die Geselligkeits-Ausbaustufe umfasst NPC-/Bot-Gespräche, Sitzplatzsuche,
|
||||
Tresen/Gastwirt und situationsbezogene Gesprächsreaktionen. Objektuntersuchung
|
||||
und die weiteren Abenteuer- und Berufsaktionen können darauf aufbauen,
|
||||
ohne bereits die Kampf-KI vorauszusetzen.
|
||||
|
||||
## Instanzen
|
||||
|
||||
Der Besuch ist performativ. Die sichtbare Anreise und das Betreten müssen
|
||||
plausibel stattfinden; ein Durchlaufen oder Kampf innerhalb der Instanz ist
|
||||
nicht erforderlich. Die verborgene Aufenthaltsphase ist Teil des Intent-Ablaufs,
|
||||
keine zufällig neben anderen Gesten auswählbare Mikroaktion.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| Den Eingang aufsuchen | Einen erreichbaren Wartepunkt vor dem passenden Instanzeingang aufsuchen. |
|
||||
| Den Eingang betrachten | Zum Eingang schauen, kurz innehalten und sich umsehen. |
|
||||
| Sich vorbereiten | Ausrüstung prüfen und eine kurze Vorbereitung darstellen. |
|
||||
| Proviant zu sich nehmen | Vor dem Betreten essen oder trinken, sofern ein geeigneter Platz vorhanden ist. |
|
||||
| Andere Abenteurer begrüßen | Nur bei tatsächlich anwesendem passendem Gegenüber. |
|
||||
| Die Instanz betreten | Den tatsächlichen Eingang nutzen; bloßes Stehen davor zählt nicht als Besuch. |
|
||||
| Den Aufenthalt abstrahieren | Nach bestätigtem Eintritt für eine festgelegte Besuchsdauer außerhalb der sichtbaren Außenwelt bleiben. Keine Dungeon-KI erforderlich. |
|
||||
| Am Ausgang zurückkehren | Nach dem Aufenthalt am zugehörigen plausiblen Ausgang wieder erscheinen. |
|
||||
| Nach dem Besuch sammeln | Kurz orientieren, Ausrüstung prüfen oder eine Rast darstellen. |
|
||||
|
||||
Vorgeschlagener Ablauf: Anreise → Vorbereitung → bestätigter Eintritt →
|
||||
abstrahierter Aufenthalt → Rückkehr → kurze Nachbereitung.
|
||||
Zeitmodell, Unterbringung, Neustartverhalten und Rückkehrposition wurden am
|
||||
27.10.2026 vom Nutzer konkretisiert: verbleibender Location-Zeitblock mit fünf
|
||||
Minuten Nachruhe, Warten direkt hinter dem Eingang in der eigenen Instanzkopie,
|
||||
Wiederaufnahme mit ursprünglicher Frist und Rückkehr über den zugehörigen
|
||||
Ausgang beziehungsweise Eingang. Details und technische Vorprüfung stehen in
|
||||
[instance-intent.md](instance-intent.md). Ein fehlgeschlagener Eintritt darf die
|
||||
Aufenthaltsphase nicht starten.
|
||||
|
||||
## Ruhe
|
||||
|
||||
Die erste Umsetzung ist als [Ruhe-Intent `rest`](rest-intent.md) dokumentiert:
|
||||
native Sitzplätze, markierte Schlaf-/Bodenrastplätze, Essen und Trinken im
|
||||
Sitzen, ruhiges Umsehen und Feuerrast über die gemeinsame Feuerfähigkeit.
|
||||
Neue Feuer sind im Ruhe-Intent auf markierte Bodenrast-Locations beschränkt. Weitere Aktionen dieses Katalogs bleiben Ausbau.
|
||||
|
||||
Erholung ist das eigentliche Vorhaben. Schlaf und längere Rast brauchen einen
|
||||
passenden Platz; zufälliges Niederlegen auf Straßen oder in Durchgängen ist
|
||||
keine geeignete Standarddarstellung.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| Einen Ruheplatz suchen | Einen erreichbaren geeigneten Schlaf- oder Rastplatz aufsuchen. |
|
||||
| Sich zur Ruhe setzen | Einen nativen Sitzplatz benutzen oder an einem geeigneten Rastpunkt am Boden sitzen. |
|
||||
| Sich schlafen legen | An einem geeigneten Platz eine native Schlafdarstellung verwenden; vorhandene geeignete Betten bevorzugen, ohne deren Benutzbarkeit vorauszusetzen. |
|
||||
| Schlafen | Eine zusammenhängende Ruhephase ohne dazwischengewürfelte Gespräche oder Arbeitsgesten halten. |
|
||||
| Aufwachen und aufstehen | Schlafdarstellung beenden und sich vor dem Weitergehen aufrichten. |
|
||||
| Am Feuer ruhen | Ein vorhandenes Feuer aufsuchen oder an geeignetem Platz ein eigenes entzünden. |
|
||||
| Eine kleine Mahlzeit einnehmen | Essen oder trinken als Teil einer Rast. |
|
||||
| Ruhig verweilen | Im Sitzen oder Stehen eine längere stille Pause einlegen. |
|
||||
| Den Ruheplatz verlassen | Sitz- oder Schlafzustand sauber beenden und den Platz freigeben. |
|
||||
|
||||
## Freizeit
|
||||
|
||||
Die Umsetzung ist in [Freizeit-Intent `leisure`](leisure-intent.md) dokumentiert.
|
||||
|
||||
Die Bewegung oder Beschäftigung ist hier selbst das Ziel. Freizeit braucht
|
||||
keine ständig neuen Sehenswürdigkeiten oder vorgetäuschten Arbeitsaufträge.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| Spazieren gehen | Mehrere erreichbare Punkte innerhalb der gewählten Stadt oder Umgebung im Gehmodus besuchen. |
|
||||
| Ziellos umherlaufen | Abwechslungsreiche lokale Ziele innerhalb eines begrenzten Aufenthaltsbereichs wählen; keine endlose Fernreise. |
|
||||
| Ein Haustier ausführen | Eigenen Begleiter beschwören, wenn möglich mit der nativen Haustierleine anleinen, einer zusammenhängenden lokalen MMAP-Strecke folgen und auf demselben Weg zurückkehren. Arthoran verwendet eine Bombay-Katze. |
|
||||
| Einen Ausritt machen | In einer geeigneten Umgebung beritten umherziehen; vor unzulässigen Bereichen absteigen. |
|
||||
| Einen Rundflug machen | Bei vorhandener Flugfähigkeit und erlaubtem Gebiet einen Freizeitflug mit geeigneter Landemöglichkeit durchführen. |
|
||||
| Eine Aussicht genießen | Einen geeigneten Aussichtspunkt aufsuchen und länger betrachten. |
|
||||
| An einem Platz verweilen | Einen Park, Brunnen, Marktplatz oder ein Ufer besuchen und dort pausieren. |
|
||||
| Angeln darstellen | Einen erreichbaren geeigneten Angelplatz aufsuchen und den gemeinsamen Angelablauf verwenden. |
|
||||
| Andere beobachten | Zum tatsächlichen Geschehen schauen und ruhig verweilen. |
|
||||
| Sich ungezwungen unterhalten | Einen passenden anwesenden NPC oder Bot ansprechen. |
|
||||
| An einem Fest teilnehmen | Nur bei tatsächlich passender Umgebung gelegentlich tanzen, jubeln oder andere Festgesten zeigen. |
|
||||
| Eine Pause einlegen | Sitzen, essen oder trinken; anschließend die Freizeitbeschäftigung fortsetzen. |
|
||||
|
||||
## Wirtschaften
|
||||
|
||||
Alle Tätigkeiten sind performativ. Es gibt keine tatsächlichen Käufe,
|
||||
Verkäufe, Auktionen, Gebote, Banktransfers oder Geldbewegungen.
|
||||
|
||||
| Aktion | Darstellung und Bedingungen |
|
||||
|---|---|
|
||||
| Einen Händler aufsuchen | Zu einem erreichbaren passenden Händler gehen. |
|
||||
| Waren betrachten | Zum Händler oder einer geeigneten Auslage ausrichten und verweilen. |
|
||||
| Ein Handelsgespräch darstellen | Begrüßen, reden, zuhören und gegebenenfalls eine passende Textzeile verwenden. |
|
||||
| Angebote vergleichen | Nacheinander unterschiedliche passende Händler oder Stände besuchen; Wiederholungen dämpfen. |
|
||||
| Das Auktionshaus besuchen | Den zugänglichen Innenbereich beziehungsweise einen geeigneten Auktionator aufsuchen. |
|
||||
| Auktionen betrachten | Beim Auktionator eine ruhige Prüfphase mit gelegentlichen passenden Gesten darstellen. |
|
||||
| Die Bank besuchen | Einen geeigneten Bankschalter beziehungsweise Bankier aufsuchen. |
|
||||
| Bankgeschäfte darstellen | Am Schalter verweilen und ein kurzes Gespräch oder eine Prüfung darstellen. |
|
||||
| Taschen und Vorräte prüfen | Eine kurze Vorbereitung oder Nachbereitung ohne Inventaränderung darstellen. |
|
||||
| Auf Bedienung warten | An einem geeigneten Punkt kurz warten; kein vollständiges Warteschlangensystem erforderlich. |
|
||||
| Den Besuch abschließen | Verabschieden, Interaktion beenden und den Schalter oder Stand verlassen. |
|
||||
|
||||
## Gemeinsame Aktionen und Intent-Zuordnung
|
||||
|
||||
Eine Aktion wird einmal als Fähigkeit umgesetzt und kann mehreren Intents
|
||||
zugeordnet werden. Der Intent liefert Gewicht, Dauer, Variante und Zielpräferenz.
|
||||
Ein passender Intent allein reicht nicht: Umgebung, erreichbares Ziel und
|
||||
benötigte Darstellung müssen ebenfalls passen. Es werden nicht alle Aktionen
|
||||
automatisch für jeden Intent freigeschaltet.
|
||||
|
||||
| Gemeinsame Aktion | Passende Intents | Unterschied im Ablauf |
|
||||
|---|---|---|
|
||||
| Angeln | Freizeit, Beruf | Freizeit betont entspanntes Verweilen; Beruf betont die wiederholte dargestellte Arbeit am Angelplatz. |
|
||||
| Sitzen | Ruhe, Geselligkeit, Freizeit; als Pause auch Abenteuer und Beruf | Ruhe hält eine längere Erholungsphase; Geselligkeit verbindet Sitzen mit Trinken und Gesprächen. |
|
||||
| Essen und Trinken | Geselligkeit, Ruhe, Abenteuer, Beruf, Freizeit, Instanzen | Tavernenaufenthalt, Rast, Arbeitspause oder Vorbereitung bestimmen Dauer und Variante. |
|
||||
| Lagerfeuer und Feuerrast | Abenteuer, Ruhe, Geselligkeit, Freizeit | Je nach Vorhaben unterwegs rasten, länger ruhen oder gesellig verweilen. |
|
||||
| Gespräch | Geselligkeit, Abenteuer, Beruf, Freizeit, Wirtschaften, Instanzen | Gastwirt, Reisender, Ausbilder, Händler oder Abenteurer sind passende unterschiedliche Ziele. |
|
||||
| Umsehen und Betrachten | Alle sieben | Blickziel und Anlass müssen zur Szene passen. |
|
||||
| Ausrüstung oder Vorräte prüfen | Abenteuer, Beruf, Instanzen, Wirtschaften | Vorbereitung, Werkzeugprüfung oder dargestellte Bestandsprüfung. |
|
||||
| Ortswechsel | Alle sieben | Unterstützt das Vorhaben; nur bei Freizeit kann die Bewegung selbst die Haupttätigkeit sein. |
|
||||
|
||||
### Gemeinsamer Angelablauf
|
||||
|
||||
Angelplatz wählen → zum erreichbaren Ufer gehen → zum geeigneten Wasser
|
||||
ausrichten → Angeln darstellen → warten → gegebenenfalls wiederholen →
|
||||
Darstellung beenden und Platz verlassen.
|
||||
|
||||
Für beide Intents bleibt Angeln zunächst performativ: kein Fang und keine
|
||||
Inventaränderung. Vor der Implementierung sind geeignete native Darstellung,
|
||||
eventuell benötigte Ausrüstung und die Prüfung eines Angelplatzes zu klären.
|
||||
Die Wiederverwendung derselben Fähigkeit darf keine tatsächliche Beuteerzeugung
|
||||
als unbeabsichtigten Nebeneffekt einschalten.
|
||||
|
||||
## Schrittweise Umsetzung
|
||||
|
||||
Die folgenden Schritte sind ein Vorschlag für die Reihenfolge, keine bereits
|
||||
implementierten Funktionen:
|
||||
|
||||
1. Den Katalog abstimmen und je Ausbaustufe Ziele, Voraussetzungen und Abschluss festlegen.
|
||||
2. Ruhe mit Sitz-, Rast- und Schlafabläufen ergänzen; bestehende Sitz- und Feuerfähigkeiten wiederverwenden.
|
||||
3. Freizeit mit Spaziergängen und Aufenthalten ergänzen; Ausritte und Rundflüge gesondert prüfen.
|
||||
4. Wirtschaften mit Händler-, Bank- und Auktionshausbesuchen ergänzen.
|
||||
5. Abenteuer um gezielte Erkundung und Objektuntersuchung erweitern.
|
||||
6. Beruf um passende Arbeitsplätze und Darstellungen erweitern; Angeln gemeinsam für Beruf und Freizeit ergänzen.
|
||||
7. Instanzbesuche mit bestätigtem Eintritt, abstrahiertem Aufenthalt und zuverlässiger Rückkehr ergänzen.
|
||||
|
||||
Jede Stufe erhält passende technische Prüfungen und anschließend eine visuelle
|
||||
Abnahme im Spiel. Der bestehende Geselligkeitsausbau bleibt Grundlage für
|
||||
gemeinsame Gesprächs-, Sitz- und Rastfähigkeiten. Echte Kampf-KI bleibt separat.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Portal-Auswahl für AdventureBots
|
||||
|
||||
Nutzerentscheidungen vom 26.10.2026, zusätzlich zur historischen
|
||||
Bestandsaufnahme in `same-map-portals.md/json`:
|
||||
|
||||
| Übergänge | Entscheidung |
|
||||
| --- | --- |
|
||||
| 527/542, Rut’theran ↔ Darnassus | Aktiv, live getestet. |
|
||||
| 702/704, Magierturm Sturmwind | Aktiv, live getestet; Groundanschluss wird vom Nutzer später aufgenommen. |
|
||||
| 6321/6322, Ödland Anleger ↔ Klippe | Als Bot-Reiseziel gewünscht; gezielt importiert und live getestet. |
|
||||
| 4233/4267, Duskwither im Immersangwald | Außerhalb des Graphen lassen. Laut Nutzer questbezogen und kein gewünschtes Reiseziel. |
|
||||
| 5273, Dalaran-Brunnen | Vorerst außerhalb lassen. Laut Nutzer voraussichtlich Sprung in den Brunnen; alternative Zugänge zur Kanalisation vorhanden. |
|
||||
| Arena-interne Umsetzungen | Für den aktuellen Reisegraph irrelevant; nicht importieren. |
|
||||
| Eindeutige Quest-/Phasenübergänge | Derzeit nicht allgemein freigeben. |
|
||||
| Dungeon-/Raid-interne Übergänge | Zurückstellen; für spätere Gruppenbegleitung gegebenenfalls erneut bewerten. |
|
||||
|
||||
Dungeon-Eingänge sind ausdrücklich relevante Reiseziele und wurden deshalb
|
||||
bereits importiert. Das bedeutet keine Freigabe selbstständiger Bewegung
|
||||
innerhalb einer Instanz. Für allein reisende AdventureBots genügt gemäß
|
||||
Nutzerwunsch perspektivisch ein zeitlich simulierter Aufenthalt mit späterer
|
||||
Rückkehr am Ausgang. Diese Aktion ist durch diese Portalarbeit **nicht
|
||||
implementiert**. Die spätere Begleitung von Spielergruppen innerhalb von
|
||||
Dungeons ist gesondert zu behandeln; interne Teleporter werden deshalb nicht
|
||||
pauschal als dauerhaft unnötig eingeordnet. DungeonBots bleiben unabhängig.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Beruf (`profession`)
|
||||
|
||||
Berufsaktionen bleiben dauerhaft rein performativ. Der Bot bewegt sich mit
|
||||
TravelGraph und MMAP zu echten Ressourcen, Arbeitsplätzen oder Ansprechpartnern
|
||||
und stellt die Tätigkeit mit nativen Gesten dar. Er benutzt keine Quellen,
|
||||
erzeugt keine Beute, verarbeitet keine Materialien, erhöht keine Fertigkeiten,
|
||||
lernt nichts und heilt nicht tatsächlich.
|
||||
|
||||
Hauptberufe werden ausschließlich im Lua-Profil über `professions.primary`
|
||||
freigegeben. Arthoran besitzt `mining` und `blacksmithing`; das generische Profil
|
||||
besitzt keine Hauptberufe. Unbekannte Namen gewähren keine Berechtigung.
|
||||
Nebenberufe benötigen keine Hauptberufsfreigabe. Die Freigabe wird auch während
|
||||
einer laufenden Szene geprüft.
|
||||
|
||||
Der Tagesplan wählt den Intent unabhängig vom Ortsbestand. Danach wird ein
|
||||
geeigneter importierter Ort oder ein Gebiet ausgewählt. Erst vor Ort bestimmen
|
||||
reale Ziele und Profilrechte die möglichen Mikroaktionen. Eine Workshop- oder
|
||||
Gebietszuordnung ersetzt keinen Amboss und gewährt keine Hauptberufe.
|
||||
|
||||
Erz und Pflanzen werden anhand nativer Lock-Skills erkannt, nicht anhand ihrer
|
||||
Namen. Quellen müssen gespawnt, bereit, sichtbar und in der passenden Phase sein.
|
||||
Kürschnerei setzt einen vorhandenen toten, kürschnerbaren Tierkadaver voraus.
|
||||
Arbeitsplatzrollen stehen im editierbaren Katalog `vcore_adventure_workstation`.
|
||||
Die Migration `2026_10_27_05_adventure_profession.sql` ergänzt native Fokusrollen
|
||||
und erkennbare Arbeitsobjekte. Amboss und Esse haben getrennte Rollen; deaktivierte
|
||||
Rollen und bearbeitete Gewichte bleiben bei erneuter Migration erhalten.
|
||||
Trainer werden anhand nativer Tradeskill- und SkillLine-Daten zugeordnet.
|
||||
|
||||
Eine Szene nähert sich dem Ziel über normale Navigation, zeigt die Arbeit erst
|
||||
nach bestätigter Ankunft, betrachtet das Ergebnis und tritt kurz zurück.
|
||||
Verlust von Profilrecht, Ziel oder Arbeitsplatz beendet die Darstellung.
|
||||
Kürzlich vollständig dargestellte Sammelziele werden über die Zielhistorie
|
||||
vorübergehend gemieden. Reines Erzbetrachten setzt diese Bearbeitungssperre nicht.
|
||||
|
||||
Gebietsaufträge reisen zu einem erreichbaren Graphknoten im Zielgebiet. Die lokale
|
||||
Suche nutzt fortschreitende Bodenrouten und prüft an bestätigten Wegpunkten erneut
|
||||
auf zulässige Arbeit. Nach abgeschlossenem Fortschritt verschiebt sich der lokale
|
||||
Anker. Angeln verlangt eine ausgerüstete Angel und tatsächliches nahes Wasser;
|
||||
es wird kein Angelzauber ausgeführt und kein Fisch gefangen.
|
||||
|
||||
Automatisierte Prüfungen führen den produktiven Profilparser mit Lua 5.4,
|
||||
die native Zielklassifikation und die Szenensteuerung mit Server-Doubles aus.
|
||||
Katalogfixtures prüfen Wiederholbarkeit und Erhalt bearbeiteter Einstellungen.
|
||||
Diese Prüfungen ersetzen nicht die visuelle Abnahme im Spiel.
|
||||
|
||||
## Technischer Teststand am 27.10.2026
|
||||
|
||||
37 Clientless-Testskripte bestanden; Debug-Build mit `-j10` installiert,
|
||||
Migration `_05` auf der Test-DB angewendet. Frische Ready-Meldung, Prozess und
|
||||
Port 8085 geprüft. Arthoran erreichte den importierten Schmiedeort regulär
|
||||
über Graph, Taxi und MMAP und stellte am echten Amboss 201415 (Low 556)
|
||||
`smithing_show` dar. Work-Emote 233, Ergebnisbetrachtung und Wegtreten wurden
|
||||
im Serverlog bestätigt. Eine angeforderte Kräuterszene wurde zurückgewiesen.
|
||||
Nach `saveall` blieb die Geld-/Inventar-Prüfsumme unverändert.
|
||||
|
||||
Elwynn (`poi_tele_338`) wurde als Gebiet geladen, über `travel_to_node` samt
|
||||
bestehendem Free-flight-Fallback erreicht und mit `INTENT_ARRIVED` bestätigt.
|
||||
Die anschließende lokale `profession_search` absolvierte alle sechs progressiven
|
||||
MMAP-Wegpunkte mit etwa 104 Yards Ausdehnung (`LEISURE_COMPLETE`, legs=6). Ressourcenabbau in freier Wildbahn,
|
||||
weitere Berufe und die sichtbare Darstellung sind damit noch nicht live abgenommen.
|
||||
|
||||
Zwei im Test gefundene Fehler wurden behoben: VMAP-Sichtlinien zu unsichtbaren
|
||||
Arbeitsplatzmarkern prüfen jetzt die Arbeitsfläche oberhalb des Bodenmarkers;
|
||||
die Location-Abfrage erhält die nativen numerischen Spaltentypen, damit Debug
|
||||
Gebietsflag und Fraktion korrekt liest. Ein während aktiver Reise beobachteter
|
||||
Graph-Handover-/Recovery-Loop zu `portal_at_109_target` bleibt ein separater
|
||||
unbehobener Befund.
|
||||
@@ -0,0 +1,281 @@
|
||||
# Ruhe-Intent
|
||||
|
||||
Stand: 27.10.2026. Technischer Intentname: `rest`.
|
||||
|
||||
Ruhe ist ein eigenes Vorhaben mit anschließender Auswahl passender
|
||||
Mikroaktionen. Tavernen werden bei der Ortswahl stärker gewichtet als
|
||||
Siedlungen. Native Stühle und Bänke dürfen auch außerhalb von Tavernen
|
||||
benutzt werden, beispielsweise in Sturmwind. Ein Ort ohne passende
|
||||
Ruhemöglichkeit löst die Suche nach einer Ersatzlocation aus.
|
||||
|
||||
## Mikroaktionen
|
||||
|
||||
| Schlüssel | Ausführung |
|
||||
|---|---|
|
||||
| `rest_seat` | Erreichbaren nativen Stuhl oder eine Bank aufsuchen, regulär benutzen und 60–100 Sekunden sitzen. |
|
||||
| `rest_sleep` | Einen geprüften Schlafplatz nahe dem Schlafanker oder im Gasthaus aufsuchen und 120–300 Sekunden mit nativer Schlafhaltung ruhen. |
|
||||
| `rest_ground` | Einen ausdrücklich markierten Bodenrastplatz aufsuchen und 60–120 Sekunden sitzen. |
|
||||
| `rest_drink` | Eine vorhandene native Sitzgelegenheit benutzen und Trinken darstellen. |
|
||||
| `rest_eat` | Eine vorhandene native Sitzgelegenheit benutzen und Essen darstellen. |
|
||||
| `rest_look` | Kurzes ruhiges Umsehen zwischen den Ruhephasen. |
|
||||
| `rest_fire` | Vorhandenes geeignetes Feuer nutzen oder an einem markierten Bodenrastplatz ein natives Kochfeuer entzünden, hingehen, sitzen, trinken und ruhen (45–75 Sekunden Szenenbasis). |
|
||||
|
||||
Sitz-, Ess-, Trink- und Feuerabläufe verwenden dieselben Fähigkeiten wie Geselligkeit.
|
||||
`2026_10_27_01_adventure_rest_fire.sql` ergänzt `rest_fire` mit Auswahlgewicht 3,
|
||||
ohne vorhandene Szenen oder manuell geänderte Gewichte zu überschreiben.
|
||||
|
||||
Für vorhandene Feuer gelten die bisherigen Ortsgrenzen, Phasen-, Sicht- und
|
||||
Navigationsprüfungen. Ein eigenes Feuer wird bei `rest` nur an einer Location
|
||||
mit Kategorie `rest_ground` erlaubt, zusätzlich zu den bestehenden Prüfungen
|
||||
auf Außenbereich, ebenen freien Boden, Wasser, Fallen und Zauberabklingzeit.
|
||||
Zusätzlich verbietet die gemeinsame Feuerfähigkeit das Entzünden innerhalb von
|
||||
Städten für sämtliche Intents. Dafür werden Stadt-/Handelskanal-Kennzeichen der
|
||||
nativen AreaTable am aktuellen Standort, in übergeordneten Gebieten und der
|
||||
Zone geprüft. Fehlende oder zyklische Gebietsdaten erlauben kein neues Feuer.
|
||||
Die Prüfung erfolgt auch unmittelbar vor dem Zaubern. Vorhandene geeignete
|
||||
Feuer bleiben in Städten und Gebäuden nutzbar.
|
||||
Ein fehlendes Feuer an einer Stadtbank oder in einer Taverne berechtigt nicht
|
||||
zum Entzünden. Der native Zauber 818 benötigt keine Kochkunst; erst das
|
||||
bestätigte Feuerobjekt erlaubt die anschließende Feuerrast. Verschwindet es,
|
||||
endet die Szene. Aufstehen und Aufräumen erfolgen über denselben Szenenabschluss
|
||||
wie bei den anderen Ruheaktionen.
|
||||
Gespräche, Bestellungen und Tanz gehören nicht zum anfänglichen Ruhe-Katalog.
|
||||
Die Zeit der Schlaf- und Bodenrastphase beginnt nach bestätigter Ankunft;
|
||||
die lokale Anreise verwendet den Gehmodus und kein Bodenmount.
|
||||
|
||||
## Geeignete Orte
|
||||
|
||||
Die additive Migration ist
|
||||
`sql/custom/world/2026_10_27_00_adventure_rest.sql` (nach den bisherigen
|
||||
Verhaltens- und Geselligkeitsmigrationen anwenden).
|
||||
|
||||
Die vorhandene Weltpunkt-Tabelle bleibt der Ortskatalog. Zusätzliche Kategorien:
|
||||
|
||||
- `rest_seat`: Anlaufpunkt bei einer geeigneten nativen Sitzgelegenheit.
|
||||
- `rest_sleep`: ausdrücklich festgelegter Schlafplatz mit Position und Ausrichtung.
|
||||
- `rest_ground`: ausdrücklich festgelegter Bodenrastplatz.
|
||||
|
||||
Ein Schlafanker ist keine automatische Bettinteraktion. Der Bot sucht heute
|
||||
eine freie Liegefläche in seiner Nähe, läuft regulär dorthin und nimmt die native
|
||||
Schlafhaltung ein (Details und Grenzen im Abschnitt zur Flächensuche unten).
|
||||
Dekorative Betten werden weder als benutzbar vorausgesetzt noch durch Teleports
|
||||
betreten. Neue Schlafplätze benötigen weiterhin eine visuelle Abnahme.
|
||||
|
||||
Die Migration ergänzt einen Ruheplatz im Obergeschoss der Goldhainer Taverne
|
||||
(`goldshire_sleep_upstairs`) und einen Anlaufpunkt bei einer vorhandenen
|
||||
Sturmwinder Steinbank (`stormwind_rest_bench`, Spawn 219847, Entry 203946).
|
||||
Die Bankdefinition wird nur angelegt, wenn der passende native Spawn vorhanden
|
||||
ist. Bestehende Definitionen und manuell bearbeitete Gewichte bleiben erhalten.
|
||||
|
||||
Beim Schlafen oder Bodenrasten muss der Punkt zur Fraktion und Karte passen
|
||||
und höchstens 30 Yards vom Aufenthaltsanker entfernt sein; maximal 12 Yards
|
||||
Höhenunterschied erlauben einen Schlafplatz im Obergeschoss. Der lokale Weg
|
||||
muss vollständig und unverdächtig sein und darf maximal 120 Yards lang sein.
|
||||
Anlauf und Ankunft prüfen auf andere Spieler am Platz. Die Ankunft muss
|
||||
innerhalb von 60 Sekunden und mit höchstens einem Yard Positionsabweichung
|
||||
bestätigt werden. Wasser, Fallen, Kartenwechsel, entfernte Ortsdefinitionen,
|
||||
veränderte Ruhehaltung und Kampf beenden beziehungsweise verhindern die Szene.
|
||||
Beim Abbruch oder Intentwechsel wird die Haltung zurückgesetzt. Fernreisen
|
||||
behalten die vorhandene sichere Übergabe an regulären Graphnodes.
|
||||
|
||||
## Bedienung
|
||||
|
||||
Serverkonsole (im Spiel mit führendem Punkt):
|
||||
|
||||
```text
|
||||
clientless adventure intent 26 rest goldshire_tavern 3600
|
||||
clientless adventure status 26
|
||||
clientless adventure micro 26 rest_sleep
|
||||
clientless adventure intent 26 rest stormwind_rest_bench 3600
|
||||
clientless adventure micro 26 rest_seat
|
||||
clientless adventure stop 26
|
||||
```
|
||||
|
||||
`micro` ist ein gezielter Test während eines laufenden passenden Intents am
|
||||
Zielort. Es umgeht weder Ortsbedingungen noch Navigation oder native
|
||||
Sitzbestätigung. Der Tagesplaner kann `rest` anhand von
|
||||
`activity_affinity.rest` auswählen (Standardgewicht 0,5); vorhandene gespeicherte
|
||||
Tagespläne werden nicht nachträglich umgeschrieben. Arthorans Tagesplan bleibt
|
||||
für die gezielte Sichtprüfung ausgeschaltet.
|
||||
|
||||
## Prüfungen
|
||||
|
||||
```bash
|
||||
python3 tests/clientless/test_adventure_rest.py
|
||||
python3 tests/clientless/test_adventure_rest_fire.py
|
||||
python3 tests/clientless/test_adventure_social_fire.py
|
||||
python3 tests/clientless/test_adventure_micro_reset.py
|
||||
python3 tests/clientless/test_adventure_intent_state.py
|
||||
python3 tests/clientless/test_adventure_social.py
|
||||
python3 tests/clientless/test_adventure_walk.py
|
||||
```
|
||||
|
||||
Die neue Regression führt die produktiven Auswahl- und Aktualisierungsfunktionen
|
||||
mit kontrollierten Navigationsadaptern aus: geeignete Kategorien, Karte,
|
||||
Fraktion, Abstand und Höhe, bestätigte Ankunft, belegte Plätze, vollständige
|
||||
Ruhedauer nach Anreise, Navigationsfehler, Zeitlimit, Katalogänderung und
|
||||
unterbrochene Haltung. Bestehende Prüfungen decken Sitzbestätigung, Gehmodus,
|
||||
Aufräumen und Intentübergabe ab. Build und technische Tests ersetzen die
|
||||
visuelle Abnahme der neuen Ruheabläufe nicht.
|
||||
|
||||
## Testserverstand am 27.10.2026
|
||||
|
||||
- Debug-Build mit `-j10` erfolgreich, installiert. Alle neun ausgeführten
|
||||
Adventure-/Beobachter-Regressionsskripte erfolgreich.
|
||||
- Frische Worldserver-Sitzung mit `(worldserver-daemon) ready...`, fortlaufendem
|
||||
Prozess und geöffnetem Port 8085 bestätigt.
|
||||
- Goldhain: `INTENT_ARRIVED`, `REST_APPROACH` und `REST_CONFIRMED` für
|
||||
`goldshire_sleep_upstairs` bestätigt. Der lokale Weg führte über die Treppe
|
||||
und zwei Splineabschnitte mit `walk=1`; die tatsächliche Ankunft lag bei
|
||||
`(-9457.200, 32.800, 63.820)`. Angeforderte Schlafdauer: 131 Sekunden.
|
||||
Der nachfolgende Intentwechsel beendete diese Schlafphase vorzeitig.
|
||||
- Sturmwind: `INTENT_ARRIVED` und `rest_seat` bestätigt. Native Steinbank
|
||||
Entry 203936, Slotposition `(-8473.900, 847.299, 105.786)`, Slotfehler
|
||||
`0.000`, Sitzhaltung `5`, Bewegungs-GUID `26`. Der lokale Anlauf lief mit
|
||||
`walk=1`. Die Auswahl darf andere passende Bänke in der Nähe des
|
||||
Anlaufpunkts verwenden.
|
||||
- Der Banktest begann nach administrativer Positionierung am Kathedralenplatz;
|
||||
die anschließende Navigation zum Ruheort und die Sitzplatzbenutzung waren
|
||||
regulär. Die Fernreise von Goldhain zu dieser Bank ist nicht als erfolgreich
|
||||
geprüft einzustufen: der bestehende Graph plante einen weiten Umweg über
|
||||
Eisenschmiede (16 Schritte zum Hafenanker); der Versuch wurde beendet.
|
||||
Bei einer zwischenzeitlichen Rückreise traten außerdem vorhandene
|
||||
Navigationsfehler mit `_checkPathLengths()` auf. Diese Reiseprobleme wurden
|
||||
im Rahmen der Ruhe-Erweiterung nicht verändert.
|
||||
- Für den isolierten Banktest wurde der Startauftrag im Profil kurzzeitig
|
||||
angepasst und nach bestätigtem Login wieder vollständig zurückgesetzt.
|
||||
Arthoran bleibt zur Sichtprüfung im laufenden Ruhe-Intent in Sturmwind;
|
||||
sein Tagesplan ist aus. Das unveränderte Profil startet nach erneutem Login
|
||||
weiterhin den bisherigen Sozialauftrag in Goldhain.
|
||||
|
||||
Offen bleiben die visuelle Abnahme der neuen Schlafdarstellung und des
|
||||
Ruheablaufs sowie eine reguläre Fernreise bis zum Stadtbank-Ruheort.
|
||||
Bodenrast ist automatisiert geprüft, hat aber noch keinen eigenen
|
||||
Live-Testpunkt. Weitere Ruheorte können über den bestehenden Ortskatalog
|
||||
ergänzt werden.
|
||||
|
||||
Fortschreibung: Der Nutzer hat den lokalen Anlauf zur Stadtbank, Absteigen
|
||||
und Hinsetzen visuell bestätigt. Für die anschließende Schlafvorführung in
|
||||
Sturmwind wurde `gilded_rose_sleep_upstairs` im Obergeschoss der Taverne
|
||||
`the_gilded_rose` ergänzt. Die markierte Bodenposition verwendet die native
|
||||
Schlafhaltung; automatische Bettbenutzung ist weiterhin nicht implementiert.
|
||||
|
||||
## Feuerrast-Ergänzung am 27.10.2026
|
||||
|
||||
`rest_fire` ist im Testkatalog aktiv (34 Aktionen insgesamt). Die additive
|
||||
Migration wurde angewendet; vorhandene Feueraktionen für Geselligkeit und
|
||||
Abenteuer blieben unverändert. Alle 22 Clientless-Regressionsskripte und der
|
||||
Debug-Build mit `-j10` bestanden. Die Binärdateien sind installiert; der frische
|
||||
Start erreichte `ready...`, Prozess und Port 8085 wurden bestätigt.
|
||||
|
||||
Arthoran wurde mit seinem Ruheauftrag in der Gilded Rose wieder eingeloggt.
|
||||
Sein Profil wurde nur für diesen Login temporär angepasst und anschließend
|
||||
bytegenau zurückgesetzt. `INTENT_ARRIVED` und natives Sitzen sind erneut
|
||||
bestätigt. Der gezielte Aufruf `micro 26 rest_fire` wurde dort mangels eines
|
||||
geeigneten erkannten Feuers abgelehnt; die laufende Sitzszene blieb erhalten.
|
||||
Damit ist die Laufzeitsperre an diesem Innenraum geprüft, nicht eine erfolgreiche
|
||||
Feuerrast. Feuererzeugung und vorhandene Feuer sind mit kontrollierten Adaptern
|
||||
getestet; eine positive Sichtprüfung der Feuerrast und der verschobene visuelle
|
||||
Schlaftest bleiben offen. Im aktuellen Testkatalog gibt es noch keine aktivierten
|
||||
`rest_ground`-Locations; neue Plätze müssen vor Freigabe räumlich geprüft werden.
|
||||
|
||||
|
||||
Die ergänzte Gebäudesperre/Stadtsperre ist ebenfalls gebaut (`-j10`) und
|
||||
installiert. Die drei betroffenen Feuer-/Szenen-Regressionsskripte bestanden,
|
||||
einschließlich unmarkierter Stadtviertel mit Stadt-Parent, getrennter Zone,
|
||||
Handelskanal-Kennzeichen, fehlender Gebietsdaten und weiterhin nutzbarer
|
||||
vorhandener Feuer. Die geladenen enUS-AreaTable-Daten bestätigen die
|
||||
Stadtkennzeichen unter anderem für Sturmwind und deren Vererbung an das
|
||||
selbst unmarkierte Untergebiet 1617. Der Testserver erreichte erneut `ready...`;
|
||||
Prozess und Port 8085 wurden geprüft. Arthoran ist wieder im Ruhe-Intent in
|
||||
der Gilded Rose, sein temporär angepasstes Startprofil ist zurückgesetzt.
|
||||
|
||||
## Schlafvorführung am 27.10.2026
|
||||
|
||||
Auf ausdrücklichen Nutzerwunsch wurde die Schlafprüfung wieder aufgenommen.
|
||||
Arthoran reiste regulär von Elwynn zur Gilded Rose. Der alte Schlafmarker lag
|
||||
1,72 Yards vom nativen MMAP-Endpunkt entfernt und wurde deshalb von der strengen
|
||||
lokalen Ankunftsprüfung zurückgewiesen. Die native Navigation erreichte über
|
||||
die Treppe (-8865.066, 684.800, 105.517); der Marker wurde gezielt dorthin
|
||||
korrigiert (Migration `_06`, auf Test-DB bereits ausgeführt). Keine Lockerung
|
||||
der Ankunftsprüfung, kein Teleport. Der kurz verwendete Lua-Testoverride wurde
|
||||
bytegleich wiederhergestellt.
|
||||
|
||||
`REST_CONFIRMED guid=26 point='gilded_rose_sleep_upstairs' posture='sleep'
|
||||
durationMs=168000` bestätigt die gestartete native Schlafhaltung. Die sichtbare
|
||||
Abnahme durch den Nutzer steht noch aus. Der Ruheauftrag gilt für diesen
|
||||
Testlauf; das normale Lua-Profil blieb unverändert.
|
||||
|
||||
|
||||
## Flächensuche statt ungeprüfter Schlafposition
|
||||
|
||||
Die Sichtprüfung vom 27.10.2026 zeigte Arthoran mitten im oberen Stuhl.
|
||||
`REST_CONFIRMED` belegte zuvor nur Navigation und Haltung, keine freie Liegefläche.
|
||||
Die Migration `_06` wird deshalb nicht weiter als räumlich abgenommener Platz
|
||||
betrachtet. Ihr Punkt dient jetzt als Suchanker; vorhandene Koordinaten bleiben erhalten.
|
||||
|
||||
Schlaf sucht bis acht Yards um einen geeigneten `rest_sleep`-Anker; ohne nutzbaren
|
||||
Schlafanker dürfen freigegebene Tavernen als Suchanker dienen. Explizite
|
||||
Schlafanker haben Vorrang. Die Suche bleibt innerhalb von 1,5 Yards zur
|
||||
Ankerhöhe und im Innenraum. Sie ersetzt keine Anreise und teleportiert nicht.
|
||||
|
||||
Reihenfolge innerhalb der Suche:
|
||||
|
||||
1. Phasenrichtige, gespawnte native Bettobjekte, deren Name ein vollständiges
|
||||
Bett-/Bedroll-/Bunk-/Cot-Wort enthält. Ein eigener nativer Betttyp existiert
|
||||
nicht; auch Betten vom Typ Chair werden nicht als Stuhl benutzt.
|
||||
2. Geometrisch mögliche erhöhte Liegeflächen mit abrupten Kanten auf beiden
|
||||
Seiten (mindestens 0,35 Yards Abfall auf 0,15 Yards Strecke, höchstens ein
|
||||
Yard Höhendifferenz). Das ist eine Heuristik, keine sichere Bettklassifikation;
|
||||
ein passender Tisch kann geometrisch gleich aussehen.
|
||||
3. Ein freier ebener Bodenplatz, auch in Gasthäusern ohne Bett.
|
||||
|
||||
Für jede Ausrichtung wird eine modellgrößenabhängige Körperfläche geprüft:
|
||||
mindestens 3,2 × 1,3 Yards, größere Charaktermodelle entsprechend größer.
|
||||
45 Stützstellen müssen eine gemeinsame ebene, trockene Fläche ergeben
|
||||
(maximal 0,18 Yards Abweichung). Native VMAP-/dynamische Sichtlinien auf
|
||||
mehreren Körperhöhen und senkrechte Abfragen prüfen Möbel, Wände und niedrige
|
||||
Überbauten. Native Stühle werden zusätzlich mit Sicherheitsabstand ausgeschlossen,
|
||||
auch wenn ihr Modell keine nutzbare Kollision besitzt. Andere Spieler und
|
||||
Kreaturen dürfen die Körperfläche nicht belegen. Dekoration ohne Kollisionsdaten
|
||||
und ohne eigene erkennbare Objektkennung bleibt technisch nicht sicher erfassbar.
|
||||
|
||||
Der gewählte Platz und seine Ausrichtung werden getrennt vom Suchanker in der
|
||||
Szene gespeichert. MMAP muss ihn vollständig und unverdächtig erreichen;
|
||||
maximale Endpunktabweichung 0,3 Yards, tatsächliche Ankunft höchstens 0,35 Yards.
|
||||
Ein Pfad auf dem Boden unter einer Bettfläche gilt damit nicht als Bettankunft.
|
||||
Die Flächenprüfung wiederholt sich unmittelbar vor der Schlafhaltung und alle
|
||||
zwei Sekunden während des Schlafens. Änderungen beenden die Szene über das
|
||||
vorhandene Aufräumen. Bodenrast (`rest_ground`) behält ihr bisheriges Verhalten.
|
||||
|
||||
Neue Regressionen: `test_adventure_rest_space.py` (produktive Flächen-/Kantenregeln),
|
||||
`test_adventure_rest_targets.py` (produktive native Objektauswahl und Suchadapter).
|
||||
`test_adventure_rest.py` prüft zusätzlich den vom Anker abweichenden Zielpunkt,
|
||||
die erneute Flächenprüfung und den Abbruch bei nachträglicher Belegung.
|
||||
|
||||
|
||||
Liveprüfung des Flächenausbaus am 27.10.2026:
|
||||
- Debug-Build (`-j10`) erfolgreich, sauber gestoppt, installiert und neu gestartet.
|
||||
Frische Ready-Meldung nach elf Sekunden, Prozess 31446 und Port 8085 bestätigt.
|
||||
- Alle 38 zunächst vorhandenen/ergänzten Testskripte bestanden; der danach
|
||||
ergänzte native Zieladaptertest ebenfalls, insgesamt 39. Die anschließend
|
||||
erweiterten Ruhe-, Flächen- und Zieladaptertests erneut erfolgreich.
|
||||
- Arthoran erreichte den oberen Suchanker regulär. Suche: `beds=0 raised=0 floor=18`.
|
||||
Gewählt wurde `(-8868.534, 682.800, 104.949)`, Ausrichtung 3,740.
|
||||
Native Geh-Anreise über 4,03 Yards, Endpunktfehler 0,00, danach
|
||||
`REST_CONFIRMED` mit 243 Sekunden Schlafdauer. Kein Teleport/Objektbenutzen.
|
||||
- Source- und installierte Profilkopie entsprechen wieder dem unveränderten
|
||||
Normalprofil (SHA256 `26b11c3108e6ecc5dbc59d1852b4103ca4e818148603a34c02a470c969dc659b`).
|
||||
- Bett-/erhöhte-Flächen-Präferenz ist durch produktive Adapterfixtures geprüft,
|
||||
noch nicht positiv live an einem realen Bett. Sichtprüfung des neuen
|
||||
Bodenplatzes durch den Nutzer bleibt offen. Keine neue DB-Migration nötig.
|
||||
|
||||
|
||||
Erneute Suche auf Nutzerwunsch bei Allitester: separater Testanker
|
||||
`gilded_rose_sleep_room_test`, (-8877.360, 673.489, 104.950), O=0,649831.
|
||||
Arthoran erreichte den Punkt nach frischem Laden des Reisepunkt-Caches regulär.
|
||||
Auch hier `beds=0 raised=0`, zuletzt `floor=46`; Schlafhaltung am Boden bestätigt
|
||||
(143 Sekunden). Die sichtbaren Zimmerbetten sind damit weiterhin nicht erkannt;
|
||||
der genaue geometrische Ablehnungsgrund wurde noch nicht instrumentiert.
|
||||
Der ältere Anker wurde für die gezielte Auswahl kurz ausgeblendet und danach
|
||||
vollständig wieder aktiviert. Normalprofil unverändert wiederhergestellt.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Rut’theran / Darnassus: Graphkorrektur vom 26.10.2026
|
||||
|
||||
`taxi_585` wurde auf GM-Anweisung ausschließlich im CPC-TravelGraph und dessen
|
||||
Weltpunkttabelle deaktiviert. Der Punkt bei (8334.76, 1029.83, 22.79) ist kein
|
||||
regulärer Spieler-Flugpunkt. Es waren keine Kanten mit diesem Node verbunden.
|
||||
Native Taxi-/NPC-Definitionen bleiben erhalten. Die explizite Testmigration
|
||||
steht in `sql/custom/world/2026_10_26_00_clientless_disable_taxi_585.sql`.
|
||||
|
||||
Der Taxi-Importer behält bestehende `enabled=0`-Flags und deren Kommentare bei,
|
||||
anstatt sie bei jedem Neuimport zu aktivieren. Neue Taxi-Datensätze werden wie
|
||||
bisher aktiviert angelegt. Ein SQL-Regressionstest führt die tatsächlichen
|
||||
UPDATE-Anweisungen mit aktiven und deaktivierten Datensätzen aus:
|
||||
`python3 tests/clientless/test_taxi_import_disabled.py`.
|
||||
|
||||
## Fehlende Portale
|
||||
|
||||
Der frühere Portalimport übersprang gleichkartige Übergänge, und der Executor
|
||||
lehnte sie ausdrücklich ab. Rut’theran und Darnassus liegen beide auf Karte 1.
|
||||
Die allgemeine Clientless-Near-Teleport-Bestätigung ist seit der
|
||||
Transportintegration vorhanden und wird jetzt auch vom Portal-Executor benutzt.
|
||||
Portalreisen durchlaufen weiterhin den normalen AreaTrigger-Handler mit dessen
|
||||
Zugangsprüfungen. Vor Fortsetzung muss der Teleport abgeschlossen sein und die
|
||||
Position höchstens fünf Yards vom tatsächlichen Ziel entfernt liegen. Dadurch
|
||||
kann ein verweigerter gleichkartiger Teleport nicht als Erfolg gelten.
|
||||
|
||||
`.clientless portal import <triggerId>` erlaubt nun einen gezielten Import,
|
||||
einschließlich gleichkartiger Portale. Der bisherige Bulk-Import ohne Argument
|
||||
behält seinen Umfang (Kartenwechsel) bei. `portal import` und `portal info` sind
|
||||
mit denselben GM-Rechten auch über die Konsole nutzbar.
|
||||
|
||||
Aus den installierten DBC-/DB-Daten abgeleitete Nodes, alle auf Karte 1:
|
||||
|
||||
| Ort | Node | X | Y | Z |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Rut’theran, nach Darnassus | portal_at_542_source | 8393.800 | 1003.900 | 30.191 |
|
||||
| Darnassus, Ankunft | portal_at_542_target | 9946.250 | 2612.970 | 1316.490 |
|
||||
| Darnassus, nach Rut’theran | portal_at_527_source | 9947.480 | 2630.040 | 1318.600 |
|
||||
| Rut’theran, Ankunft | portal_at_527_target | 8380.560 | 998.536 | 29.129 |
|
||||
|
||||
Gerichtete Portalkanten: 542_source → 542_target (ID 1747) und
|
||||
527_source → 527_target (ID 1746), Kosten jeweils 1. Groundanschlüsse werden
|
||||
separat aufgezeichnet oder vom Planner vollständig per MMAP validiert.
|
||||
|
||||
## Verifikation
|
||||
|
||||
Build, Installation und Regressionstests bestanden. Echter Live-Test mit
|
||||
Arthoran: Trigger 542 um 10:26:22, Trigger 527 um 10:27:17, jeweils
|
||||
`EDGE_COMPLETE`, `arrivalError=0.00`, Recovery 0. Die Rückfahrt nutzte zunächst
|
||||
eine validierte MMAP-Brücke von `portal_at_542_target` zum 17,24 Yards entfernten
|
||||
`portal_at_527_source`; danach wurde der reguläre AreaTrigger ausgeführt.
|
||||
|
||||
`tests/clientless/test_portal_transfer.py` prüft den tatsächlichen
|
||||
Handler-/ACK-/Zielprüfungsblock mit Core-Doubles: Near und Far, abgewiesener
|
||||
Same-Map-Teleport, fehlender ACK-Abschluss und falscher Sessiontyp.
|
||||
Die existierenden Transport- und Lua-Reload-Regressionstests bestanden ebenfalls.
|
||||
|
||||
Ausgangsdaten, neu erzeugte Portalnodes und vorheriges Arthoran-Lua liegen unter
|
||||
`/tmp/vcore-ruttheran-fix.yxm90j91`. Ein laufender GM-Aufnahmebuffer wurde vor
|
||||
dem Neustart ausdrücklich als gespeichert bestätigt und im Log nachgewiesen.
|
||||
|
||||
Die abschließend installierte Build-ID ist
|
||||
`f2873b12546ada19e68aa3b6b0d8e7823fe816e5` (einschließlich korrigierter
|
||||
`portal info`-Anzeige). Ready-Meldung, laufender Prozess 42675 und Port 8085
|
||||
wurden nach dem finalen Start geprüft. Arthoran wurde nach beiden Tests sauber
|
||||
ausgeloggt; das vorherige Lua-Skript ist wiederhergestellt.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,101 @@
|
||||
# Vom Bulk-Import übersprungene gleichkartige Portalübergänge
|
||||
|
||||
Historische Bestandsaufnahme vom 26.10.2026 vor dem Magierturm-Import, ausschließlich lesender Abgleich der lokalen Testdatenbank mit den installierten AreaTrigger-/Map-DBC-Dateien.
|
||||
|
||||
Nachtrag: 702/704 und 6321/6322 sind inzwischen importiert und als Portalübergänge live getestet. Damit bleiben 54 der hier ursprünglich fehlenden 58 Übergänge unimportiert; das bedeutet keine geplante Freigabe dieser restlichen Übergänge. Die aktuelle Auswahl steht in [portal-selection.md](portal-selection.md), die Ödland-Tests in [badlands-dock-portals.md](badlands-dock-portals.md). Der noch fehlende Stadtanschluss ist in [stormwind-mage-tower.md](stormwind-mage-tower.md) dokumentiert. Die folgende Tabelle und die JSON-Datei zeigen weiterhin den Vorherstand.
|
||||
|
||||
Teleportdefinitionen: 316; davon gleichkartig: 60, kartenwechselnd: 256, ohne passenden DBC-Trigger: 0.
|
||||
|
||||
Aktuell vollständig aktiv im Graph: 2 gleichkartige Übergänge. Der Bulk-Importer überspringt sie weiterhin; gezielter Import ist möglich. Keine Daten wurden verändert.
|
||||
|
||||
## Einordnung der 58 zusätzlich fehlenden Übergänge
|
||||
|
||||
Alle 58 fehlen sowohl als Source-Node und Target-Node als auch als Portal-Kante: insgesamt 116 fehlende Nodes und 58 fehlende gerichtete Kanten. Die bereits ergänzten Trigger 527 und 542 sind vollständig aktiv.
|
||||
|
||||
| Gruppe nach DB-Bezeichnung/Kartentyp | Trigger | Anzahl |
|
||||
| --- | --- | --- |
|
||||
| Sturmwind, Magierturm | 702, 704 | 2 |
|
||||
| Immersangwald, Duskwither-Teleporter | 4233, 4267 | 2 |
|
||||
| Dalaran, Brunnen | 5273 | 1 |
|
||||
| Acherus/Ebon Hold, interne Ebenenübergänge | 5127–5138 | 12 |
|
||||
| Hyjal/Feuerlande, Outdoor-Übergänge | 5879, 5880, 5893, 5895, 5931, 5937 | 6 |
|
||||
| Ödland, Klippen-/Anlegerübergänge | 6321, 6322 | 2 |
|
||||
| Tausend Nadeln, Test of Faith | 943 | 1 |
|
||||
| Scherbenwelt, Invasion Point | 4561, 4562 | 2 |
|
||||
| Hyjal-Schlachtzug, Basisübergänge | 4311–4313 | 3 |
|
||||
| Hallen der Reflexion, Türübergang | 5740 | 1 |
|
||||
| Verlorene Inseln, Volcanoth/Phase 8+ | 5926 | 1 |
|
||||
| Arena-Start-/Umsetzungstrigger auf fünf Arenakarten | siehe vollständige Liste | 25 |
|
||||
|
||||
Diese Gruppen sind eine Einordnung anhand der gespeicherten Namen und nativen Kartentypen. Sie ersetzen keine Prüfung der Quest-, Fraktions-, Phasen- und Instanzbedingungen. Insbesondere Arena-Starttrigger sind keine frei nutzbaren überregionalen Reisekanten.
|
||||
|
||||
Als nächsten gezielten Kandidaten zuerst **702/704 in Sturmwind** prüfen, danach nach Bedarf Duskwither und den Dalaran-Brunnen. Den übrigen Bestand erst nach Prüfung seiner tatsächlichen Spielmechanik und Zugänglichkeit ergänzen. Es wurde nichts importiert, aktiviert oder am laufenden Server geändert.
|
||||
|
||||
## Vollständiger Bestand der 60 gleichkartigen Übergänge
|
||||
|
||||
| Trigger | Name laut DB | Karte | Graphstatus | Source X/Y/Z | Target X/Y/Z |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 527 | Darnassus Exit Target | 1 – Kalimdor | aktiv | 9947.48 / 2630.04 / 1318.60 | 8380.56 / 998.54 / 29.13 |
|
||||
| 542 | Darnassus Entrance Target | 1 – Kalimdor | aktiv | 8393.80 / 1003.90 / 30.19 | 9946.25 / 2612.97 / 1316.49 |
|
||||
| 702 | Stormwind - Mage Exit Target | 0 – Eastern Kingdoms | fehlt/unvollständig | -9020.67 / 890.10 / 34.00 | -9014.94 / 873.33 / 148.62 |
|
||||
| 704 | Stormwind - Mage Entrance Target | 0 – Eastern Kingdoms | fehlt/unvollständig | -9017.37 / 877.30 / 152.00 | -9016.97 / 885.44 / 29.62 |
|
||||
| 943 | Thousand Needles - Test of Faith (Target) | 1 – Kalimdor | fehlt/unvollständig | -4950.74 / -1595.14 / -3.02 | -5191.27 / -2802.59 / -7.21 |
|
||||
| 4233 | Eversong Woods - Duskwither UP Target | 530 – Outland | fehlt/unvollständig | 9336.22 / -7883.46 / 74.91 | 9331.49 / -7812.27 / 136.57 |
|
||||
| 4267 | Eversong Woods - Duskwither DOWN Target | 530 – Outland | fehlt/unvollständig | 9285.97 / -7916.01 / 176.13 | 9334.03 / -7880.02 / 74.91 |
|
||||
| 4311 | CoT - Hyjal - Human Base - Teleport Target | 534 – The Battle for Mount Hyjal | fehlt/unvollständig | 4162.02 / -4227.07 / 869.18 | 5066.79 / -1791.90 / 1321.65 |
|
||||
| 4312 | CoT - Hyjal - Orc Base - Teleport Target | 534 – The Battle for Mount Hyjal | fehlt/unvollständig | 4284.15 / -4138.85 / 866.81 | 5499.96 / -2756.80 / 1488.96 |
|
||||
| 4313 | CoT - Hyjal - Night Elf Base - Teleport Target | 534 – The Battle for Mount Hyjal | fehlt/unvollständig | 4203.64 / -4103.24 / 878.36 | 5163.02 / -3428.31 / 1627.61 |
|
||||
| 4561 | Invasion Point, Cataclysm (Return Point) | 530 – Outland | fehlt/unvollständig | -2829.78 / 1953.76 / 202.46 | -3278.63 / 2831.31 / 123.01 |
|
||||
| 4562 | Invasion Point, Cataclysm (Return Point) | 530 – Outland | fehlt/unvollständig | -2745.24 / 2730.42 / 127.78 | -3278.63 / 2831.31 / 123.01 |
|
||||
| 4917 | Arena - Nagrand - Teleport Target - Game On | 559 – Nagrand Arena | fehlt/unvollständig | 4054.15 / 2923.70 / -40.00 | 4054.57 / 2923.23 / 13.82 |
|
||||
| 4919 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6188.01 / 320.00 / 20.00 | 6238.89 / 264.15 / 0.89 |
|
||||
| 4921 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6288.22 / 210.00 / 20.00 | 6238.89 / 264.15 / 0.89 |
|
||||
| 4922 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6214.87 / 200.26 / 20.00 | 6238.89 / 264.15 / 0.89 |
|
||||
| 4923 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6187.77 / 196.88 / 20.00 | 6238.89 / 264.15 / 0.89 |
|
||||
| 4924 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6264.76 / 329.75 / 3.41 | 6238.89 / 264.15 / 0.89 |
|
||||
| 4925 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6290.77 / 333.41 / 20.00 | 6238.89 / 264.15 / 0.89 |
|
||||
| 4927 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1200.33 / 1682.09 / 33.08 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4928 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1223.61 / 1630.81 / 32.61 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4929 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1359.18 / 1692.25 / 37.07 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4930 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1371.51 / 1649.08 / 34.51 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4931 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1299.76 / 1554.74 / 40.00 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4932 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1274.51 / 1774.68 / 27.04 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4933 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1246.06 / 1743.62 / 40.00 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4934 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1305.44 / 1754.14 / 40.00 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4935 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1321.62 / 1586.98 / 40.00 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4936 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1269.12 / 1579.99 / 40.00 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4941 | Arena - Undercity - Teleport Target - Game On | 572 – Ruins of Lordaeron | fehlt/unvollständig | 1285.36 / 1667.68 / 10.00 | 1286.57 / 1667.40 / 39.60 |
|
||||
| 4944 | Arena - Bladesedge - Teleport Target - Game On | 562 – Blade's Edge Arena | fehlt/unvollständig | 6237.84 / 261.36 / -20.00 | 6238.89 / 264.15 / 0.89 |
|
||||
| 5127 | Ebon Hold (E.K.) Top Return Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2479.34 / -5495.73 / 421.84 | 2462.76 / -5598.19 / 550.22 |
|
||||
| 5128 | Ebon Hold (E.K.) Top West Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2469.29 / -5545.84 / 546.10 | 2472.67 / -5530.10 / 420.64 |
|
||||
| 5129 | Ebon Hold (E.K.) Top Return Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2362.55 / -5574.54 / 421.84 | 2462.76 / -5598.19 / 550.22 |
|
||||
| 5130 | Ebon Hold (E.K.) Top South Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2412.68 / -5584.65 / 546.10 | 2397.37 / -5581.06 / 420.64 |
|
||||
| 5131 | Ebon Hold (E.K.) Top Return Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2558.37 / -5612.56 / 421.83 | 2462.76 / -5598.19 / 550.22 |
|
||||
| 5132 | Ebon Hold (E.K.) Top North Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2508.14 / -5602.50 / 546.10 | 2522.45 / -5605.70 / 420.64 |
|
||||
| 5133 | Ebon Hold (E.K.) Top Return Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2441.37 / -5691.42 / 421.83 | 2462.76 / -5598.19 / 550.22 |
|
||||
| 5134 | Ebon Hold (E.K.) Top East Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2451.50 / -5641.27 / 546.10 | 2448.02 / -5655.82 / 420.64 |
|
||||
| 5135 | Ebon Hold (E.K.) Middle -> Bottom Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2427.67 / -5548.64 / 542.09 | 2435.77 / -5610.34 / 366.82 |
|
||||
| 5136 | Ebon Hold (E.K.) Middle -> Bottom Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2505.39 / -5563.90 / 542.09 | 2435.77 / -5610.34 / 366.82 |
|
||||
| 5137 | Ebon Hold (E.K.) Bottom -> Middle Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2419.03 / -5622.17 / 542.07 | 2472.90 / -5530.64 / 420.64 |
|
||||
| 5138 | Ebon Hold (E.K.) Bottom -> Ground Target | 0 – Eastern Kingdoms | fehlt/unvollständig | 2486.99 / -5636.42 / 542.14 | 2415.16 / -5733.04 / 153.92 |
|
||||
| 5273 | Dalaran Well teleporter | 571 – Northrend | fehlt/unvollständig | 5886.27 / 651.45 / 640.00 | 5878.56 / 666.42 / 615.29 |
|
||||
| 5326 | Arena - Dalaran Arena - Teleport Target | 617 – Dalaran Sewers | fehlt/unvollständig | 1330.00 / 800.00 / -10.00 | 1291.57 / 792.97 / 8.11 |
|
||||
| 5328 | Arena - Dalaran Arena - Teleport Target | 617 – Dalaran Sewers | fehlt/unvollständig | 1289.72 / 736.61 / 3.16 | 1291.57 / 792.97 / 8.11 |
|
||||
| 5329 | Arena - Dalaran Arena - Teleport Target | 617 – Dalaran Sewers | fehlt/unvollständig | 1292.05 / 845.27 / 5.63 | 1291.57 / 792.97 / 8.11 |
|
||||
| 5330 | Arena - Dalaran Arena - Teleport Target | 617 – Dalaran Sewers | fehlt/unvollständig | 1238.08 / 780.11 / 3.16 | 1291.57 / 792.97 / 8.11 |
|
||||
| 5331 | Arena - Dalaran Arena - Teleport Target | 617 – Dalaran Sewers | fehlt/unvollständig | 1348.50 / 792.83 / 3.82 | 1291.57 / 792.97 / 8.11 |
|
||||
| 5447 | Arena - Orgrimmar - Teleport Target 3 | 618 – The Ring of Valor | fehlt/unvollständig | 801.66 / -278.86 / -24.00 | 763.37 / -284.29 / 28.28 |
|
||||
| 5740 | Halls of Reflection (The Impenetrable Door) | 668 – Halls of Reflection | fehlt/unvollständig | 5361.10 / 2061.02 / 707.70 | 5354.01 / 2053.53 / 707.70 |
|
||||
| 5879 | Firelands Forgeworks (Exit) | 1 – Kalimdor | fehlt/unvollständig | 5042.17 / -2026.51 / 1148.98 | 5036.41 / -2045.99 / 1368.39 |
|
||||
| 5880 | Firelands Forgeworks (Enterance) | 1 – Kalimdor | fehlt/unvollständig | 5030.84 / -2036.30 / 1378.09 | 5029.45 / -2029.36 / 1148.97 |
|
||||
| 5893 | Hyjal - Teleport from Seat of the Prophets | 1 – Kalimdor | fehlt/unvollständig | 4320.92 / -3288.20 / 1036.05 | 3948.62 / -2818.22 / 618.75 |
|
||||
| 5895 | Hyjal - Teleport From Sulfuron Spire | 1 – Kalimdor | fehlt/unvollständig | 3943.90 / -2807.49 / 618.75 | 4316.05 / -3282.51 / 1035.53 |
|
||||
| 5926 | The Lost Isles - Volcanoth's Lair - Teleport Target - Phase 8+ | 659 – Lost Isles Volcano Eruption | fehlt/unvollständig | 1429.99 / 1233.86 / 124.60 | 1172.59 / 1094.79 / 119.23 |
|
||||
| 5931 | The Crucible of Flame (Enterance) | 1 – Kalimdor | fehlt/unvollständig | 4664.00 / -3686.81 / 956.63 | 4679.10 / -3675.53 / 696.45 |
|
||||
| 5937 | The Crucible of Flame (Exit) | 1 – Kalimdor | fehlt/unvollständig | 4678.15 / -3682.77 / 696.45 | 4653.99 / -3688.44 / 955.26 |
|
||||
| 6321 | Badlands 4.x - Cliff Teleport Target | 0 – Eastern Kingdoms | fehlt/unvollständig | -6518.68 / -4604.42 / 29.23 | -6547.88 / -4443.24 / 332.08 |
|
||||
| 6322 | Badlands 4.x - Dock Teleport Target | 0 – Eastern Kingdoms | fehlt/unvollständig | -6551.28 / -4446.46 / 332.83 | -6519.82 / -4608.52 / 28.48 |
|
||||
|
||||
Die Namen stammen aus der Teleporttabelle. Sie belegen keine universelle Begehbarkeit oder Freigabe für alle Spieler. Quests, Fraktion, Instanzstatus und Skriptbedingungen müssen vor einem Import geprüft werden.
|
||||
|
||||
Maschinenlesbare Daten einschließlich des vollständigen Node-/Kantenstatus: [same-map-portals.json](same-map-portals.json).
|
||||
@@ -0,0 +1,107 @@
|
||||
# Erste Schiffsverbindung: Sturmwind – Rut’theran
|
||||
|
||||
Auswahl des Nutzers: Schiff ab Sturmwind. Erster Test mit **The Bravery**,
|
||||
Spawn **2**, Entry **176310**. Die Datenbankbeschreibung nennt noch Auberdine;
|
||||
die tatsächlichen nativen Halte liegen bei Sturmwind und südlich des
|
||||
Rut’theran-Teleportziels. Für die Aufnahmen ist der echte Anleger maßgeblich.
|
||||
|
||||
Live über `clientless transport services 2` geprüft:
|
||||
|
||||
| Halt | Karte | Fahrzeugursprung X / Y / Z | Haltezeit |
|
||||
| --- | --- | --- | --- |
|
||||
| Sturmwind | 0 | -8650.719 / 1346.051 / 0.000 | 60 s |
|
||||
| Kalimdor, Anleger bei Rut’theran | 1 | 8162.587 / 1005.365 / 0.000 | 60 s |
|
||||
|
||||
Umlaufzeit: 235782 ms, zwei Halte und zwei native Pfadabschnitte. Diese
|
||||
Koordinaten bezeichnen den Schiffsrumpf-Ursprung, nicht den Groundnode.
|
||||
|
||||
## Aufnahme in Sturmwind
|
||||
|
||||
Am festen Boden unmittelbar vor dem Übergang zum Schiff positionieren:
|
||||
|
||||
```text
|
||||
.clientless node add ship_sw_br ship
|
||||
.clientless transport near 50
|
||||
```
|
||||
|
||||
Bei frisch angedocktem Schiff Spawn 2 beginnen, normal an Bord zu einem
|
||||
sicheren ebenen Deckplatz laufen und dort speichern:
|
||||
|
||||
```text
|
||||
.clientless transport record start ship_sw_br 2
|
||||
.clientless transport record stop bravery_center
|
||||
```
|
||||
|
||||
## Aufnahme auf Kalimdor
|
||||
|
||||
Mit demselben Schiff mitfahren. Am Ziel aussteigen und direkt vor dem
|
||||
Übergang auf festem Boden den gemeinsamen Haltestellen-Node erstellen:
|
||||
|
||||
```text
|
||||
.clientless node add ship_ruttheran_br ship
|
||||
```
|
||||
|
||||
Während eines vollständigen Halts desselben Schiffs erneut an Bord und zum
|
||||
gleichen lokalen Stehplatz gehen:
|
||||
|
||||
```text
|
||||
.clientless transport record start ship_ruttheran_br 2
|
||||
.clientless transport record stop bravery_center
|
||||
```
|
||||
|
||||
Danach Aufnahmen prüfen und Verbindung anlegen:
|
||||
|
||||
```text
|
||||
.clientless transport stops
|
||||
.clientless transport link ship_sw_br ship_ruttheran_br ship 100 both
|
||||
```
|
||||
|
||||
Der vorläufige Graphkostenwert 100 dient dem isolierten Transporttest. Erst
|
||||
nach funktioneller Abnahme und Kostenkalibrierung konkurrierende Fernrouten
|
||||
bewerten. Die Landanschlüsse zum restlichen Graphen separat aufnehmen;
|
||||
keine zusätzlichen Ein-/Ausgangsnodes für denselben Anleger erstellen.
|
||||
|
||||
## Abnahmekriterien
|
||||
|
||||
Nach zwei kompatiblen echten Übergangsaufnahmen Arthoran an `ship_sw_br`
|
||||
positionieren und `travel_to_node` nach `ship_ruttheran_br` ausführen. Prüfen:
|
||||
Warten, Boarding, Passenger, nativer Kartenwechsel 0→1 mit vollständigem
|
||||
Clientless-ACK, neue Transportkopie bei identischer Spawn-ID, Ausstieg,
|
||||
Landnode erreicht. Danach Gegenrichtung sowie Anschluss an Groundroute.
|
||||
|
||||
Die generische Typ-15-Unterstützung und der zusätzliche Regressionstest für
|
||||
den Kartenwechsel sind vorhanden. Stand der echten Schiffsfahrten siehe
|
||||
Live-Prüfung unten. Danach folgt der Zeppelin; Fahrstühle sind zurückgestellt.
|
||||
|
||||
## Live-Prüfung am 26.10.2026
|
||||
|
||||
Beide Übergänge wurden durch den GM aufgenommen und geladen:
|
||||
|
||||
- `ship_sw_br`: 11 Punkte, 17,72 Yards, Karte 0.
|
||||
- `ship_ruttheran_br`: 4 Punkte, 7,76 Yards, Karte 1. Node-Typ bei Anlage
|
||||
`ground`; der Executor verwendet den Fahrtkantentyp `ship`.
|
||||
- Beide Spawn 2, Entry 176310 und Stand `bravery_center`.
|
||||
|
||||
Die native Kompatibilitätsprüfung bestand; bidirektionale Kante 1743 wurde
|
||||
angelegt. Hinfahrt ohne Recovery: Waiting 09:15:04, Boarding 09:16:26,
|
||||
Riding/Passenger 09:16:31, Leaving 09:18:23, Arrived auf Land 09:18:25.
|
||||
Die nächste Planung begann nachweislich auf Karte 1.
|
||||
|
||||
Rückfahrt wurde ohne Logout per `.clientless luareload 26` um 09:32:29
|
||||
gestartet. Der Planer wählte Kante 1743 mit `reverse=1`. Boarding 09:34:06,
|
||||
Riding/Passenger 09:34:07, Leaving 09:36:05, Arrived auf Land in Sturmwind
|
||||
09:36:08. Auch die Rückfahrt wurde ohne Recovery abgeschlossen. Beide
|
||||
Richtungen nutzten die normalen Schiffs- und Passenger-Mechaniken inklusive
|
||||
Kartenwechsel. Es wurden während der Reisen keine Charakterpositionen als
|
||||
Test-Abkürzung manipuliert.
|
||||
|
||||
Worldserver-PID 37385 blieb während beider Fahrten unverändert. Arthoran
|
||||
blieb nach Abschluss online am Sturmwind-Anleger. Das Hinreise-Lua wurde
|
||||
auf der Festplatte wiederhergestellt, ohne eine weitere Aktion auszuführen.
|
||||
Die separat vom GM aufgezeichneten Land-/Portalanschlüsse Richtung Darnassus
|
||||
sind noch nicht Bestandteil dieses isolierten Seestrecken-Tests.
|
||||
|
||||
Ausgangsposition und vorheriges Lua liegen unter
|
||||
`/tmp/vcore-ship-ride.voj3k_8t`. Vorwärts-Lua ebenfalls dort gesichert.
|
||||
Der Nutzer untersagte für diese Testphase Shutdown und Neustart bis zu einer
|
||||
ausdrücklichen Freigabe; der laufende Server wurde durchgehend beibehalten.
|
||||
@@ -0,0 +1,92 @@
|
||||
# Sturmwind: Magierturm-Übergänge 702/704
|
||||
|
||||
Stand 26.10.2026. Auf dem lokalen Testserver gezielt importiert: vier aktive
|
||||
Portalnodes und zwei gerichtete Portalkanten. Keine Änderungen an nativen
|
||||
AreaTriggern, Teleportzielen oder interaktiven Rückreiseportalen.
|
||||
|
||||
| Node | Karte | X | Y | Z | Funktion |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| portal_at_702_source | 0 | -9020.670 | 890.104 | 29.6207 | unterer Eingang, Anlaufpunkt |
|
||||
| portal_at_702_target | 0 | -9014.940 | 873.326 | 148.616 | obere Ankunft |
|
||||
| portal_at_704_source | 0 | -9017.370 | 877.299 | 148.616 | oberer Ausgang, Anlaufpunkt |
|
||||
| portal_at_704_target | 0 | -9016.970 | 885.436 | 29.6207 | untere Ankunft |
|
||||
|
||||
Kanten: 1748 (702_source → 702_target) und 1749
|
||||
(704_source → 704_target), jeweils Kosten 1, unidirektional.
|
||||
|
||||
## Warum der reine Import nicht reicht
|
||||
|
||||
Die nativen Trigger sind gedrehte Boxen. Ihr Mittelpunkt liegt über dem Boden:
|
||||
702 bei Z=34 mit Höhe 11, 704 bei Z=152 mit Höhe 8. Der Importer übernimmt
|
||||
diesen Mittelpunkt als Source-Node. MMAP konnte insbesondere den Mittelpunkt
|
||||
von 704 nicht erreichen; der Planer wich auf einen unvollständigen langen
|
||||
Laufweg aus. Der erste Test wurde deshalb gestoppt.
|
||||
|
||||
Nur die Graph-Anlaufhöhen wurden innerhalb der Boxen auf die jeweilige Höhe
|
||||
der gegenüberliegenden nativen Ankunft gesetzt. X/Y und die Zielnodes bleiben
|
||||
unverändert. Die tatsächliche Zugehörigkeit zum Trigger wird weiterhin mit
|
||||
`IsInAreaTriggerRadius` geprüft; anschließend laufen normaler AreaTrigger-
|
||||
Handler, Clientless-ACK und Zielprüfung. Keine künstliche Portalabkürzung.
|
||||
|
||||
Reproduktion im lokalen Testsystem:
|
||||
|
||||
1. Konsole: `clientless portal import 702`, danach `clientless portal import 704`.
|
||||
2. `sql/custom/world/2026_10_26_01_clientless_stormwind_mage_tower.sql` auf die
|
||||
lokale Test-Weltdatenbank anwenden.
|
||||
3. Ingame `.clientless travelreload` oder sauberer Testserver-Neustart.
|
||||
|
||||
**Ein erneuter Portalimport überschreibt die kalibrierten Anlaufhöhen.**
|
||||
Danach die SQL-Kalibrierung erneut anwenden und den Graph neu laden. Der
|
||||
Bulk-Import überspringt gleichkartige Übergänge weiterhin.
|
||||
|
||||
## Live-Verifikation
|
||||
|
||||
Arthoran wurde ausgeloggt und nach Sicherung seiner Ausgangsdaten am nativen
|
||||
oberen Ziel von 702 positioniert. Diese Ausgangsposition simuliert eine
|
||||
Ankunft im oberen Bereich; ein interaktives Rückreiseportal selbst wurde
|
||||
nicht benutzt. Während der folgenden Reisen keine Positionsmanipulation:
|
||||
|
||||
- 11:51:06: oberer Ankunftspunkt → normaler MMAP-Anlauf → Trigger 704 → unten.
|
||||
- 11:51:07: untere Ankunft → normaler MMAP-Anlauf → Trigger 702 → oben.
|
||||
- 11:51:08: erneuter MMAP-Anlauf → Trigger 704 → unten.
|
||||
|
||||
Alle drei Übergänge: `EDGE_COMPLETE`, `arrivalError=0.00`, `recovery=0`.
|
||||
Die Kalibrierungs-SQL wurde anschließend zweimal erfolgreich angewendet;
|
||||
vier aktive Nodes und beide aktiven gerichteten Kanten wurden ausgelesen.
|
||||
|
||||
## Noch fehlender Groundanschluss
|
||||
|
||||
Der anschließende Versuch von unten nach `stormwind_gate_inner` fand keinen
|
||||
durchgängig validierten MMAP-Weg. Nach mehreren Teilanläufen endete er
|
||||
`TRAVEL_PARTIAL`, zuletzt nach einem erneuten Übergang 702. Damit ist die
|
||||
Weiterreise in den bestehenden Stadtgraph **noch nicht erfolgreich getestet**.
|
||||
Es wurden keine erfundenen Groundkanten oder geraden Wege durch Geometrie
|
||||
angelegt. Auch eine einzelne durchgehende Reise von einer beliebigen oberen
|
||||
Rückportal-Ankunft zu einem Stadtziel ist noch nicht abgenommen.
|
||||
|
||||
Nächster Schritt: mit dem GM eine echte Laufroute ab der unteren Ankunft
|
||||
`portal_at_704_target` zu einem bestehenden erreichbaren Stadtnode aufnehmen,
|
||||
zum Beispiel `stormwind_gate_inner`:
|
||||
|
||||
```text
|
||||
.clientless route start portal_at_704_target stormwind_gate_inner
|
||||
```
|
||||
|
||||
Am unteren Zielnode beginnen, den normalen begehbaren Weg bis zum Zielnode
|
||||
laufen und dort `.clientless route stop` ausführen. Der Recorder speichert
|
||||
bidirektional und lädt den Graph neu. Danach Arthoran in einem einzigen
|
||||
Reiseauftrag vom oberen Ankunftsbereich zum Stadtnode und zurück testen.
|
||||
Für den Weg hinein ist zusätzlich der Anschluss an `portal_at_702_source`
|
||||
zu prüfen; eine Aufnahme, die versehentlich durch einen Portaltrigger führt,
|
||||
ist kein durchgehender Groundweg.
|
||||
|
||||
## Abschlusszustand
|
||||
|
||||
Keine Coreänderung, daher kein neuer Build oder Binärinstall erforderlich.
|
||||
Testserver einmal sauber neu gestartet; aktuelle Ready-Meldung, Prozess 44833
|
||||
und Listener 8085 geprüft. Arthoran nach dem Test ausgeloggt, seine vorherige
|
||||
Position und das vorherige Lua-Skript wiederhergestellt.
|
||||
Sicherungen und Testlogs: `/tmp/vcore-mage-test.ntl3z51g`.
|
||||
Die Bestandsaufnahme `same-map-portals.md/json` bleibt als historischer
|
||||
Vorherstand erhalten; mit 702/704 sind nun vier gleichkartige Übergänge aktiv,
|
||||
56 der ursprünglich 58 zusätzlich fehlenden Übergänge bleiben offen.
|
||||
@@ -0,0 +1,78 @@
|
||||
# Allgemeiner Lifecycle animierter GameObject-Transporte
|
||||
|
||||
## Ursache
|
||||
|
||||
Die Tiefenbahn besteht aus sechs `GAMEOBJECT_TYPE_TRANSPORT`-GameObjects
|
||||
(Typ 11). Drei Wagen besitzen ihre Datenbank-Spawnposition in Eisenschmiede,
|
||||
drei in Sturmwind. Diese GameObjects werden beim Erstellen bereits über
|
||||
`setActive(true)` für Aktualisierung und einen Unload-Lock ihres Spawn-Grids
|
||||
registriert. Vorher müssen sie jedoch vom normalen Grid-Loader erzeugt werden.
|
||||
|
||||
Bei ausschließlich in Sturmwind anwesenden Spielern blieb das entfernte
|
||||
Spawn-Grid ungeladen. Der dort startende Zug existierte daher serverseitig noch
|
||||
nicht. Das betrifft Netzwerkspieler ebenso wie clientlose Spieler. Ein Besuch
|
||||
in Eisenschmiede lud die fehlenden Wagen und ließ den Fehler bis zum nächsten
|
||||
Neustart verschwinden.
|
||||
|
||||
## Änderung
|
||||
|
||||
`ObjectMgr::LoadGameObjects` indexiert nach Abschluss der vorhandenen
|
||||
Validierungen reguläre Typ-11-Spawns nach Karte. Ereignisgebundene Spawns
|
||||
bleiben außerhalb dieses Index und behalten die bisherige Ereignisverwaltung.
|
||||
|
||||
`MapManager` ruft nach Initialisierung der Respawn-Daten beziehungsweise der
|
||||
Instanz-/Battleground-Daten `Map::LoadTransportGameObjectGrids` auf. Diese
|
||||
Funktion lädt ausschließlich die Spawn-Grids der indexierten Transporte für die
|
||||
jeweilige Karte und Spawnmaske. Das Laden erfolgt über `EnsureGridLoaded`:
|
||||
vorhandene Pools, Spawn-Gruppen, Respawn- und Phasenmechaniken gelten weiter.
|
||||
Bereits geladene Grids erzeugen keine zusätzlichen Objektinstanzen.
|
||||
|
||||
Die Änderung verwendet keine CPC-, AdventureBot- oder TravelGraph-Komponenten.
|
||||
Die getrennt verwalteten Typ-15-Transporte (Schiffe/Zeppeline) bleiben im
|
||||
vorhandenen Transport-Lifecycle. Es werden keine Transportfahrpläne verändert.
|
||||
|
||||
Im Testdatenbestand liegen zwischen 1 und 47 Typ-11-Spawns pro betroffener
|
||||
Karte, sechs davon auf Karte 369. Benachbarte Wagen teilen sich Spawn-Grids.
|
||||
Durch das frühe Laden werden auch die normalen Inhalte dieser Grids früher
|
||||
erzeugt; ein vollständiges Vorladen sämtlicher Kartengrids erfolgt nicht.
|
||||
|
||||
## Prüfung
|
||||
|
||||
`python3 tests/clientless/test_transport_grid_loading.py` prüft die tatsächlichen
|
||||
neuen Indexierungs- und Ladeblöcke mit deterministischen Core-Doubles:
|
||||
beide Stationen ohne Spieler, wiederholtes Laden, andere Karten,
|
||||
Spawnmasken, entfernte/verschobene Spawns und Ausschluss ereignisgebundener
|
||||
Objekte sowie Typ-15-Transporte.
|
||||
|
||||
Für den entscheidenden Live-Test ist ein frischer Worldserverprozess nötig.
|
||||
Danach darf zunächst ausschließlich die Sturmwindseite betreten werden.
|
||||
Alle sechs Spawns 18802–18807 müssen dort bereits über `transport inspect`
|
||||
auflösbar sein. Zwei zeitlich getrennte Zustandsaufnahmen müssen Bewegung
|
||||
beider Zuggruppen zeigen. Das erstmalige manuelle Betreten der Gegenseite
|
||||
wäre für diesen Test eine unzulässige Vorbedingung, da es den ursprünglichen
|
||||
Fehler verdecken würde.
|
||||
|
||||
## Live-Ergebnis, 26.10.2026
|
||||
|
||||
Build und Installation bestanden, Build-ID
|
||||
`28fa55f1b9604a57da4616b23a195c117d2fcc82`. Neuer Worldserverprozess: PID 36683;
|
||||
Ready-Meldung und Port 8085 geprüft. Vor dem Test war kein GM eingeloggt.
|
||||
Arthoran wurde ausschließlich an `tram_sw` mit einem untätigen Lua-Skript
|
||||
eingeloggt; ein Besuch am anderen Ende entfiel vollständig.
|
||||
|
||||
Die neue Core-Diagnostik meldete für Karte 369 drei geladene Spawn-Grids und
|
||||
sechs Transportkandidaten. Alle sechs Spawns 18802–18807 waren auflösbar.
|
||||
Zwei mindestens 20 Sekunden getrennte Aufnahmen bestätigten für jeden Wagen
|
||||
geänderte Position und Animationsfortschritt. Beide Zuggruppen bewegten sich.
|
||||
Ergebnis und Konsolenausgaben:
|
||||
`/tmp/vcore-tram-ride.1i65g2dm/cold-grid-test-result.json` und
|
||||
`cold-grid-test-console.txt` im selben Verzeichnis. Das vorherige Reise-Lua wurde
|
||||
anschließend wiederhergestellt; Arthoran blieb online und untätig in Sturmwind.
|
||||
Eine visuelle Abnahme durch einen normalen WoW-Client bleibt Aufgabe des GM.
|
||||
|
||||
Separater offener Befund: Beim vorhergehenden Shutdown des noch unveränderten
|
||||
Servers (PID 30922, alter Build) erschien `Object.h:448 in GetMap ASSERTION FAILED:
|
||||
m_currMap`. Der Prozess endete. Diese Assertion trat vor Installation des
|
||||
Grid-Fixes auf; ihre Ursache ist noch nicht festgestellt. Vorherige Logs liegen
|
||||
unter `before-grid-fix-restart` im obigen Testverzeichnis. Die Konsolenmeldung
|
||||
enthielt keinen auswertbaren Stacktrace.
|
||||
@@ -0,0 +1,330 @@
|
||||
# Clientless Transport: Aufnahme und Test
|
||||
|
||||
Die Integration verwendet reguläre Trinity-Transporte (`TransportBase`). Eine
|
||||
Haltestelle hat genau einen TravelGraph-Node für Ein- und Ausstieg. Der Übergang
|
||||
auf das Fahrzeug wird getrennt von den Groundkanten aufgenommen. Es werden
|
||||
keine Schiffe, Aufzüge oder Bahnen teleportiert oder für den Bot angehalten.
|
||||
|
||||
## Datenbank
|
||||
|
||||
Die zusätzliche Migration liegt unter
|
||||
`sql/custom/world/2026_10_25_00_clientless_transport.sql`. Sie wird ausdrücklich
|
||||
auf die Test-Weltdatenbank angewendet. Die drei neuen Tabellen sind:
|
||||
|
||||
- `vcore_clientless_transport_stop`: Haltestelle, Fahrzeug-Entry, Spawn und Dockpose.
|
||||
- `vcore_clientless_transport_point`: geordnete Übergangspunkte mit Welt-/Transportbezug.
|
||||
- `vcore_clientless_transport_stand`: benannte Stehplätze relativ zum Fahrzeugmodell.
|
||||
|
||||
Bestehende Nodes und Groundkanten bleiben erhalten. Neue Fahrtverbindungen
|
||||
werden in `vcore_clientless_travel_edge` gespeichert. Ohne zwei gültige,
|
||||
kompatible Aufnahmen wird eine Transportkante vom Graphen nicht geladen.
|
||||
Ein Reload kopiert keine Änderungen in eine bereits laufende Fahrt hinein.
|
||||
|
||||
## 1. Haltestelle und Fahrzeug bestimmen
|
||||
|
||||
Schiffe und Zeppeline können unabhängig vom Aufenthaltsort des GM über die
|
||||
nativen Routendaten untersucht werden:
|
||||
|
||||
```text
|
||||
.clientless transport services
|
||||
.clientless transport services 7
|
||||
```
|
||||
|
||||
Die Liste zeigt Spawn, Entry, Modellname, Umlaufzeit, Zahl der geplanten Halte
|
||||
und Pfadabschnitte. Mit Spawn-ID werden zusätzlich die tatsächlichen
|
||||
Dockpositionen, Karten, Ankunftszeitpunkte im Umlauf und Haltezeiten ausgegeben.
|
||||
Diese Daten stammen aus den geladenen Transportpfaden, nicht aus möglicherweise
|
||||
veralteten `transports.name`-Beschreibungen. Die Dockposition bezeichnet den
|
||||
Fahrzeugursprung; den Haltestellen-Node weiterhin auf begehbarem festen Boden
|
||||
am tatsächlichen Land-Deck-Übergang aufnehmen. Reine Patrouillen ohne planmäßige
|
||||
Halte sind keine automatisch geeigneten Passagierverbindungen.
|
||||
|
||||
Beide Befehle sind auch ohne eingeloggten Bot in der Konsole verfügbar.
|
||||
Die Spawn-ID bleibt auf beiden Karten dieselbe, obwohl der Core beim
|
||||
Kartenwechsel eine andere Transportkopie verwendet. Diese kopiert der Recorder
|
||||
nicht als zweites Fahrzeug in den Graphen.
|
||||
|
||||
Mit dem GM auf festem Boden direkt vor der gewünschten Einstiegsstelle stehen:
|
||||
|
||||
```text
|
||||
.clientless node add lift_lower elevator
|
||||
.clientless transport near 30
|
||||
```
|
||||
|
||||
Für andere Verkehrsmittel den Nodetyp `tram`, `ship` oder `zeppelin` verwenden.
|
||||
`near` zeigt unter anderem Entry, Spawn-ID, Weltposition, `stopped`, Periode,
|
||||
Fortschritt und verbleibende Haltezeit. Die **Spawn-ID**, nicht die Entry-ID,
|
||||
bindet die Aufnahme an das konkrete Fahrzeug bzw. den konkreten Wagen.
|
||||
|
||||
```text
|
||||
.clientless transport inspect 204666
|
||||
```
|
||||
|
||||
In der Konsole wird ein online befindlicher CPC-Player als Beobachter angegeben:
|
||||
|
||||
```text
|
||||
clientless transport inspect 204666 26
|
||||
clientless transport near 30 26
|
||||
```
|
||||
|
||||
Die vom Transportrecorder verwendeten Node-Koordinaten können auch über die
|
||||
Konsole geprüft werden:
|
||||
|
||||
```text
|
||||
clientless transport node tram_sw
|
||||
clientless transport node tram_if
|
||||
```
|
||||
|
||||
Das Objekt muss auf der Map des Beobachters geladen sein. `remainingPause` wird
|
||||
in Millisekunden ausgegeben; `4294967295` bezeichnet einen Halt ohne bekannte
|
||||
zeitliche Begrenzung. Ein GoState allein wird nicht als Ankunft interpretiert.
|
||||
|
||||
## 2. Geeigneten Stehplatz speichern (optional vorab)
|
||||
|
||||
Normal an Bord gehen, einen sicheren, ebenen Platz wählen und dort stehen:
|
||||
|
||||
```text
|
||||
.clientless transport stand add center
|
||||
.clientless transport stand list
|
||||
```
|
||||
|
||||
Stehplätze sind lokal zum Transportmodell gespeichert und bleiben bei Bewegung
|
||||
und Kartenwechseln an derselben Stelle des Fahrzeugs. Sie können auch während
|
||||
der Fahrt aufgenommen werden. Nicht fliegen oder fallen. Derselbe Name wird
|
||||
nicht still überschrieben. Andere Namen erlauben weitere Standorte.
|
||||
|
||||
```text
|
||||
.clientless transport stand list 4170
|
||||
.clientless transport stand remove 4170 unused_name
|
||||
```
|
||||
|
||||
`list <entry>` und `remove <entry> <name>` sind konsolenfähig. Ein von einer
|
||||
Haltestelle verwendeter Standname kann nicht entfernt werden, bevor deren
|
||||
Aufnahme ausdrücklich entfernt wurde.
|
||||
|
||||
## 3. Land -> Deck aufnehmen
|
||||
|
||||
Wieder am gemeinsamen Haltestellen-Node auf festem Boden stehen. Auf die nächste
|
||||
Ankunft warten, damit ein vollständiges Haltefenster verfügbar ist:
|
||||
|
||||
```text
|
||||
.clientless transport record start lift_lower 204666
|
||||
```
|
||||
|
||||
Nun normal zum Fahrzeug gehen, es betreten und bis zum gewünschten Stehplatz
|
||||
laufen. Die Aufnahme erfolgt automatisch alle 100 ms mit mindestens 0,75 Yards
|
||||
Punktabstand. Der Wechsel vom Land zum Passenger wird automatisch markiert.
|
||||
|
||||
```text
|
||||
.clientless transport record mark
|
||||
.clientless transport record info
|
||||
.clientless transport record stop center
|
||||
```
|
||||
|
||||
`mark` ist optional und erzwingt einen zusätzlichen Punkt. `stop center`
|
||||
speichert den Übergang und legt bei Bedarf den Stand `center` an. Existiert er
|
||||
bereits, muss der GM höchstens 1,5 Yards davon entfernt stehen.
|
||||
|
||||
Die Aufnahme muss während desselben Halts beendet werden. Abfahrt,
|
||||
Transportwechsel, Verlassen des Fahrzeugs nach bereits erfolgtem Einstieg,
|
||||
Positionssprünge über 8 Yards, Flug oder ein Übergang über 60 Yards machen sie
|
||||
ungültig. Vorhandene Aufnahmen werden nicht still überschrieben.
|
||||
|
||||
```text
|
||||
.clientless transport record cancel
|
||||
```
|
||||
|
||||
Bei einem Fehler bleibt die Diagnose über `record info` sichtbar. Erst mit
|
||||
`cancel` verwerfen und beim nächsten Halt neu beginnen. Jeder GM hat einen
|
||||
eigenen Aufnahmebuffer; Logout verwirft nur dessen ungespeicherte Aufnahme.
|
||||
|
||||
## 4. Gegenhaltestelle aufnehmen
|
||||
|
||||
Mit genau demselben Fahrzeug/Wagen zur Gegenhaltestelle fahren. Aussteigen und
|
||||
auf festem Boden den gemeinsamen Node anlegen:
|
||||
|
||||
```text
|
||||
.clientless node add lift_upper elevator
|
||||
```
|
||||
|
||||
Bei einer folgenden Ankunft von diesem Node erneut an Bord zum gleichen lokalen
|
||||
Stand laufen und aufnehmen:
|
||||
|
||||
```text
|
||||
.clientless transport record start lift_upper 204666
|
||||
.clientless transport record stop center
|
||||
.clientless transport stops
|
||||
```
|
||||
|
||||
Die Deck-Endpunkte beider Übergänge dürfen höchstens 3 Yards auseinanderliegen.
|
||||
Damit wird keine unbekannte längere Querung des Decks zwischen zwei verschiedenen
|
||||
Standorten benötigt. Der aufgezeichnete Übergang wird beim Ausstieg umgekehrt.
|
||||
Deshalb einen Weg aufnehmen, der in beiden Laufrichtungen begehbar ist.
|
||||
|
||||
Bei einer Tiefenbahnaufnahme denselben Wagen an beiden Bahnhöfen verwenden.
|
||||
Die sechs Wagen haben Entries 176080..176085 und Spawn-IDs 18802..18807.
|
||||
Die Haltefenster betragen ungefähr 11..14 Sekunden; kurze Rampenwege sind
|
||||
entsprechend wichtig. Ein anderer Wagen ist eine andere Aufnahmeverbindung.
|
||||
|
||||
## 5. Fahrtkante anlegen
|
||||
|
||||
```text
|
||||
.clientless transport link lift_lower lift_upper elevator 100 both
|
||||
```
|
||||
|
||||
Der Kostenwert ist ein positiver **Graphkostenwert**, keine automatisch mit
|
||||
Groundlängen vergleichbare Sekundenzahl. Zum ersten isolierten Funktionstest
|
||||
ist der genaue Wert unkritisch; konkurrierende Fernrouten benötigen später eine
|
||||
gemeinsame Kostenkalibrierung. `both` ist optional und erzeugt eine bidirektionale
|
||||
Kante. Es darf nur verwendet werden, wenn das reale Verkehrsmittel beide
|
||||
Richtungen bedient. Ohne `both` entsteht nur die angegebene Fahrtrichtung.
|
||||
|
||||
Die Kante wird erst nach Prüfung beider Haltestellen angelegt. Gleicher Entry,
|
||||
gleicher Spawn, verschiedene Dockpositionen/Maps und kompatible Stehplätze sind
|
||||
notwendig. Die Typen `tram`/`elevator` gehören zu GameObjects des Typs 11,
|
||||
`ship`/`zeppelin` zu Typ 15.
|
||||
|
||||
Die Haltestellen benötigen wie andere Nodes eine Verbindung zum übrigen Netz:
|
||||
aufgenommene Groundkanten oder zulässige, vollständig geprüfte MMAP-Anschlüsse.
|
||||
|
||||
## 6. Botfahrt testen
|
||||
|
||||
Arthoran zunächst an der Abfahrt positionieren und clientlos einloggen. Das
|
||||
bestehende Login-Lua-Skript kann bereits andere Aufträge starten; für einen
|
||||
isolierten Transporttest dieses Skript vorher entsprechend einstellen, z.B.:
|
||||
|
||||
```lua
|
||||
queue_action("travel_to_node", {
|
||||
node = "lift_upper",
|
||||
hard_destination = true
|
||||
})
|
||||
```
|
||||
|
||||
Alternativ bei einem untätigen CPC-Player über Konsole oder Spielchat:
|
||||
|
||||
```text
|
||||
clientless transport travel 26 lift_upper
|
||||
clientless transport status 26
|
||||
clientless actioninfo 26
|
||||
```
|
||||
|
||||
`travel` hängt einen Auftrag an die reguläre CPC-Aktionswarteschlange an; es
|
||||
unterbricht keine bereits laufende andere Aktion. Die Zustände sind `Waiting`,
|
||||
`Boarding`, `Riding`, `Leaving`, `Arrived`, `Failed`. Während der Mitfahrt wird
|
||||
keine Groundnavigation gestartet. Native Kartenwechsel werden für CPC ohne
|
||||
Client-ACK abgeschlossen. Der nächste Graphschritt beginnt erst nach dem
|
||||
Aussteigen und Erreichen des gemeinsamen Zielnodes auf Land.
|
||||
|
||||
```text
|
||||
clientless transport cancel 26
|
||||
```
|
||||
|
||||
Abbruch auf Land stoppt die Fahrt. An Bord bleibt der Bot Passenger und steigt
|
||||
an einer sicheren aufgezeichneten Haltestelle aus, statt in der Luft oder im
|
||||
Wasser abgehängt zu werden. Ein harter Timeout meldet `Failed` und lässt eine
|
||||
noch vorhandene Passenger-Zuordnung bestehen; die Diagnose bleibt erhalten.
|
||||
|
||||
Alle Transport-Zustandswechsel und Aufnahmefehler stehen in
|
||||
`adventurebot-navigation.log`. `.clientless`-Spielchatbefehle und deren Antworten
|
||||
werden dort ebenfalls protokolliert; Konsolenantworten sind über tmux lesbar.
|
||||
|
||||
## Pflege
|
||||
|
||||
```text
|
||||
.clientless transport reload
|
||||
.clientless transport forget lift_lower
|
||||
```
|
||||
|
||||
`forget` entfernt nur die Übergangsaufnahme. Node, Groundkanten und benannte
|
||||
Stehplätze bleiben bestehen. Nach Verschieben des Nodes dessen Aufnahme neu
|
||||
anlegen. Fahrtkanten mit unvollständigen Daten werden nicht geplant.
|
||||
|
||||
## Verifikation und Grenzen
|
||||
|
||||
Automatisierte Zustands-/Recorder-Tests:
|
||||
|
||||
```text
|
||||
python3 tests/clientless/test_transport.py
|
||||
```
|
||||
|
||||
Diese verwenden die tatsächlichen Produktionsmethoden mit deterministischen
|
||||
Weltobjekt-Doubles. Sie prüfen unter anderem Haltefenster, Koordinatenrahmen,
|
||||
Warteverhalten, Passenger-Zuordnung, Ausstieg und Abbruch/Timeout. Sie beweisen
|
||||
keine Kollisionsfreiheit eines konkreten Decks und keine erfolgreiche Fahrt
|
||||
auf einem realen GameObject.
|
||||
|
||||
Nach dem Tiefenbahntest folgen ein Schiff mit Kartenwechsel und ein Zeppelin;
|
||||
Fahrstühle werden anschließend behandelt. Je Verbindung beide Fahrtrichtungen,
|
||||
verpasste Halte, Ein-/Ausstieg und Fortsetzung einer Groundroute prüfen. Logout/Serverneustart
|
||||
während einer Typ-11-Fahrt ist noch separat zu verifizieren; der bestehende
|
||||
Trinity-Loginpfad stellt vorrangig die Typ-15-Transportzuordnung wieder her.
|
||||
Die Recorder setzen einen normalen GM-Client für die echte Bewegung voraus;
|
||||
sie erzeugen keine synthetischen Deckpfade.
|
||||
|
||||
## Live-Test Sturmwind → Eisenschmiede, 26.10.2026
|
||||
|
||||
Arthoran (GUID 26) fuhr über Kante 1741 von `tram_sw` nach `tram_if` auf
|
||||
Wagen 18803. Navigationlog: Boarding 00:37:34, Riding mit `passenger=1`
|
||||
00:37:35, Leaving 00:38:38, Arrived mit `passenger=0` 00:38:42.
|
||||
Die Konsole meldete anschließend `travel-route-complete`. Das belegt die
|
||||
serverseitige Durchführung einer Richtung; Gegenrichtung und visuelle
|
||||
Ingame-Abnahme sind damit noch nicht bestätigt.
|
||||
|
||||
Vorbedingung/noch offener Fehler: Beim ersten Start ausschließlich an der
|
||||
Sturmwindseite war Spawn 18803 nicht geladen. Seine Datenbank-Spawnposition
|
||||
liegt auf der Eisenschmiedeseite (4.528, 8.435, 7.011). Ein kurzer Diagnose-Login
|
||||
Arthorans an `tram_if` lud das Spawn-Grid; danach war der aktive Wagen auch von
|
||||
Sturmwind aus verfügbar. Für den eigentlichen Fahrtest wurde Arthoran offline
|
||||
wieder an `tram_sw` positioniert. Während der Fahrt wurden keine Positionen per
|
||||
Datenbank oder Teleport verändert. Automatisches Laden des entfernten
|
||||
Transport-Spawn-Grids muss vor autonomem Betrieb ergänzt werden; der erfolgreiche
|
||||
Fahrtest nach manuellem Vorladen behebt diese Einschränkung nicht.
|
||||
|
||||
Testskript und vorherige Charakterposition gesichert unter
|
||||
`/tmp/vcore-tram-ride.1i65g2dm`.
|
||||
|
||||
Nachtrag: Der oben beschriebene Spawn-Grid-Fehler wurde anschließend im
|
||||
allgemeinen Map-Lifecycle behoben und mit einem frischen Prozess ausschließlich
|
||||
von Sturmwind aus geprüft. Alle sechs Wagen waren verfügbar und bewegten sich.
|
||||
Details und verbleibende Befunde: [transport-grid-lifecycle.md](transport-grid-lifecycle.md).
|
||||
|
||||
## Nächste Verbindungen: Schiff und Zeppelin
|
||||
|
||||
Aktuelle Nutzerauswahl: zuerst **Schiff ab Sturmwind**. Die konkrete Aufnahme
|
||||
für Spawn 2 und der Testablauf stehen in
|
||||
[ship-stormwind-ruttheran.md](ship-stormwind-ruttheran.md).
|
||||
|
||||
Geeignete erste Kandidaten aus der Testdatenbank:
|
||||
|
||||
- Spawn 7, Entry 20808, `The Maiden's Fancy`: Küstenschiff; tatsächliche Häfen
|
||||
über `services 7` prüfen. Der Kartenwechsel zwischen Kalimdor und den östlichen
|
||||
Königreichen prüft die Passenger-Übergabe zwischen Transportkopien.
|
||||
- Spawn 20, Entry 190549, `The Zephyr`: Zeppelin auf Kalimdor. Die vorhandene
|
||||
Transport-/SmartAI bleibt erhalten. Die Fahrt ergänzt den Lufttransport-Test
|
||||
ohne Kartenwechsel.
|
||||
|
||||
Die Recorder- und Link-Befehle bleiben dieselben. Beispiele mit nach Prüfung
|
||||
der Anlegestellen manuell aufgenommenen Nodes:
|
||||
|
||||
```text
|
||||
.clientless node add ship_ratchet ship
|
||||
.clientless transport record start ship_ratchet 7
|
||||
.clientless transport record stop maiden_center
|
||||
|
||||
.clientless node add ship_booty_bay ship
|
||||
.clientless transport record start ship_booty_bay 7
|
||||
.clientless transport record stop maiden_center
|
||||
.clientless transport link ship_ratchet ship_booty_bay ship 100 both
|
||||
```
|
||||
|
||||
Den ersten Stehplatz an der Gegenhaltestelle wieder exakt aufsuchen. Zwischen
|
||||
den beiden Node-Aufnahmen mit demselben Schiff mitfahren. `record start` beginnt
|
||||
jeweils auf festem Boden, `record stop` endet an Bord während desselben Halts.
|
||||
Pro physischer Anlegestelle weiterhin nur einen gemeinsamen Node verwenden;
|
||||
Landverbindungen zum übrigen TravelGraph getrennt als Groundkante erfassen.
|
||||
|
||||
Für den Zeppelin analog eigene Haltestellen-Keys, Fahrzeug-Spawn 20 und
|
||||
Kantentyp `zeppelin` verwenden. Schiffs- und Zeppelin-Verbindungen erst nach
|
||||
einer echten Fahrt als verifiziert betrachten. Die automatisierten Tests
|
||||
simulieren den nativen Kartenwechsel; sie ersetzen keinen echten Worldport-
|
||||
und Kollisions-/Sichtbarkeitstest.
|
||||
@@ -0,0 +1,151 @@
|
||||
# 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 <gameobjectSpawnId>
|
||||
```
|
||||
|
||||
Oder in der Testserver-Konsole ohne Punkt:
|
||||
|
||||
```text
|
||||
clientless portal object import <gameobjectSpawnId>
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,371 @@
|
||||
# Fahrzeug-Haltestellen und Reiseverbindungen aufnehmen
|
||||
|
||||
Anleitung für den Vcore-Testserver, Stand 26.10.2026. Für Schiffe, Zeppeline,
|
||||
Tiefenbahn und unterstützte Fahrstühle. Gemeint sind native Transportobjekte,
|
||||
keine NPC-Fahrzeuge, Reittiere oder Flugtaxen.
|
||||
|
||||
Die Aufnahme erfolgt mit einem eingeloggten GM im Spiel. Alle Beispiele mit
|
||||
`.clientless` gehören in den Spielchat. Diagnose- und Testbefehle sind teilweise
|
||||
auch in der Worldserver-Konsole verfügbar; dort den führenden Punkt weglassen.
|
||||
Eine neue Verbindung benötigt keinen Build und normalerweise keinen Neustart.
|
||||
|
||||
## Grundprinzip
|
||||
|
||||
Pro physischer Haltestelle gibt es **einen gemeinsamen Node für Ein- und
|
||||
Ausstieg**, auf festem Boden unmittelbar vor dem Übergang zum Fahrzeug.
|
||||
Auf dem Deck wird kein zusätzlicher TravelGraph-Node angelegt.
|
||||
|
||||
Für eine Verbindung A ↔ B werden aufgenommen:
|
||||
|
||||
1. Haltestellen-Node A und dessen kurzer Weg vom Land zum Deck-Stehplatz.
|
||||
2. Haltestellen-Node B und dessen kurzer Weg zum selben Deck-Stehplatz.
|
||||
3. Eine Fahrtkante zwischen A und B.
|
||||
4. Bei Bedarf separate Groundwege vom übrigen Reisenetz zu A und B.
|
||||
|
||||
Die eigentliche Fahrt wird nicht aufgezeichnet. Der Bot fährt als Passenger
|
||||
mit dem normalen Fahrzeug. Zum Aussteigen läuft er die jeweilige
|
||||
Land-Deck-Aufnahme rückwärts ab. Deshalb müssen diese Wege in beiden
|
||||
Laufrichtungen begehbar sein.
|
||||
|
||||
| Verkehrsmittel | Node- und Fahrtkantentyp |
|
||||
| --- | --- |
|
||||
| Schiff | `ship` |
|
||||
| Zeppelin | `zeppelin` |
|
||||
| Tiefenbahn | `tram` |
|
||||
| Fahrstuhl | `elevator` |
|
||||
|
||||
## 1. Fahrzeug und Halte bestimmen
|
||||
|
||||
Für Schiffe und Zeppeline lassen sich die konfigurierten nativen Dienste
|
||||
ortsunabhängig auflisten:
|
||||
|
||||
```text
|
||||
.clientless transport services
|
||||
.clientless transport services <spawnId>
|
||||
```
|
||||
|
||||
Die Detailausgabe nennt tatsächliche Halte, Karten und Haltezeiten. Historische
|
||||
Fahrzeugnamen können veraltete Zielorte enthalten. Die ausgegebene Dockposition
|
||||
ist der Fahrzeugursprung und **nicht** die Position für den Haltestellen-Node.
|
||||
`services` listet nicht sämtliche Fahrstühle oder Tiefenbahnwagen auf.
|
||||
|
||||
Vor Ort das gewünschte Fahrzeug untersuchen:
|
||||
|
||||
```text
|
||||
.clientless transport near 50
|
||||
.clientless transport inspect <spawnId>
|
||||
```
|
||||
|
||||
Entscheidend sind:
|
||||
|
||||
- `spawn`: das konkrete Fahrzeug bzw. der konkrete Wagen; diese ID für `record start` verwenden.
|
||||
- `entry`: Fahrzeugmodell/-vorlage; wird beispielsweise für `stand list` verwendet.
|
||||
- `stopped=1`: Fahrzeug steht laut serverseitiger Bewegung.
|
||||
- `remainingPause`: verbleibende Haltezeit in Millisekunden.
|
||||
|
||||
**Spawn-ID und Entry-ID nicht verwechseln.** Beide Haltestellen einer
|
||||
Verbindung müssen dasselbe konkrete Fahrzeug verwenden. Bei der Tiefenbahn
|
||||
also auch denselben Wagen. Bei einem nativen Kartenwechsel bleibt die
|
||||
Spawn-ID gleich.
|
||||
|
||||
Für reine Patrouillen ohne geeignete Halte keine reguläre Passagierverbindung
|
||||
anlegen. Vor Beginn mindestens einen Umlauf beobachten und beide Einstiege
|
||||
prüfen. Fahrstühle sind noch nicht als konkrete Verbindung live abgenommen;
|
||||
ihre Unterstützung muss je Objekt überprüft werden.
|
||||
|
||||
## 2. Haltestellen-Node A anlegen
|
||||
|
||||
Auf festem Boden direkt vor Rampe, Steg oder Plattform stehen. Der Node muss
|
||||
auch bei abwesendem Fahrzeug sicher erreichbar sein. Vorher vorhandene Nodes
|
||||
prüfen, damit keine doppelte Haltestelle entsteht:
|
||||
|
||||
```text
|
||||
.clientless node list_nearby 30
|
||||
```
|
||||
|
||||
Beispiel für eine **neue** Schiffsverbindung mit frei gewählten Namen:
|
||||
|
||||
```text
|
||||
.clientless node add ship_hafen_a ship
|
||||
.clientless transport node ship_hafen_a
|
||||
```
|
||||
|
||||
Die Beispielnamen `ship_hafen_a`, `ship_hafen_b` und `mein_schiff_deck` sind
|
||||
Platzhalter für deine neue Verbindung. Namen eindeutig wählen, ohne Leerzeichen,
|
||||
zum Beispiel mit Kleinbuchstaben, Ziffern und Unterstrichen. Für andere
|
||||
Verkehrsmittel Namen und Nodetyp entsprechend ändern.
|
||||
|
||||
## 3. An A den Weg Land → Deck aufnehmen
|
||||
|
||||
Auf eine frische Ankunft warten. Zu Fuß am Node stehen, noch nicht Passenger.
|
||||
Der Start erlaubt höchstens **2 Yards Abstand zum Node**. Das Fahrzeug muss
|
||||
auf derselben Karte und in derselben Phase geladen sein und stillstehen.
|
||||
|
||||
`<spawnId>` vor Ausführung durch die ermittelte Zahl ersetzen:
|
||||
|
||||
```text
|
||||
.clientless transport record start ship_hafen_a <spawnId>
|
||||
```
|
||||
|
||||
Jetzt normal an Bord gehen und einen sicheren, ebenen Deckplatz aufsuchen.
|
||||
Einen kurzen Weg ohne Sprünge, Flug, Teleport oder Hindernisse wählen. Dann
|
||||
noch während **desselben Halts** speichern:
|
||||
|
||||
```text
|
||||
.clientless transport record stop mein_schiff_deck
|
||||
```
|
||||
|
||||
`stop` speichert den Übergang und legt den benannten Deck-Stehplatz bei Bedarf
|
||||
an. Der Standname bezeichnet eine Position relativ zum Fahrzeugmodell.
|
||||
Diesen Platz an der Gegenhaltestelle wieder verwenden.
|
||||
|
||||
Optionale Befehle während der Aufnahme:
|
||||
|
||||
```text
|
||||
.clientless transport record info
|
||||
.clientless transport record mark
|
||||
.clientless transport record cancel
|
||||
```
|
||||
|
||||
`info` zeigt Punkte, Länge, Passenger-Status und Fehler. `mark` erzwingt einen
|
||||
zusätzlichen Punkt, beispielsweise an einer engen Kurve. Die automatische
|
||||
Aufnahme läuft alle 100 ms mit mindestens 0,75 Yards Punktabstand;
|
||||
der Übergang zum Passenger wird automatisch markiert.
|
||||
|
||||
Die Aufnahme wird ungültig, wenn das Fahrzeug abfährt, der Recorder das
|
||||
Fahrzeug nach dem Einstieg wieder verlässt oder wechselt, ein Positionssprung
|
||||
über 8 Yards entsteht oder der Übergang länger als 60 Yards wird.
|
||||
Fehler mit `info` ansehen, danach mit `cancel` verwerfen und beim nächsten
|
||||
vollständigen Halt neu beginnen. Ein Logout oder Serverneustart verliert
|
||||
ungespeicherte Aufnahmen; jede Haltestelle zuerst erfolgreich speichern.
|
||||
|
||||
## 4. An B denselben Deckplatz aufnehmen
|
||||
|
||||
Mit genau diesem Fahrzeug zur anderen Haltestelle fahren. Dort aussteigen
|
||||
und auf festem Boden unmittelbar vor dem Übergang Node B anlegen:
|
||||
|
||||
```text
|
||||
.clientless node add ship_hafen_b ship
|
||||
```
|
||||
|
||||
Beim nächsten geeigneten Halt von B wieder auf dasselbe Fahrzeug gehen:
|
||||
|
||||
```text
|
||||
.clientless transport record start ship_hafen_b <spawnId>
|
||||
```
|
||||
|
||||
Zum selben lokalen Deckplatz laufen und mit demselben Standnamen speichern:
|
||||
|
||||
```text
|
||||
.clientless transport record stop mein_schiff_deck
|
||||
.clientless transport stops
|
||||
```
|
||||
|
||||
Ist der Stand bereits gespeichert, muss man beim Speichern höchstens
|
||||
1,5 Yards davon entfernt stehen. Die beiden aufgezeichneten Deck-Endpunkte
|
||||
müssen außerdem innerhalb von 3 Yards liegen. Es wird kein unbekannter Weg
|
||||
quer über das Deck zwischen unterschiedlichen Standorten ergänzt.
|
||||
|
||||
Optional kann der Deckplatz schon vor der ersten Aufnahme gespeichert werden,
|
||||
indem man an Bord am gewünschten Platz steht:
|
||||
|
||||
```text
|
||||
.clientless transport stand add mein_schiff_deck
|
||||
.clientless transport stand list
|
||||
```
|
||||
|
||||
Das ist nicht erforderlich, wenn `record stop` den Stand bereits angelegt hat.
|
||||
Ein vorhandener Standname wird nicht überschrieben.
|
||||
|
||||
## 5. Fahrtkante erstellen
|
||||
|
||||
Nach beiden erfolgreich gespeicherten Aufnahmen:
|
||||
|
||||
```text
|
||||
.clientless transport link ship_hafen_a ship_hafen_b ship 100 both
|
||||
```
|
||||
|
||||
`both` erstellt eine bidirektionale Kante. Nur verwenden, wenn das Fahrzeug
|
||||
beide Richtungen tatsächlich bedient. Ohne `both` gilt ausschließlich A → B:
|
||||
|
||||
```text
|
||||
.clientless transport link ship_hafen_a ship_hafen_b ship 100
|
||||
```
|
||||
|
||||
`100` ist ein positiver **Graphkostenwert**, keine Fahrzeit in Sekunden.
|
||||
Er eignet sich als vorläufiger Wert für einen isolierten Funktionstest.
|
||||
Bei konkurrierenden Fernrouten die Kosten später passend abstimmen.
|
||||
|
||||
Der Link prüft kompatible Aufnahmen, dieselbe Spawn-ID und denselben Entry,
|
||||
unterschiedliche Halte und passende Deck-Endpunkte. `tram`/`elevator` erwarten
|
||||
GameObject-Typ 11, `ship`/`zeppelin` Typ 15. Eine bereits gleichgerichtet
|
||||
vorhandene Kante wird nicht überschrieben. Erfolgreiches Speichern und
|
||||
Verknüpfen laden die betreffenden Daten automatisch neu.
|
||||
|
||||
## 6. Groundanschlüsse getrennt aufnehmen
|
||||
|
||||
Der Transportlink verbindet die beiden Haltestellen miteinander, nicht
|
||||
zugleich mit dem übrigen Reisenetz. Für einen fehlenden Landanschluss beide
|
||||
Nodes vorher anlegen bzw. einen bestehenden Stadtnode verwenden.
|
||||
|
||||
Beispiel: am bestehenden Node `stadt_knoten_a` anfangen und bis zur
|
||||
Haltestelle laufen:
|
||||
|
||||
```text
|
||||
.clientless route start stadt_knoten_a ship_hafen_a
|
||||
```
|
||||
|
||||
Am Haltestellen-Node auf festem Boden stoppen:
|
||||
|
||||
```text
|
||||
.clientless route stop
|
||||
```
|
||||
|
||||
Der Groundrecorder speichert bidirektional und lädt den Graph neu. Möglichst
|
||||
exakt an den Nodes beginnen und enden, damit die angehängten Endstücke keine
|
||||
Hindernisse schneiden. Diese Aufnahme endet **vor** dem Einstieg ins Fahrzeug;
|
||||
Land-Deck-Übergang und Fahrt werden separat wie oben erfasst. Auf Seite B
|
||||
entsprechend verfahren. Vollständig geprüfte MMAP-Anschlüsse können eine
|
||||
Groundaufnahme ersetzen, müssen aber für die konkrete Route funktionieren.
|
||||
|
||||
## 7. Botfahrt prüfen
|
||||
|
||||
Mit einem online befindlichen, untätigen Clientless-Bot an A testen.
|
||||
Die Zahl `26` ist Arthorans Charakter-GUID und bei einem anderen Bot zu ersetzen.
|
||||
Sein Login-Lua darf nicht gleichzeitig andere Reisen starten.
|
||||
|
||||
```text
|
||||
.clientless transport travel 26 ship_hafen_b
|
||||
.clientless transport status 26
|
||||
.clientless actioninfo 26
|
||||
```
|
||||
|
||||
`travel` stellt einen normalen Reiseauftrag in die Aktionswarteschlange;
|
||||
es unterbricht keine laufende Aktion. Nach Abschluss die Gegenrichtung testen:
|
||||
|
||||
```text
|
||||
.clientless transport travel 26 ship_hafen_a
|
||||
```
|
||||
|
||||
Eine funktionierende Fahrt durchläuft `Waiting` → `Boarding` → `Riding` →
|
||||
`Leaving` → `Arrived`. Prüfen, dass der Bot wirklich Passenger wird, einen
|
||||
gegebenenfalls nötigen Kartenwechsel abschließt, am Ziel aussteigt und den
|
||||
Landnode erreicht. Anschließend auch eine Reise mit Groundanschluss testen.
|
||||
Ein gespeicherter Link allein bestätigt noch keine funktionierende Botfahrt.
|
||||
|
||||
Abbruch einer bereits laufenden Transportfahrt:
|
||||
|
||||
```text
|
||||
.clientless transport cancel 26
|
||||
```
|
||||
|
||||
An Bord bleibt der Bot zunächst Passenger und versucht einen sicheren Ausstieg
|
||||
an einer aufgezeichneten Haltestelle. Das ist kein sofortiges Abspringen und
|
||||
kein allgemeines Leeren der Aktionswarteschlange.
|
||||
|
||||
## Aufnahmen korrigieren
|
||||
|
||||
**Nur die gespeicherte Land-Deck-Aufnahme ersetzen:**
|
||||
|
||||
```text
|
||||
.clientless transport forget ship_hafen_a
|
||||
```
|
||||
|
||||
Danach an A erneut `record start` und `record stop` ausführen. `forget`
|
||||
entfernt nur diese Übergangsaufnahme. Node, Groundkanten, Fahrtkante und
|
||||
benannte Deck-Stehplätze bleiben bestehen. Unvollständige Transportverbindungen
|
||||
werden währenddessen nicht geplant. Bleiben die Endpunkte kompatibel,
|
||||
muss die bestehende Fahrtkante nicht erneut angelegt werden.
|
||||
|
||||
**Haltestellen-Node verschieben:** am neuen festen Boden stehen und ausführen:
|
||||
|
||||
```text
|
||||
.clientless node move ship_hafen_a
|
||||
```
|
||||
|
||||
Danach die betroffene Transportaufnahme mit `forget` und neuer Aufnahme
|
||||
ersetzen. Angeschlossene Groundwege ebenfalls prüfen und gegebenenfalls neu
|
||||
aufnehmen; sie passen sich nicht automatisch an die neue Position an.
|
||||
|
||||
**Falsche Fahrtkante entfernen:**
|
||||
|
||||
```text
|
||||
.clientless route remove ship_hafen_a ship_hafen_b
|
||||
```
|
||||
|
||||
Dieser Befehl entfernt **alle Kanten zwischen diesen beiden Nodes in beiden
|
||||
Richtungen**, unabhängig vom Kantentyp. Daher nur verwenden, wenn genau diese
|
||||
Verbindungen entfernt werden sollen. Haltestellen-Aufnahmen und Nodes bleiben
|
||||
erhalten. Anschließend die gewünschte Fahrtkante mit `transport link` neu anlegen.
|
||||
|
||||
**Deckplätze prüfen oder einen unbenutzten Stand entfernen:**
|
||||
|
||||
```text
|
||||
.clientless transport stand list <entryId>
|
||||
.clientless transport stand remove <entryId> <standName>
|
||||
```
|
||||
|
||||
Ein von einer Haltestellen-Aufnahme verwendeter Stand kann nicht entfernt
|
||||
werden. Eine Änderung des gemeinsamen Deckplatzes erfordert passende neue
|
||||
Aufnahmen an beiden Haltestellen.
|
||||
|
||||
## Diagnose und häufige Fehler
|
||||
|
||||
| Meldung oder Symptom | Nächster Schritt |
|
||||
| --- | --- |
|
||||
| Abstand zum Node zu groß | Auf festem Boden bis auf höchstens 2 Yards an den Node zurückgehen. |
|
||||
| Recorder bereits Passenger | Aussteigen; Aufnahme muss auf festem Boden beginnen. |
|
||||
| Spawn nicht geladen | Spawn-ID, Karte und Phase prüfen; Fahrzeug vor Ort aufsuchen. |
|
||||
| Fahrzeug bewegt sich / Aufnahme nach Abfahrt ungültig | `record cancel`, nächsten vollständigen Halt abwarten. |
|
||||
| Dock bereits aufgenommen | Bestehende Daten mit `stops` prüfen; nur für einen beabsichtigten Ersatz `forget` verwenden. |
|
||||
| Standname an anderer Deckposition vorhanden | Zum ursprünglichen Stand gehen; alternativ neuen Namen und kompatible Aufnahmen verwenden. |
|
||||
| Link abgelehnt | Zwei gespeicherte Halte, gleicher Spawn/Entry, kompatible Deck-Endpunkte und richtigen Kantentyp prüfen. |
|
||||
| Bot wartet dauerhaft | Richtigen Spawn, tatsächliche Halte, Dockposition und `status` prüfen. |
|
||||
| Fahrt klappt, Weiterreise nicht | Groundanschluss der Haltestelle separat prüfen bzw. aufnehmen. |
|
||||
|
||||
Weitere Befehle:
|
||||
|
||||
```text
|
||||
.clientless transport stops
|
||||
.clientless transport node ship_hafen_a
|
||||
.clientless transport reload
|
||||
```
|
||||
|
||||
`reload` lädt Transportdaten und TravelGraph neu. Laufende Fahrten behalten
|
||||
jedoch ihre beim Start erfassten Definitionen. Änderungen deshalb mit einem
|
||||
neuen Reiseauftrag testen.
|
||||
|
||||
Konsolenbeispiele ohne Punkt; für räumliche Diagnose ist ein online
|
||||
befindlicher Bot als Beobachter auf der betreffenden Karte nötig:
|
||||
|
||||
```text
|
||||
clientless transport services
|
||||
clientless transport services <spawnId>
|
||||
clientless transport node ship_hafen_a
|
||||
clientless transport inspect <spawnId> 26
|
||||
clientless transport near 50 26
|
||||
clientless transport stops
|
||||
clientless transport status 26
|
||||
```
|
||||
|
||||
`remainingPause=4294967295` bezeichnet einen Halt ohne bekannte zeitliche
|
||||
Begrenzung. Zustandswechsel und Aufnahmefehler stehen in
|
||||
`adventurebot-navigation.log` im Arbeitsverzeichnis des Test-worldservers.
|
||||
|
||||
## Bestehende Beispiele
|
||||
|
||||
Diese Namen und IDs gehören bereits erfassten Verbindungen; nicht als neue
|
||||
Haltestellen doppelt anlegen oder zum Üben überschreiben:
|
||||
|
||||
| Verbindung | Haltestellen | Fahrzeug |
|
||||
| --- | --- | --- |
|
||||
| Sturmwind ↔ Rut’theran, The Bravery | `ship_sw_br` ↔ `ship_ruttheran_br` | Spawn 2, Entry 176310, Stand `bravery_center` |
|
||||
| Tiefenbahn | `tram_sw` ↔ `tram_if` | Im dokumentierten Fahrtest Wagen-Spawn 18803; bestehende Aufnahme mit `stops` prüfen. |
|
||||
|
||||
Bei der Tiefenbahn gibt es mehrere Wagen mit verschiedenen Spawn-IDs; deren
|
||||
Aufnahmen nicht mischen. Die kurzen Haltefenster erfordern einen kurzen
|
||||
Einstiegsweg und zügiges Speichern.
|
||||
|
||||
Weiterführend: [technische Transportdokumentation](../doc/clientless/transport-tools.md),
|
||||
[Schiff Sturmwind–Rut’theran](../doc/clientless/ship-stormwind-ruttheran.md),
|
||||
[Transport-Grid-Lifecycle](../doc/clientless/transport-grid-lifecycle.md).
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Same database/transaction as characters.health and saved instance position.
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_instance_visit (
|
||||
character_guid int unsigned NOT NULL,
|
||||
location_key varchar(100) NOT NULL,
|
||||
entry_trigger int unsigned NOT NULL,
|
||||
exit_trigger int unsigned NOT NULL,
|
||||
instance_map int unsigned NOT NULL,
|
||||
instance_id int unsigned NOT NULL DEFAULT 0,
|
||||
block_end bigint unsigned NOT NULL,
|
||||
prepare_until bigint unsigned NOT NULL DEFAULT 0,
|
||||
phase tinyint unsigned NOT NULL,
|
||||
loss_percent tinyint unsigned NOT NULL,
|
||||
injury_applied tinyint unsigned NOT NULL DEFAULT 0,
|
||||
schedule tinyint unsigned NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY(character_guid)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1 +1,14 @@
|
||||
*.sql
|
||||
!2026_10_25_00_clientless_transport.sql
|
||||
!2026_10_26_00_clientless_disable_taxi_585.sql
|
||||
!2026_10_26_01_clientless_stormwind_mage_tower.sql
|
||||
!2026_10_26_02_clientless_portal_use.sql
|
||||
!2026_10_26_03_adventure_behavior.sql
|
||||
!2026_10_26_04_adventure_social.sql
|
||||
!2026_10_27_00_adventure_rest.sql
|
||||
!2026_10_27_01_adventure_rest_fire.sql
|
||||
!2026_10_27_02_adventure_leisure.sql
|
||||
|
||||
!2026_10_27_03_adventure_economy.sql
|
||||
!2026_10_27_04_adventure_exploration.sql
|
||||
!2026_10_27_05_adventure_profession.sql
|
||||
@@ -0,0 +1,27 @@
|
||||
-- Vcore CPC: one shared embark/disembark node per physical stop.
|
||||
-- Apply explicitly to the dedicated test world database. No routes are seeded.
|
||||
CREATE TABLE IF NOT EXISTS vcore_clientless_transport_stop (
|
||||
node_key varchar(100) NOT NULL,
|
||||
transport_entry int unsigned NOT NULL,
|
||||
transport_spawn int unsigned NOT NULL,
|
||||
map int unsigned NOT NULL,
|
||||
dock_x float NOT NULL, dock_y float NOT NULL, dock_z float NOT NULL, dock_o float NOT NULL,
|
||||
period_ms int unsigned NOT NULL,
|
||||
stand_name varchar(100) NOT NULL,
|
||||
PRIMARY KEY (node_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS vcore_clientless_transport_point (
|
||||
node_key varchar(100) NOT NULL,
|
||||
point_index int unsigned NOT NULL,
|
||||
on_transport tinyint unsigned NOT NULL,
|
||||
x float NOT NULL, y float NOT NULL, z float NOT NULL, o float NOT NULL,
|
||||
PRIMARY KEY (node_key,point_index)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS vcore_clientless_transport_stand (
|
||||
transport_entry int unsigned NOT NULL,
|
||||
name varchar(100) NOT NULL,
|
||||
x float NOT NULL, y float NOT NULL, z float NOT NULL, o float NOT NULL,
|
||||
PRIMARY KEY (transport_entry,name)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Explicit test-TravelGraph correction. No changes to WoW taxi definitions/NPCs.
|
||||
START TRANSACTION;
|
||||
UPDATE vcore_clientless_travel_node
|
||||
SET enabled=0,comment='Disabled: taxi 585 is not a regular player flight point (GM verified in Ruttheran)'
|
||||
WHERE node_key='taxi_585';
|
||||
UPDATE vcore_clientless_world_point
|
||||
SET enabled=0,comment='Disabled: taxi 585 is not a regular player flight point (GM verified in Ruttheran)'
|
||||
WHERE point_key='taxi_585';
|
||||
UPDATE vcore_clientless_travel_edge SET enabled=0
|
||||
WHERE from_node_key='taxi_585' OR to_node_key='taxi_585';
|
||||
COMMIT;
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Explicit local test-graph calibration; first run these worldserver commands:
|
||||
-- clientless portal import 702
|
||||
-- clientless portal import 704
|
||||
-- The importer seeds source nodes at the native AreaTrigger box centers.
|
||||
-- These centers are above the walkable floor. Keep their X/Y and move only
|
||||
-- the graph approach Z inside the native box, using the opposite arrival Z.
|
||||
-- Native areatrigger_teleport and DBC data are deliberately untouched.
|
||||
-- Reapply after reimporting 702/704, then reload the travel graph.
|
||||
START TRANSACTION;
|
||||
UPDATE vcore_clientless_world_point
|
||||
SET position_z=29.6207,
|
||||
comment='Mage tower 702 walkable approach inside native trigger; calibrated 2026-10-26'
|
||||
WHERE point_key='portal_at_702_source' AND map=0;
|
||||
UPDATE vcore_clientless_world_point
|
||||
SET position_z=148.616,
|
||||
comment='Mage tower 704 walkable approach inside native trigger; calibrated 2026-10-26'
|
||||
WHERE point_key='portal_at_704_source' AND map=0;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,10 @@
|
||||
-- Apply explicitly to the dedicated test world DB. No portals are auto-enabled.
|
||||
-- A directed portal_use edge binds to one static clickable GameObject spawn.
|
||||
-- Entry and spell identify stale bindings after native portal data changes.
|
||||
CREATE TABLE IF NOT EXISTS vcore_clientless_portal_use (
|
||||
edge_id int unsigned NOT NULL,
|
||||
gameobject_spawn_id int unsigned NOT NULL,
|
||||
gameobject_entry int unsigned NOT NULL,
|
||||
spell_id int unsigned NOT NULL,
|
||||
PRIMARY KEY (edge_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -0,0 +1,73 @@
|
||||
-- Additive catalogs and metadata; reapplying preserves all manual corrections.
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_location (
|
||||
point_key VARCHAR(100) NOT NULL PRIMARY KEY,
|
||||
display_name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
source_type VARCHAR(32) NOT NULL DEFAULT 'manual', source_id INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
area_id INT UNSIGNED NOT NULL DEFAULT 0, zone_id INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
region_key VARCHAR(100) NOT NULL DEFAULT '', is_area TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
faction TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 any, 1 alliance, 2 horde',
|
||||
KEY zone_id(zone_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_location_intent (
|
||||
category VARCHAR(64) NOT NULL, intent VARCHAR(32) NOT NULL,
|
||||
weight FLOAT NOT NULL DEFAULT 1, PRIMARY KEY(category,intent)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent VALUES
|
||||
('tavern','social',5),('festival','social',3),('settlement','social',1),
|
||||
('mine','profession',3),('mine','adventure',2),('workshop','profession',4),
|
||||
('service','profession',1),('ruins','adventure',3),('dungeon','adventure',3),
|
||||
('landmark','adventure',1),('wilderness','adventure',3),('zone','adventure',2),
|
||||
('settlement','adventure',0.5),('bank','profession',0.5);
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_action (
|
||||
action_key VARCHAR(64) NOT NULL PRIMARY KEY, kind VARCHAR(32) NOT NULL,
|
||||
min_seconds INT UNSIGNED NOT NULL, max_seconds INT UNSIGNED NOT NULL,
|
||||
requirement VARCHAR(32) NOT NULL DEFAULT '', emote_id INT UNSIGNED NOT NULL DEFAULT 0
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT IGNORE INTO vcore_adventure_action VALUES
|
||||
('look','look',6,14,'',0),('explore','wander',12,30,'',0),
|
||||
('rest','sit',20,60,'',0),('campfire_rest','sit',25,65,'campfire',0),
|
||||
('drink','drink',15,35,'',0),('eat','eat',15,35,'',0),
|
||||
('wave','emote',8,18,'audience',3),('nod','emote',8,18,'audience',273),
|
||||
('laugh','emote',10,24,'audience',11),('cheer','emote',10,24,'audience',4),
|
||||
('speak','say',12,30,'audience',1),
|
||||
('mining_show','work',15,35,'ore',233),('smithing_show','work',15,35,'forge',173);
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_action_intent (
|
||||
action_key VARCHAR(64) NOT NULL,intent VARCHAR(32) NOT NULL,
|
||||
weight FLOAT NOT NULL DEFAULT 1, PRIMARY KEY(action_key,intent)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent VALUES
|
||||
('look','social',1),('explore','social',0.5),('rest','social',2),('campfire_rest','social',3),
|
||||
('drink','social',5),('eat','social',2),('wave','social',1),('nod','social',1),
|
||||
('laugh','social',1),('cheer','social',0.5),('speak','social',2),
|
||||
('look','adventure',2),('explore','adventure',5),('rest','adventure',1),
|
||||
('campfire_rest','adventure',3),('drink','adventure',0.5),('eat','adventure',1),
|
||||
('speak','adventure',0.5),('look','profession',1),('explore','profession',2),
|
||||
('rest','profession',1),('eat','profession',0.5),('speak','profession',1),
|
||||
('mining_show','profession',5),('smithing_show','profession',5);
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_dialog (
|
||||
line_key VARCHAR(64) NOT NULL,locale VARCHAR(8) NOT NULL,intent VARCHAR(32) NOT NULL,
|
||||
text VARCHAR(255) NOT NULL,weight FLOAT NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY(line_key,locale)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT IGNORE INTO vcore_adventure_dialog VALUES
|
||||
('another_drink','deDE','social','Noch ein Bier bitte.',1),
|
||||
('good_rest','deDE','social','Eine gute Gelegenheit für eine Pause.',1),
|
||||
('good_company','deDE','social','In guter Gesellschaft vergeht die Zeit schnell.',1),
|
||||
('long_road','deDE','social','Heute war ich schon eine Weile unterwegs.',1),
|
||||
('adventure_road','deDE','adventure','Mal sehen, was es hier zu entdecken gibt.',1),
|
||||
('adventure_rest','deDE','adventure','Eine kurze Rast, dann geht es weiter.',1),
|
||||
('work_care','deDE','profession','Gute Arbeit braucht ihre Zeit.',1),
|
||||
('work_tools','deDE','profession','Mit dem richtigen Werkzeug geht es leichter.',1),
|
||||
('another_drink','enUS','social','Another drink, please.',1),
|
||||
('good_rest','enUS','social','A good time for a little rest.',1),
|
||||
('good_company','enUS','social','Time passes quickly in good company.',1),
|
||||
('long_road','enUS','social','I have been on the road for a while today.',1),
|
||||
('adventure_road','enUS','adventure','Let us see what there is to discover here.',1),
|
||||
('adventure_rest','enUS','adventure','A short rest before moving on.',1),
|
||||
('work_care','enUS','profession','Good work takes time.',1),
|
||||
('work_tools','enUS','profession','The right tools make the job easier.',1);
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_day (
|
||||
character_guid INT UNSIGNED NOT NULL,local_date INT UNSIGNED NOT NULL,
|
||||
hour_slot TINYINT UNSIGNED NOT NULL,intent VARCHAR(32) NOT NULL,location_key VARCHAR(100) NOT NULL,
|
||||
PRIMARY KEY(character_guid,local_date,hour_slot)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -0,0 +1,63 @@
|
||||
-- Apply after 2026_10_26_03. Seed new social scenes without replacing manual weights.
|
||||
INSERT IGNORE INTO vcore_adventure_action VALUES
|
||||
('social_npc','social',20,35,'npc',0),
|
||||
('social_bot','social',20,35,'bot',0),
|
||||
('social_seat','social',30,75,'seat',0),
|
||||
('social_counter','social',15,30,'counter',0),
|
||||
('social_order','social',20,30,'order',0),
|
||||
('social_greet','social',6,10,'greet',0),
|
||||
('social_listen','social',12,20,'listen',0),
|
||||
('social_react','social',6,12,'react',0),
|
||||
('social_toast','social',8,14,'toast',0),
|
||||
('social_farewell','social',4,8,'farewell',0),
|
||||
('social_comment','social',8,14,'comment',0),
|
||||
('social_dance','social',12,25,'dance',0),
|
||||
('social_fire','social',25,50,'fire',0),
|
||||
('social_make_fire','social',8,15,'make_fire',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent VALUES
|
||||
('social_npc','social',3),('social_bot','social',1.5),('social_seat','social',3),
|
||||
('social_counter','social',1.2),('social_order','social',2),('social_greet','social',0.7),
|
||||
('social_listen','social',1),('social_react','social',1),('social_toast','social',0.4),
|
||||
('social_farewell','social',0.4),('social_comment','social',0.6),('social_dance','social',0.3),
|
||||
('social_fire','social',1),('social_make_fire','social',0.4);
|
||||
-- Upgrade only the unchanged original seed; intentional edits to that row survive.
|
||||
UPDATE vcore_adventure_action SET kind='social',requirement='npc'
|
||||
WHERE action_key='speak' AND kind='say' AND requirement='audience' AND emote_id=1;
|
||||
INSERT IGNORE INTO vcore_adventure_dialog VALUES
|
||||
('greet_hello','deDE','social','Seid gegrüßt!',1),
|
||||
('greet_evening','deDE','social','Wie geht es Euch heute?',1),
|
||||
('greet_rest','deDE','social','Darf ich Euch kurz Gesellschaft leisten?',1),
|
||||
('talk_road','deDE','social','Auf meinen Reisen gibt es immer etwas zu erzählen.',1),
|
||||
('talk_news','deDE','social','Gibt es Neuigkeiten aus der Gegend?',1),
|
||||
('talk_weather','deDE','social','Hier lässt es sich eine Weile aushalten.',1),
|
||||
('talk_company','deDE','social','Ein gutes Gespräch gehört zu einer guten Rast.',1),
|
||||
('order_beer','deDE','social','Noch ein Bier bitte.',1),
|
||||
('order_drink','deDE','social','Etwas zu trinken wäre jetzt genau richtig.',1),
|
||||
('order_please','deDE','social','Ein Getränk, wenn Ihr einen Moment Zeit habt.',1),
|
||||
('farewell_road','deDE','social','Macht es gut. Wir sehen uns bestimmt wieder.',1),
|
||||
('farewell_thanks','deDE','social','Danke für die Gesellschaft!',1),
|
||||
('farewell_later','deDE','social','Bis später!',1),
|
||||
('toast_health','deDE','social','Auf Euer Wohl!',1),
|
||||
('toast_road','deDE','social','Auf gute Reisen und sichere Heimkehr!',1),
|
||||
('comment_rest','deDE','social','Eine angenehme Pause.',1),
|
||||
('comment_company','deDE','social','In guter Gesellschaft vergeht die Zeit schnell.',1),
|
||||
('greet_hello','enUS','social','Greetings!',1),
|
||||
('greet_evening','enUS','social','How are you today?',1),
|
||||
('greet_rest','enUS','social','May I join you for a moment?',1),
|
||||
('talk_road','enUS','social','There is always a story to tell after a journey.',1),
|
||||
('talk_news','enUS','social','Any news from around here?',1),
|
||||
('talk_weather','enUS','social','This is a pleasant place to spend some time.',1),
|
||||
('talk_company','enUS','social','A good conversation makes a good rest.',1),
|
||||
('order_beer','enUS','social','Another beer, please.',1),
|
||||
('order_drink','enUS','social','Something to drink would be just right.',1),
|
||||
('order_please','enUS','social','A drink when you have a moment, please.',1),
|
||||
('farewell_road','enUS','social','Farewell. I am sure we will meet again.',1),
|
||||
('farewell_thanks','enUS','social','Thank you for the company!',1),
|
||||
('farewell_later','enUS','social','See you later!',1),
|
||||
('toast_health','enUS','social','To your health!',1),
|
||||
('toast_road','enUS','social','To good journeys and safe returns!',1),
|
||||
('comment_rest','enUS','social','A pleasant little rest.',1),
|
||||
('comment_company','enUS','social','Time passes quickly in good company.',1);
|
||||
-- Existing campfire rest can also create its fire; no Cooking skill gate.
|
||||
UPDATE vcore_adventure_action SET kind='social',requirement='fire'
|
||||
WHERE action_key='campfire_rest' AND kind='sit' AND requirement='campfire' AND emote_id=0;
|
||||
@@ -0,0 +1,55 @@
|
||||
-- Apply after 2026_10_26_04. Preserve edited weights and existing world points.
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent VALUES
|
||||
('tavern','rest',8),('settlement','rest',1),
|
||||
('rest_seat','rest',4),('rest_sleep','rest',6),('rest_ground','rest',3);
|
||||
|
||||
-- Native furniture scenes are shared with social; no generic ground sitting
|
||||
-- in streets. Sleeping and ground sitting require explicitly authored points.
|
||||
INSERT IGNORE INTO vcore_adventure_action VALUES
|
||||
('rest_seat','social',60,100,'seat',0),
|
||||
('rest_sleep','recovery',120,300,'sleep',0),
|
||||
('rest_ground','recovery',60,120,'ground',0),
|
||||
('rest_drink','social',35,60,'drink_seated',0),
|
||||
('rest_eat','social',35,60,'eat_seated',0),
|
||||
('rest_look','look',6,12,'',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent VALUES
|
||||
('rest_seat','rest',6),('rest_sleep','rest',8),('rest_ground','rest',3),
|
||||
('rest_drink','rest',1),('rest_eat','rest',1),('rest_look','rest',0.25);
|
||||
|
||||
-- Sleep/ground points are deliberately not generated from innkeepers or random
|
||||
-- terrain. Add surveyed resting spots as enabled world points with category
|
||||
-- rest_sleep/rest_ground. A city bench approach point uses rest_seat.
|
||||
|
||||
-- Initial Goldshire upstairs resting corner. Navigation must confirm arrival
|
||||
-- before the native sleep pose is applied; no teleport onto decorative beds.
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment) VALUES
|
||||
('goldshire_sleep_upstairs','rest_sleep',0,-9457.2,32.8,63.9322,1.45,1,
|
||||
'Designated upstairs tavern floor resting spot; native sleep pose after MMAP arrival');
|
||||
INSERT IGNORE INTO vcore_adventure_location
|
||||
(point_key,display_name,source_type,region_key,zone_id,faction) VALUES
|
||||
('goldshire_sleep_upstairs','Goldhain: Ruheplatz im Obergeschoss','manual','elwynn',12,1);
|
||||
|
||||
-- Keep this dependent on the actual native bench spawn, rather than creating
|
||||
-- furniture. The approach lies two yards in front of the Stormwind bench.
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment)
|
||||
SELECT 'stormwind_rest_bench','rest_seat',g.map,
|
||||
g.position_x+2*COS(g.orientation),g.position_y+2*SIN(g.orientation),
|
||||
g.position_z,g.orientation,1,'Rest approach to native Stormwind stone bench spawn 219847'
|
||||
FROM gameobject g JOIN gameobject_template t ON t.entry=g.id
|
||||
WHERE g.guid=219847 AND g.map=0 AND g.id=203946 AND t.type=7;
|
||||
INSERT IGNORE INTO vcore_adventure_location
|
||||
(point_key,display_name,source_type,region_key,zone_id,faction)
|
||||
SELECT point_key,'Sturmwind: Bankpause','manual','stormwind',1519,1
|
||||
FROM vcore_clientless_world_point WHERE point_key='stormwind_rest_bench';
|
||||
|
||||
-- Gilded Rose upstairs resting corner; MMAP arrival is required and visual
|
||||
-- suitability is checked in game. This is a floor pose, not native bed use.
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment) VALUES
|
||||
('gilded_rose_sleep_upstairs','rest_sleep',0,-8863.8,685.8,104.932,3.74,1,
|
||||
'Designated upstairs Gilded Rose floor sleeping spot; visual acceptance pending');
|
||||
INSERT IGNORE INTO vcore_adventure_location
|
||||
(point_key,display_name,source_type,region_key,zone_id,faction) VALUES
|
||||
('gilded_rose_sleep_upstairs','Gilded Rose: Ruheplatz im Obergeschoss','manual','stormwind',1519,1);
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Apply after 2026_10_27_00. Reuse the shared native fire scene for rest.
|
||||
-- Preserve existing action definitions and manually edited selection weights.
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id) VALUES
|
||||
('rest_fire','social',45,75,'fire',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent
|
||||
(action_key,intent,weight) VALUES ('rest_fire','rest',3);
|
||||
@@ -0,0 +1,39 @@
|
||||
-- Additive leisure catalog after the social/rest stages; preserve edited weights.
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent (category,intent,weight) VALUES
|
||||
('leisure','leisure',8),('leisure_fishing','leisure',3),('settlement','leisure',3),
|
||||
('landmark','leisure',1),('wilderness','leisure',2),('festival','leisure',3);
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id) VALUES
|
||||
('leisure_walk','leisure',150,240,'walk',0),
|
||||
('leisure_roam','leisure',90,180,'roam',0),
|
||||
('leisure_pet_walk','leisure',180,300,'pet_walk',0),
|
||||
('leisure_ride','leisure',90,180,'ride',0),
|
||||
('leisure_flight','leisure',180,300,'flight',0),
|
||||
('leisure_fish','leisure',45,90,'fish',0),
|
||||
('leisure_view','look',20,45,'',0),
|
||||
('leisure_linger','look',30,75,'',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent (action_key,intent,weight) VALUES
|
||||
('leisure_walk','leisure',6),('leisure_roam','leisure',3),('leisure_pet_walk','leisure',3),
|
||||
('leisure_ride','leisure',1),('leisure_flight','leisure',0.4),('leisure_fish','leisure',2),
|
||||
('leisure_view','leisure',2),('leisure_linger','leisure',2),
|
||||
('social_npc','leisure',1),('social_bot','leisure',1),('social_listen','leisure',0.8),
|
||||
('social_seat','leisure',2),('rest_drink','leisure',1),('rest_eat','leisure',1),
|
||||
('social_fire','leisure',0.5),('social_dance','leisure',0.3);
|
||||
-- Native teleport catalog supplies surveyed ground coordinates; travel remains MMAP.
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment)
|
||||
SELECT 'stormwind_leisure_trade','leisure',map,position_x,position_y,position_z,orientation,1,
|
||||
'Leisure anchor at native TradeDistrict ground position; no teleport is performed'
|
||||
FROM game_tele WHERE name='TradeDistrict' AND map=0;
|
||||
INSERT IGNORE INTO vcore_adventure_location
|
||||
(point_key,display_name,source_type,region_key,zone_id,faction)
|
||||
SELECT point_key,'Sturmwind: Freizeit im Handelsdistrikt','manual','stormwind',1519,1
|
||||
FROM vcore_clientless_world_point WHERE point_key='stormwind_leisure_trade';
|
||||
|
||||
INSERT IGNORE INTO vcore_adventure_dialog (line_key,locale,intent,text,weight) VALUES
|
||||
('greet_leisure','deDE','leisure','Guten Tag! Ein schöner Tag für einen Spaziergang.',1),
|
||||
('talk_leisure','deDE','leisure','Heute lasse ich es einmal ruhig angehen.',1),
|
||||
('farewell_leisure','deDE','leisure','Macht es gut, ich drehe noch eine Runde.',1),
|
||||
('greet_leisure','enUS','leisure','Hello! A fine day for a stroll.',1),
|
||||
('talk_leisure','enUS','leisure','I am taking things easy today.',1),
|
||||
('farewell_leisure','enUS','leisure','Take care. I will walk a little farther.',1);
|
||||
@@ -0,0 +1,48 @@
|
||||
-- Performative economic visits. Additive catalog; preserve edited definitions/weights.
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent (category,intent,weight) VALUES
|
||||
('economy_vendor','economy',5),('economy_bank','economy',3),('economy_auction','economy',3);
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id) VALUES
|
||||
('economy_vendor_visit','social',15,25,'vendor_visit',0),
|
||||
('economy_goods','social',25,45,'goods',0),
|
||||
('economy_trade','social',25,40,'trade',0),
|
||||
('economy_compare','social',50,70,'vendor_compare',0),
|
||||
('economy_auction_visit','social',20,30,'auction_visit',0),
|
||||
('economy_auctions','social',35,60,'auctions',0),
|
||||
('economy_bank_visit','social',15,25,'bank_visit',0),
|
||||
('economy_banking','social',30,50,'banking',0),
|
||||
('economy_supplies','social',12,20,'supplies',0),
|
||||
('economy_wait','social',10,20,'service_wait',0),
|
||||
('economy_finish','social',5,10,'service_finish',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent (action_key,intent,weight) VALUES
|
||||
('economy_vendor_visit','economy',2),('economy_goods','economy',5),('economy_trade','economy',4),
|
||||
('economy_compare','economy',3),('economy_auction_visit','economy',2),('economy_auctions','economy',5),
|
||||
('economy_bank_visit','economy',2),('economy_banking','economy',5),('economy_supplies','economy',1),
|
||||
('economy_wait','economy',1),('economy_finish','economy',0.5);
|
||||
-- Named Stormwind service spawns supply the anchor's facing and position. Bank
|
||||
-- and auction NPCs stand on a raised counter platform; visitors use the floor
|
||||
-- in front. These are navigation destinations, never teleport instructions.
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment)
|
||||
SELECT CASE c.id WHEN 1285 THEN 'stormwind_economy_market' WHEN 2456 THEN 'stormwind_economy_bank' ELSE 'stormwind_economy_auction' END,
|
||||
CASE c.id WHEN 1285 THEN 'economy_vendor' WHEN 2456 THEN 'economy_bank' ELSE 'economy_auction' END,
|
||||
c.map,c.position_x+COS(c.orientation)*7,c.position_y+SIN(c.orientation)*7,
|
||||
c.position_z-CASE WHEN c.id=1285 THEN 0 ELSE 1.5 END,c.orientation,1,
|
||||
'Performative economic visit: arrival/withdrawal point in front of native service NPC; no transactions'
|
||||
FROM creature c JOIN creature_template t ON t.entry=c.id
|
||||
WHERE c.map=0 AND c.position_x BETWEEN -9000 AND -8750 AND c.position_y BETWEEN 450 AND 850
|
||||
AND ((c.id=1285 AND (t.npcflag & 128)<>0) OR (c.id=2456 AND (t.npcflag & 131072)<>0)
|
||||
OR (c.id=8719 AND (t.npcflag & 2097152)<>0)) ORDER BY c.guid;
|
||||
INSERT IGNORE INTO vcore_adventure_location
|
||||
(point_key,display_name,source_type,region_key,zone_id,faction)
|
||||
SELECT point_key,CASE category WHEN 'economy_vendor' THEN 'Sturmwind: Waren im Handelsdistrikt'
|
||||
WHEN 'economy_bank' THEN 'Sturmwind: Bankbesuch' ELSE 'Sturmwind: Auktionshausbesuch' END,
|
||||
'manual','stormwind',1519,1 FROM vcore_clientless_world_point
|
||||
WHERE point_key IN ('stormwind_economy_market','stormwind_economy_bank','stormwind_economy_auction');
|
||||
INSERT IGNORE INTO vcore_adventure_dialog (line_key,locale,intent,text,weight) VALUES
|
||||
('greet_economy','deDE','economy','Guten Tag. Ich möchte mich ein wenig umsehen.',1),
|
||||
('talk_economy','deDE','economy','Ich prüfe gerade, was ich für meine nächste Reise brauche.',1),
|
||||
('farewell_economy','deDE','economy','Vielen Dank für Eure Zeit. Einen schönen Tag noch!',1),
|
||||
('greet_economy','enUS','economy','Good day. I would like to have a look around.',1),
|
||||
('talk_economy','enUS','economy','I am checking what I need for my next journey.',1),
|
||||
('farewell_economy','enUS','economy','Thank you for your time. Have a good day!',1);
|
||||
@@ -0,0 +1,43 @@
|
||||
-- Exploration builds on existing social/rest/native ground-outing abilities.
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id) VALUES
|
||||
('adventure_explore','outing',150,240,'explore',0),
|
||||
('adventure_patrol','outing',90,180,'patrol',0),
|
||||
('adventure_view','social',25,45,'vista',0),
|
||||
('adventure_inspect','social',20,35,'inspect',0),
|
||||
('adventure_inspect_detail','social',25,40,'inspect_detail',0),
|
||||
('adventure_point','social',8,15,'point_object',0),
|
||||
('adventure_scout','social',20,35,'scout',0),
|
||||
('adventure_equipment','social',12,20,'equipment',0),
|
||||
('adventure_entrance','social',20,35,'entrance',0),
|
||||
('adventure_comment','social',10,20,'comment',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent (action_key,intent,weight) VALUES
|
||||
('adventure_explore','adventure',5),('adventure_patrol','adventure',3),
|
||||
('adventure_view','adventure',2),('adventure_inspect','adventure',4),
|
||||
('adventure_inspect_detail','adventure',3),('adventure_point','adventure',1),
|
||||
('adventure_scout','adventure',3),('adventure_equipment','adventure',1),
|
||||
('adventure_entrance','adventure',2),('adventure_comment','adventure',0.4),
|
||||
('social_npc','adventure',1.5),('social_seat','adventure',1),
|
||||
('social_fire','adventure',1.5),('rest_drink','adventure',0.5),('rest_eat','adventure',1);
|
||||
-- Retire only the untouched original tiny random wander for this intent;
|
||||
-- custom weights and its social/profession uses are preserved.
|
||||
UPDATE vcore_adventure_action_intent SET weight=0
|
||||
WHERE action_key='explore' AND intent='adventure' AND weight=5;
|
||||
INSERT IGNORE INTO vcore_adventure_dialog (line_key,locale,intent,text,weight) VALUES
|
||||
('greet_adventure','deDE','adventure','Seid gegrüßt. Ich sehe mich hier ein wenig um.',1),
|
||||
('talk_adventure','deDE','adventure','Gibt es hier in der Gegend etwas Interessantes zu entdecken?',1),
|
||||
('farewell_adventure','deDE','adventure','Danke für Eure Zeit. Ich werde mich noch etwas umsehen.',1),
|
||||
('comment_adventure','deDE','adventure','Das ist einen genaueren Blick wert.',1),
|
||||
('greet_adventure','enUS','adventure','Greetings. I am exploring the area.',1),
|
||||
('talk_adventure','enUS','adventure','Is there anything interesting to discover nearby?',1),
|
||||
('farewell_adventure','enUS','adventure','Thank you for your time. I will look around some more.',1),
|
||||
('comment_adventure','enUS','adventure','That deserves a closer look.',1);
|
||||
-- Locations own their intent eligibility through the editable category mapping.
|
||||
-- Materialize the previous general economic defaults instead of applying a
|
||||
-- hidden code fallback. Existing edited weights, including zero, take priority.
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent (category,intent,weight)
|
||||
SELECT DISTINCT category,'economy',CASE
|
||||
WHEN category IN ('settlement','zone') THEN 6
|
||||
WHEN category IN ('bank','service','tavern') THEN 4 ELSE 1 END
|
||||
FROM vcore_clientless_world_point WHERE category NOT LIKE 'travel%';
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent (category,intent,weight) VALUES ('tavern','leisure',1);
|
||||
@@ -0,0 +1,81 @@
|
||||
-- All jobs remain permanently performative. No harvesting/loot/crafting handlers.
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_workstation (
|
||||
gameobject_entry INT UNSIGNED NOT NULL,
|
||||
role VARCHAR(32) NOT NULL,
|
||||
enabled TINYINT UNSIGNED NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY(gameobject_entry,role)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
-- Native spell-focus semantics, verified against the loaded world templates.
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'anvil' FROM gameobject_template WHERE type=8 AND data0 IN (1,623);
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'forge' FROM gameobject_template WHERE type=8 AND data0 IN (3,543);
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'cooking' FROM gameobject_template WHERE type=8 AND data0=4;
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'alchemy' FROM gameobject_template WHERE type=8 AND data0=663;
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'inscription' FROM gameobject_template WHERE type=8 AND data0=1589;
|
||||
-- Semantic roles describe object TYPES, never bot-specific locations. Permit
|
||||
-- native focus-zero anvil/forge templates and explicit workshop props too.
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'anvil' FROM gameobject_template WHERE (type=5 OR (type=8 AND data0=0)) AND LOWER(name) LIKE '%anvil%';
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'forge' FROM gameobject_template WHERE (type=5 OR (type=8 AND data0=0)) AND LOWER(name) LIKE '%forge%' AND LOWER(name) NOT LIKE '%runeforge%';
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'workbench' FROM gameobject_template WHERE (type=8 AND data0 IN (1,623)) OR (type IN (5,8) AND LOWER(name) LIKE '%workbench%') OR ((type=5 OR (type=8 AND data0=0)) AND LOWER(name) LIKE '%anvil%');
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'sewing' FROM gameobject_template WHERE type IN (5,8) AND (LOWER(name)='loom' OR LOWER(name) LIKE '% loom%' OR LOWER(name) LIKE 'doodad_loom%' OR LOWER(name) LIKE '%sewing%');
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'leather' FROM gameobject_template WHERE type IN (5,8) AND (LOWER(name) LIKE '%tanning%' OR LOWER(name) LIKE '%leatherworking%table%');
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'jewelcrafting' FROM gameobject_template WHERE type IN (5,8) AND LOWER(name) LIKE '%jewel%table%';
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'enchanting' FROM gameobject_template WHERE type IN (5,8) AND LOWER(name) LIKE '%enchant%table%';
|
||||
INSERT IGNORE INTO vcore_adventure_workstation (gameobject_entry,role)
|
||||
SELECT entry,'wood' FROM gameobject_template WHERE type IN (5,8) AND (LOWER(name) LIKE '%woodpile%' OR LOWER(name) LIKE '%wood pile%' OR LOWER(name) LIKE '%lumber pile%');
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id) VALUES
|
||||
('profession_search','outing',90,150,'work_search',0),
|
||||
('profession_ore_inspect','social',12,20,'ore_inspect',0),
|
||||
('profession_herbalism','social',20,35,'work_herbalism',0),
|
||||
('profession_skinning','social',15,25,'work_skinning',0),
|
||||
('profession_smelting','social',25,40,'work_smelting',0),
|
||||
('profession_engineering','social',25,45,'work_engineering',0),
|
||||
('profession_alchemy','social',25,45,'work_alchemy',0),
|
||||
('profession_tailoring','social',25,45,'work_tailoring',0),
|
||||
('profession_leatherworking','social',25,45,'work_leatherworking',0),
|
||||
('profession_inscription','social',25,45,'work_inscription',0),
|
||||
('profession_enchanting','social',25,45,'work_enchanting',0),
|
||||
('profession_jewelcrafting','social',25,45,'work_jewelcrafting',0),
|
||||
('profession_wood','social',20,40,'work_wood',0),
|
||||
('profession_cooking','social',25,45,'work_cooking',0),
|
||||
('profession_first_aid','social',15,25,'work_first_aid',0),
|
||||
('profession_fishing','leisure',45,90,'fish',0),
|
||||
('profession_tools','social',12,20,'profession_tools',0),
|
||||
('profession_trainer','social',25,40,'profession_trainer',0),
|
||||
('profession_vendor','social',25,40,'profession_vendor',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent (action_key,intent,weight) VALUES
|
||||
('profession_search','profession',8),('profession_ore_inspect','profession',2),
|
||||
('profession_herbalism','profession',5),('profession_skinning','profession',5),
|
||||
('profession_smelting','profession',3),('profession_engineering','profession',4),
|
||||
('profession_alchemy','profession',4),('profession_tailoring','profession',4),
|
||||
('profession_leatherworking','profession',4),('profession_inscription','profession',4),
|
||||
('profession_enchanting','profession',4),('profession_jewelcrafting','profession',4),
|
||||
('profession_wood','profession',0.5),('profession_cooking','profession',0.5),
|
||||
('profession_first_aid','profession',0.3),('profession_fishing','profession',0.5),
|
||||
('profession_tools','profession',1),('profession_trainer','profession',1),
|
||||
('profession_vendor','profession',1),('social_seat','profession',0.5);
|
||||
-- A zone is a legitimate destination. Its actual workplaces/resources are
|
||||
-- discovered after travel to a reachable graph node in that area.
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent (category,intent,weight) VALUES
|
||||
('zone','profession',3),('wilderness','profession',3),('settlement','profession',2);
|
||||
UPDATE vcore_adventure_action_intent SET weight=0
|
||||
WHERE action_key='explore' AND intent='profession' AND weight=2;
|
||||
INSERT IGNORE INTO vcore_adventure_dialog (line_key,locale,intent,text,weight) VALUES
|
||||
('greet_profession','deDE','profession','Seid gegrüßt. Habt Ihr kurz Zeit für eine Fachfrage?',1),
|
||||
('talk_profession','deDE','profession','Ich sehe mich nach passenden Materialien und Arbeitsplätzen um.',1),
|
||||
('farewell_profession','deDE','profession','Vielen Dank. Ich mache mich wieder an die Arbeit.',1),
|
||||
('greet_profession','enUS','profession','Greetings. Do you have a moment for a trade question?',1),
|
||||
('talk_profession','enUS','profession','I am looking for suitable materials and places to work.',1),
|
||||
('farewell_profession','enUS','profession','Thank you. I will get back to work.',1);
|
||||
@@ -0,0 +1,30 @@
|
||||
-- Native outside entrance aliases only. Instance interiors stay graph nodes.
|
||||
CREATE TABLE IF NOT EXISTS vcore_adventure_instance (
|
||||
location_key varchar(100) NOT NULL,
|
||||
entry_trigger int unsigned NOT NULL,
|
||||
exit_trigger int unsigned NOT NULL DEFAULT 0 COMMENT '0: native exit discovery, separate exit preferred',
|
||||
enabled tinyint unsigned NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY(location_key), UNIQUE KEY(entry_trigger)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment)
|
||||
SELECT CONCAT('instance_visit_at_',a.ID),'instance_entrance',w.map,
|
||||
w.position_x,w.position_y,w.position_z,w.orientation,1,
|
||||
CONCAT('Native instance entrance: ',a.Name)
|
||||
FROM areatrigger_teleport a
|
||||
JOIN instance_template i ON i.map=a.target_map
|
||||
JOIN vcore_clientless_travel_node n ON n.node_key=CONCAT('portal_at_',a.ID,'_source') AND n.enabled=1
|
||||
JOIN vcore_clientless_world_point w ON w.point_key=n.world_point_key AND w.enabled=1
|
||||
LEFT JOIN instance_template inside_source ON inside_source.map=w.map
|
||||
WHERE inside_source.map IS NULL;
|
||||
|
||||
INSERT IGNORE INTO vcore_adventure_location (point_key,display_name,source_type,source_id)
|
||||
SELECT CONCAT('instance_visit_at_',a.ID),a.Name,'instance_entrance',a.ID
|
||||
FROM areatrigger_teleport a
|
||||
JOIN vcore_clientless_world_point w ON w.point_key=CONCAT('instance_visit_at_',a.ID) AND w.category='instance_entrance';
|
||||
INSERT IGNORE INTO vcore_adventure_instance(location_key,entry_trigger)
|
||||
SELECT point_key,source_id FROM vcore_adventure_location WHERE source_type='instance_entrance';
|
||||
INSERT IGNORE INTO vcore_adventure_location_intent(category,intent,weight)
|
||||
VALUES ('instance_entrance','instance',5);
|
||||
-- Other intent/category weights and existing plans are deliberately preserved.
|
||||
@@ -0,0 +1,7 @@
|
||||
-- A real native repairer is required. Only the scene is acted; completion
|
||||
-- restores durability for free without invoking trade/vendor handlers.
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id)
|
||||
VALUES ('economy_repair','social',25,45,'repair',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent(action_key,intent,weight)
|
||||
VALUES ('economy_repair','economy',2);
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Training is a leisure scene, only at a real, visible, reachable training dummy.
|
||||
INSERT IGNORE INTO vcore_adventure_action
|
||||
(action_key,kind,min_seconds,max_seconds,requirement,emote_id)
|
||||
VALUES ('leisure_training','leisure',60,180,'training',0);
|
||||
INSERT IGNORE INTO vcore_adventure_action_intent(action_key,intent,weight)
|
||||
VALUES ('leisure_training','leisure',2);
|
||||
@@ -85,3 +85,14 @@ endif()
|
||||
if(USE_COREPCH)
|
||||
add_cxx_pch(game ${PRIVATE_PCH_HEADER})
|
||||
endif()
|
||||
|
||||
# Vcore C7: server-side Lua runtime for clientless Player controllers.
|
||||
find_package(Lua 5.4 REQUIRED)
|
||||
target_include_directories(game PRIVATE ${LUA_INCLUDE_DIR})
|
||||
target_link_libraries(game PRIVATE ${LUA_LIBRARIES})
|
||||
|
||||
install(
|
||||
DIRECTORY "${CMAKE_SOURCE_DIR}/src/server/scripts/Custom/clientless/"
|
||||
DESTINATION "bin/scripts/clientless"
|
||||
FILES_MATCHING PATTERN "*.lua"
|
||||
)
|
||||
@@ -198,6 +198,9 @@ void ChatHandler::SendSysMessage(const char *str, bool escapeCharacters)
|
||||
|
||||
while (char* line = LineFromMessage(pos))
|
||||
{
|
||||
if (_logClientlessCommand)
|
||||
TC_LOG_INFO("server.adventurebot.navigation",
|
||||
"CLIENTLESS_COMMAND_REPLY account=%u text='%s'", m_session->GetAccountId(), line);
|
||||
BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
|
||||
m_session->SendPacket(&data);
|
||||
}
|
||||
@@ -411,6 +414,19 @@ bool ChatHandler::SetDataForCommandInTable(std::vector<ChatCommand>& table, char
|
||||
|
||||
bool ChatHandler::_ParseCommands(char const* text)
|
||||
{
|
||||
// Scope reply mirroring to this command invocation, including syntax errors.
|
||||
std::string const command(text);
|
||||
std::string const token = command.substr(0, command.find(' '));
|
||||
_logClientlessCommand = m_session && !token.empty() &&
|
||||
hasStringAbbr("clientless", token.c_str());
|
||||
struct ResetClientlessLog
|
||||
{
|
||||
bool& Enabled;
|
||||
~ResetClientlessLog() { Enabled = false; }
|
||||
} reset{ _logClientlessCommand };
|
||||
if (_logClientlessCommand)
|
||||
TC_LOG_INFO("server.adventurebot.navigation",
|
||||
"CLIENTLESS_COMMAND account=%u text='%s'", m_session->GetAccountId(), text);
|
||||
if (ExecuteCommandInTable(getCommandTable(), text, text))
|
||||
return true;
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ class TC_GAME_API ChatHandler
|
||||
|
||||
// common global flag
|
||||
bool sentErrorMessage;
|
||||
bool _logClientlessCommand = false;
|
||||
};
|
||||
|
||||
class TC_GAME_API CliHandler : public ChatHandler
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace Trainer
|
||||
void SendSpells(Creature const* npc, Player const* player, LocaleConstant locale) const;
|
||||
void TeachSpell(Creature const* npc, Player* player, uint32 spellId) const;
|
||||
|
||||
std::vector<Spell> const& GetSpells() const { return _spells; }
|
||||
|
||||
Type GetTrainerType() const { return _type; }
|
||||
uint32 GetTrainerRequirement() const { return _requirement; }
|
||||
bool IsTrainerValidForPlayer(Player const* player) const;
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <G3D/Box.h>
|
||||
#include <G3D/CoordinateFrame.h>
|
||||
#include <G3D/Quat.h>
|
||||
#include <limits>
|
||||
|
||||
bool QuaternionData::isUnit() const
|
||||
{
|
||||
@@ -330,6 +331,54 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool GetTransportDockState(TransportDockState& state) const override
|
||||
{
|
||||
state = {};
|
||||
if (!_animationInfo || !_animationInfo->TotalTime)
|
||||
return false;
|
||||
state.Progress = _pathProgress;
|
||||
state.Period = _animationInfo->TotalTime;
|
||||
if (!_stopFrames.empty())
|
||||
{
|
||||
if (int32(GameTime::GetGameTimeMS() - _owner.GetUInt32Value(GAMEOBJECT_LEVEL)) >= 0)
|
||||
{
|
||||
state.Stopped = true;
|
||||
state.RemainingPause = std::numeric_limits<uint32>::max();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
auto current = _animationInfo->Path.upper_bound(_pathProgress);
|
||||
if (current == _animationInfo->Path.begin())
|
||||
return true;
|
||||
--current;
|
||||
auto next = std::next(current);
|
||||
// Consecutive equal animation positions represent an actual dwell,
|
||||
// unlike a GO state which may already denote a future destination.
|
||||
auto samePosition = [](TransportAnimationEntry const* a, TransportAnimationEntry const* b)
|
||||
{
|
||||
return std::fabs(a->Pos.X - b->Pos.X) < 0.001f &&
|
||||
std::fabs(a->Pos.Y - b->Pos.Y) < 0.001f && std::fabs(a->Pos.Z - b->Pos.Z) < 0.001f;
|
||||
};
|
||||
while (next != _animationInfo->Path.end() && samePosition(current->second, next->second))
|
||||
++next;
|
||||
uint32 end = next == std::next(current) ? _pathProgress :
|
||||
std::prev(next)->first;
|
||||
// A stationary origin with a rotating deck is not a boarding stop.
|
||||
auto rotation = _animationInfo->Rotations.upper_bound(_pathProgress);
|
||||
if (rotation != _animationInfo->Rotations.begin() && rotation != _animationInfo->Rotations.end())
|
||||
{
|
||||
auto before = std::prev(rotation)->second;
|
||||
auto after = rotation->second;
|
||||
if (std::fabs(before->X - after->X) + std::fabs(before->Y - after->Y) +
|
||||
std::fabs(before->Z - after->Z) + std::fabs(before->W - after->W) > 0.001f)
|
||||
return true;
|
||||
end = std::min(end, rotation->first);
|
||||
}
|
||||
state.Stopped = end > _pathProgress;
|
||||
state.RemainingPause = state.Stopped ? end - _pathProgress : 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 GetTransportPeriod() const
|
||||
{
|
||||
if (_animationInfo)
|
||||
@@ -2963,6 +3012,14 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
|
||||
data->append(fieldBuffer);
|
||||
}
|
||||
|
||||
bool GameObject::GetTransportDockState(TransportDockState& state) const
|
||||
{
|
||||
state = {};
|
||||
if (Transport const* transport = ToTransport())
|
||||
return transport->GetDockState(state);
|
||||
return m_goTypeImpl && m_goTypeImpl->GetTransportDockState(state);
|
||||
}
|
||||
|
||||
std::vector<uint32> const* GameObject::GetPauseTimes() const
|
||||
{
|
||||
if (GameObjectType::Transport const* transport = dynamic_cast<GameObjectType::Transport const*>(m_goTypeImpl.get()))
|
||||
|
||||
@@ -33,6 +33,13 @@ class OPvPCapturePoint;
|
||||
class SpellInfo;
|
||||
class Transport;
|
||||
class TransportBase;
|
||||
struct TransportDockState
|
||||
{
|
||||
uint32 Progress = 0;
|
||||
uint32 Period = 0;
|
||||
uint32 RemainingPause = 0;
|
||||
bool Stopped = false;
|
||||
};
|
||||
class Unit;
|
||||
struct TransportAnimation;
|
||||
enum SpellTargetCheckTypes : uint8;
|
||||
@@ -55,6 +62,7 @@ public:
|
||||
virtual void Update([[maybe_unused]] uint32 diff) { }
|
||||
virtual void OnStateChanged([[maybe_unused]] GOState oldState, [[maybe_unused]] GOState newState) { }
|
||||
virtual void OnRelocated() { }
|
||||
virtual bool GetTransportDockState(TransportDockState&) const { return false; }
|
||||
|
||||
protected:
|
||||
GameObject& _owner;
|
||||
@@ -206,6 +214,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
|
||||
static void SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid = 0);
|
||||
|
||||
std::vector<uint32> const* GetPauseTimes() const;
|
||||
bool GetTransportDockState(TransportDockState& state) const;
|
||||
void SetPathProgressForClient(float progress);
|
||||
|
||||
void PlayAnimKit(int32 animKit);
|
||||
|
||||
@@ -273,6 +273,29 @@ void Transport::Update(uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
bool Transport::GetDockState(TransportDockState& state) const
|
||||
{
|
||||
state = {};
|
||||
if (!_transportInfo || !GetTransportPeriod())
|
||||
return false;
|
||||
state.Period = GetTransportPeriod();
|
||||
state.Progress = _pathProgress % state.Period;
|
||||
TransportMovementState movement;
|
||||
size_t index;
|
||||
if (!_transportInfo->ComputePosition(state.Progress, &movement, &index))
|
||||
return false;
|
||||
if (movement == TransportMovementState::WaitingOnPauseWaypoint)
|
||||
for (TransportPathSegment const& segment : _transportInfo->PathLegs[index].Segments)
|
||||
if (state.Progress >= segment.SegmentEndArrivalTimestamp &&
|
||||
state.Progress < segment.SegmentEndArrivalTimestamp + segment.Delay)
|
||||
{
|
||||
state.Stopped = true;
|
||||
state.RemainingPause = segment.SegmentEndArrivalTimestamp + segment.Delay - state.Progress;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Transport::AddPassenger(WorldObject* passenger)
|
||||
{
|
||||
if (!IsInWorld())
|
||||
|
||||
@@ -90,6 +90,7 @@ class TC_GAME_API Transport : public GameObject, public TransportBase
|
||||
uint32 GetTransportPeriod() const { return GetUInt32Value(GAMEOBJECT_LEVEL); }
|
||||
void SetPeriod(uint32 period) { SetUInt32Value(GAMEOBJECT_LEVEL, period); }
|
||||
uint32 GetTimer() const { return _pathProgress; }
|
||||
bool GetDockState(TransportDockState& state) const;
|
||||
|
||||
void UpdatePosition(float x, float y, float z, float o);
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "PetAI.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "ClientlessPlayerMgr.h"
|
||||
#include "PlayerAI.h"
|
||||
#include "QuestDef.h"
|
||||
#include "ReputationMgr.h"
|
||||
@@ -902,6 +903,8 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
|
||||
victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage);
|
||||
|
||||
victim->ModifyHealth(-(int32)damage);
|
||||
if (damage && victim->IsPlayer())
|
||||
sClientlessPlayerMgr->DamageTaken(victim->ToPlayer(), attacker, damage);
|
||||
|
||||
if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE)
|
||||
victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::NonPeriodicDamage, spellProto);
|
||||
|
||||
@@ -2383,6 +2383,7 @@ void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData co
|
||||
void ObjectMgr::LoadGameObjects()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
_transportGameObjectSpawns.clear();
|
||||
|
||||
// 0 1 2 3 4 5 6
|
||||
QueryResult result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, "
|
||||
@@ -2595,7 +2596,13 @@ void ObjectMgr::LoadGameObjects()
|
||||
}
|
||||
|
||||
if (gameEvent == 0) // if not this is to be managed by GameEvent System or Pool system
|
||||
{
|
||||
AddGameobjectToGrid(guid, &data);
|
||||
// These objects become active only after their spawn grid is loaded.
|
||||
// Index them so a distant station cannot leave half a service absent.
|
||||
if (gInfo->type == GAMEOBJECT_TYPE_TRANSPORT)
|
||||
_transportGameObjectSpawns[data.mapId].push_back(guid);
|
||||
}
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
@@ -3797,14 +3804,14 @@ void ObjectMgr::LoadPlayerInfo()
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
|
||||
uint32 current_class = fields[0].GetUInt8();
|
||||
uint32 current_class = fields[0].GetUInt16();
|
||||
if (current_class >= MAX_CLASSES)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Wrong class %u in `player_levelstats` table, ignoring.", current_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 current_level = fields[1].GetUInt8();
|
||||
uint32 current_level = fields[1].GetUInt16();
|
||||
if (current_level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
|
||||
|
||||
@@ -1392,6 +1392,11 @@ class TC_GAME_API ObjectMgr
|
||||
return &itr->second;
|
||||
}
|
||||
GameObjectDataContainer const& GetAllGameObjectData() const { return _gameObjectDataStore; }
|
||||
std::vector<ObjectGuid::LowType> const* GetTransportGameObjectSpawns(uint32 mapId) const
|
||||
{
|
||||
auto itr = _transportGameObjectSpawns.find(mapId);
|
||||
return itr != _transportGameObjectSpawns.end() ? &itr->second : nullptr;
|
||||
}
|
||||
GameObjectData const* GetGameObjectData(ObjectGuid::LowType spawnId) const
|
||||
{
|
||||
GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(spawnId);
|
||||
@@ -1752,6 +1757,7 @@ class TC_GAME_API ObjectMgr
|
||||
LinkedRespawnContainer _linkedRespawnStore;
|
||||
CreatureLocaleContainer _creatureLocaleStore;
|
||||
GameObjectDataContainer _gameObjectDataStore;
|
||||
std::unordered_map<uint32, std::vector<ObjectGuid::LowType>> _transportGameObjectSpawns;
|
||||
GameObjectLocaleContainer _gameObjectLocaleStore;
|
||||
GameObjectTemplateContainer _gameObjectTemplateStore;
|
||||
GameObjectTemplateAddonContainer _gameObjectTemplateAddonStore;
|
||||
|
||||
@@ -754,6 +754,56 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin&
|
||||
SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt1);
|
||||
}
|
||||
|
||||
bool WorldSession::InitializeClientlessPlayer(ObjectGuid playerGuid)
|
||||
{
|
||||
if (!IsClientless())
|
||||
{
|
||||
TC_LOG_ERROR("server.worldserver",
|
||||
"WorldSession::InitializeClientlessPlayer rejected a non-clientless session for account %u.",
|
||||
GetAccountId());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!playerGuid || !_clientlessPendingPlayerGuid.IsEmpty() || PlayerLoading() || GetPlayer())
|
||||
{
|
||||
TC_LOG_ERROR("server.worldserver",
|
||||
"WorldSession::InitializeClientlessPlayer rejected invalid initialization state for account %u, character GUID %u.",
|
||||
GetAccountId(), uint32(playerGuid.GetCounter()));
|
||||
return false;
|
||||
}
|
||||
|
||||
_clientlessPendingPlayerGuid = playerGuid;
|
||||
InitializeSession();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldSession::BeginClientlessPlayerLogin(ObjectGuid playerGuid)
|
||||
{
|
||||
if (!IsClientless())
|
||||
{
|
||||
TC_LOG_ERROR("server.worldserver",
|
||||
"WorldSession::BeginClientlessPlayerLogin rejected a non-clientless session for account %u.",
|
||||
GetAccountId());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!playerGuid || PlayerLoading() || GetPlayer())
|
||||
{
|
||||
TC_LOG_ERROR("server.worldserver",
|
||||
"WorldSession::BeginClientlessPlayerLogin rejected invalid login state for account %u, character GUID %u.",
|
||||
GetAccountId(), uint32(playerGuid.GetCounter()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clientless login deliberately does not use _legitCharacters.
|
||||
// That set is populated by CMSG_ENUM_CHARACTERS and is therefore
|
||||
// protocol/client state, not account ownership authority. Player::LoadFromDB
|
||||
// performs the authoritative account-id check against the character row.
|
||||
m_playerLoading = playerGuid;
|
||||
HandleContinuePlayerLogin();
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldSession::HandleContinuePlayerLogin()
|
||||
{
|
||||
if (!PlayerLoading() || GetPlayer())
|
||||
@@ -769,7 +819,7 @@ void WorldSession::HandleContinuePlayerLogin()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_legacyConnectionModeEnabled)
|
||||
if (IsNetworkSession() && !_legacyConnectionModeEnabled)
|
||||
SendPacket(WorldPackets::Auth::ResumeComms(CONNECTION_TYPE_INSTANCE).Write());
|
||||
|
||||
AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder)
|
||||
@@ -938,9 +988,12 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder const& holder)
|
||||
stmt->setUInt32(0, pCurrChar->GetGUID().GetCounter());
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
LoginDatabasePreparedStatement* loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE);
|
||||
loginStmt->setUInt32(0, GetAccountId());
|
||||
LoginDatabase.Execute(loginStmt);
|
||||
if (IsNetworkSession())
|
||||
{
|
||||
LoginDatabasePreparedStatement* loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE);
|
||||
loginStmt->setUInt32(0, GetAccountId());
|
||||
LoginDatabase.Execute(loginStmt);
|
||||
}
|
||||
|
||||
pCurrChar->SetInGameTime(GameTime::GetGameTimeMS());
|
||||
|
||||
|
||||
@@ -244,6 +244,24 @@ void WorldSession::HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck
|
||||
return;
|
||||
|
||||
|
||||
CompleteNearTeleport(plMover);
|
||||
}
|
||||
|
||||
void WorldSession::CompleteClientlessTeleport()
|
||||
{
|
||||
if (!IsClientless() || !GetPlayer())
|
||||
return;
|
||||
bool const pending = GetPlayer()->IsBeingTeleported();
|
||||
if (GetPlayer()->IsBeingTeleportedFar())
|
||||
HandleMoveWorldportAck();
|
||||
else if (GetPlayer()->IsBeingTeleportedNear())
|
||||
CompleteNearTeleport(GetPlayer());
|
||||
if (pending && GetPlayer() && GetPlayer()->IsInWorld() && !GetPlayer()->IsBeingTeleported())
|
||||
++_clientlessTeleportSequence;
|
||||
}
|
||||
|
||||
void WorldSession::CompleteNearTeleport(Player* plMover)
|
||||
{
|
||||
plMover->SetSemaphoreTeleportNear(false);
|
||||
|
||||
uint32 old_zone = plMover->GetZoneId();
|
||||
@@ -252,6 +270,12 @@ void WorldSession::HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck
|
||||
|
||||
WorldPackets::Movement::MoveUpdateTeleport moveUpdateTeleport;
|
||||
moveUpdateTeleport.Status = &plMover->m_movementInfo;
|
||||
// Real clients populate the movement GUID with their movement packets.
|
||||
// A clientless player may never have sent one; observers still need the
|
||||
// actual mover identity when a native chair/portal near-teleports them.
|
||||
moveUpdateTeleport.Status->guid = plMover->GetGUID();
|
||||
if (IsClientless())
|
||||
moveUpdateTeleport.Status->time = GameTime::GetGameTimeMS();
|
||||
moveUpdateTeleport.Status->pos.Relocate(dest);
|
||||
plMover->SendMessageToSet(moveUpdateTeleport.Write(), false);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ GridMap::GridMap()
|
||||
m_V9 = nullptr;
|
||||
m_V8 = nullptr;
|
||||
_minHeightPlanes = nullptr;
|
||||
_maxHeightPlanes = nullptr;
|
||||
// Liquid data
|
||||
_liquidGlobalEntry = 0;
|
||||
_liquidGlobalFlags = map_liquidHeaderTypeFlags::NoWater;
|
||||
@@ -123,6 +124,7 @@ void GridMap::unloadData()
|
||||
delete[] m_V9;
|
||||
delete[] m_V8;
|
||||
delete[] _minHeightPlanes;
|
||||
delete[] _maxHeightPlanes;
|
||||
delete[] _liquidEntry;
|
||||
delete[] _liquidFlags;
|
||||
delete[] _liquidMap;
|
||||
@@ -131,6 +133,7 @@ void GridMap::unloadData()
|
||||
m_V9 = nullptr;
|
||||
m_V8 = nullptr;
|
||||
_minHeightPlanes = nullptr;
|
||||
_maxHeightPlanes = nullptr;
|
||||
_liquidEntry = nullptr;
|
||||
_liquidFlags = nullptr;
|
||||
_liquidMap = nullptr;
|
||||
@@ -233,6 +236,13 @@ bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/)
|
||||
{ -533.33331f, -533.33331f }
|
||||
};
|
||||
|
||||
_maxHeightPlanes = new G3D::Plane[8];
|
||||
for (uint32 quarterIndex = 0; quarterIndex < 8; ++quarterIndex)
|
||||
_maxHeightPlanes[quarterIndex] = G3D::Plane(
|
||||
G3D::Vector3(boundGridCoords[indices[quarterIndex][0]][0], boundGridCoords[indices[quarterIndex][0]][1], maxHeights[indices[quarterIndex][0]]),
|
||||
G3D::Vector3(boundGridCoords[indices[quarterIndex][1]][0], boundGridCoords[indices[quarterIndex][1]][1], maxHeights[indices[quarterIndex][1]]),
|
||||
G3D::Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], maxHeights[indices[quarterIndex][2]])
|
||||
);
|
||||
_minHeightPlanes = new G3D::Plane[8];
|
||||
for (uint32 quarterIndex = 0; quarterIndex < 8; ++quarterIndex)
|
||||
_minHeightPlanes[quarterIndex] = G3D::Plane(
|
||||
@@ -565,6 +575,36 @@ float GridMap::getMinHeight(float x, float y) const
|
||||
return ray.intersection(_minHeightPlanes[quarterIndex]).z;
|
||||
}
|
||||
|
||||
float GridMap::getMaxHeight(float x, float y) const
|
||||
{
|
||||
if (!_maxHeightPlanes)
|
||||
return INVALID_HEIGHT;
|
||||
|
||||
GridCoord gridCoord = Trinity::ComputeGridCoordSimple(x, y);
|
||||
|
||||
int32 doubleGridX = int32(std::floor(-(x - MAP_HALFSIZE) / CENTER_GRID_OFFSET));
|
||||
int32 doubleGridY = int32(std::floor(-(y - MAP_HALFSIZE) / CENTER_GRID_OFFSET));
|
||||
|
||||
float gx = x - (int32(gridCoord.x_coord) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS;
|
||||
float gy = y - (int32(gridCoord.y_coord) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS;
|
||||
|
||||
uint32 quarterIndex = 0;
|
||||
if (doubleGridY & 1)
|
||||
{
|
||||
if (doubleGridX & 1)
|
||||
quarterIndex = 4 + (gx <= gy);
|
||||
else
|
||||
quarterIndex = 2 + ((-SIZE_OF_GRIDS - gx) > gy);
|
||||
}
|
||||
else if (doubleGridX & 1)
|
||||
quarterIndex = 6 + ((-SIZE_OF_GRIDS - gx) <= gy);
|
||||
else
|
||||
quarterIndex = gx > gy;
|
||||
|
||||
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(G3D::Vector3(gx, gy, 0.0f), G3D::Vector3::unitZ());
|
||||
return ray.intersection(_maxHeightPlanes[quarterIndex]).z;
|
||||
}
|
||||
|
||||
bool GridMap::isHole(int row, int col) const
|
||||
{
|
||||
if (!_holes)
|
||||
|
||||
@@ -42,6 +42,7 @@ class TC_GAME_API GridMap
|
||||
uint8* m_uint8_V8;
|
||||
};
|
||||
G3D::Plane* _minHeightPlanes;
|
||||
G3D::Plane* _maxHeightPlanes;
|
||||
// Height level data
|
||||
float _gridHeight;
|
||||
float _gridIntHeightMultiplier;
|
||||
@@ -95,6 +96,7 @@ public:
|
||||
uint16 getArea(float x, float y) const;
|
||||
inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);}
|
||||
float getMinHeight(float x, float y) const;
|
||||
float getMaxHeight(float x, float y) const;
|
||||
float getLiquidLevel(float x, float y) const;
|
||||
ZLiquidStatus GetLiquidStatus(float x, float y, float z, Optional<map_liquidHeaderTypeFlags> ReqLiquidType, LiquidData* data = 0, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h
|
||||
};
|
||||
|
||||
@@ -116,6 +116,27 @@ void Map::LoadAllCells()
|
||||
LoadGrid((cellX + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL, (cellY + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL);
|
||||
}
|
||||
|
||||
void Map::LoadTransportGameObjectGrids()
|
||||
{
|
||||
auto spawns = sObjectMgr->GetTransportGameObjectSpawns(GetId());
|
||||
if (!spawns)
|
||||
return;
|
||||
|
||||
uint32 grids = 0;
|
||||
for (ObjectGuid::LowType spawnId : *spawns)
|
||||
{
|
||||
GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);
|
||||
if (!data || data->mapId != GetId() || !(data->spawnMask & (1u << GetSpawnMode())))
|
||||
continue;
|
||||
// Use the normal loader: respawns, pools, phases and spawn groups retain
|
||||
// their existing rules. Loading an already loaded grid is idempotent.
|
||||
if (EnsureGridLoaded(Cell(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY())))
|
||||
++grids;
|
||||
}
|
||||
TC_LOG_INFO("server.loading", "Initialized transport GameObject grids: map=%u instance=%u grids=%u candidates=%u",
|
||||
GetId(), GetInstanceId(), grids, uint32(spawns->size()));
|
||||
}
|
||||
|
||||
void Map::InitStateMachine()
|
||||
{
|
||||
si_GridStates[GRID_STATE_INVALID] = new InvalidState();
|
||||
|
||||
@@ -218,6 +218,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
void SetUnloadLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
|
||||
void LoadGrid(float x, float y);
|
||||
void LoadAllCells();
|
||||
void LoadTransportGameObjectGrids();
|
||||
bool UnloadGrid(NGridType& ngrid, bool pForce);
|
||||
void GridMarkNoUnload(uint32 x, uint32 y);
|
||||
void GridUnmarkNoUnload(uint32 x, uint32 y);
|
||||
|
||||
@@ -74,6 +74,8 @@ Map* MapManager::CreateWorldMap(uint32 mapId, uint32 instanceId)
|
||||
map->LoadRespawnTimes();
|
||||
map->LoadCorpseData();
|
||||
|
||||
map->LoadTransportGameObjectGrids();
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS))
|
||||
map->LoadAllCells();
|
||||
|
||||
@@ -104,6 +106,8 @@ InstanceMap* MapManager::CreateInstance(uint32 mapId, uint32 instanceId, Instanc
|
||||
bool load_data = save != nullptr;
|
||||
map->CreateInstanceData(load_data);
|
||||
|
||||
map->LoadTransportGameObjectGrids();
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
|
||||
map->LoadAllCells();
|
||||
|
||||
@@ -118,6 +122,7 @@ BattlegroundMap* MapManager::CreateBattleground(uint32 mapId, uint32 instanceId,
|
||||
ASSERT(map->IsBattlegroundOrArena());
|
||||
map->SetBG(bg);
|
||||
bg->SetBgMap(map);
|
||||
map->LoadTransportGameObjectGrids();
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -657,6 +657,14 @@ float TerrainInfo::GetMinHeight(PhaseShift const& phaseShift, uint32 mapId, floa
|
||||
return -500.0f;
|
||||
}
|
||||
|
||||
float TerrainInfo::GetMaxHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y)
|
||||
{
|
||||
if (GridMap const* grid = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
|
||||
return grid->getMaxHeight(x, y);
|
||||
|
||||
return VMAP_INVALID_HEIGHT_VALUE;
|
||||
}
|
||||
|
||||
float TerrainInfo::GetGridHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y)
|
||||
{
|
||||
if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32 mapId, uint32& zoneid, uint32& areaid, Position const& pos) { GetZoneAndAreaId(phaseShift, mapId, zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
|
||||
|
||||
float GetMinHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y);
|
||||
float GetMaxHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y);
|
||||
float GetGridHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y);
|
||||
float GetStaticHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH);
|
||||
float GetStaticHeight(PhaseShift const& phaseShift, uint32 mapId, Position const& pos, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) { return GetStaticHeight(phaseShift, mapId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), checkVMap, maxSearchDist); }
|
||||
|
||||
@@ -62,15 +62,15 @@ inline float GetVelocity(Unit* owner, Unit* target, bool catchUp)
|
||||
{
|
||||
float targetSpeed = 0.f;
|
||||
float velocity = 0.f;
|
||||
if (target->IsPlayer())
|
||||
// Server-driven player splines can select a gait/velocity without changing
|
||||
// MOVEMENTFLAG_WALKING (MoveSplineInit::SetWalk). Follow the actual motion,
|
||||
// just as for creatures, rather than predicting a running player ahead.
|
||||
if (!target->movespline->Finalized())
|
||||
targetSpeed = target->movespline->Velocity();
|
||||
else if (target->IsPlayer())
|
||||
targetSpeed = target->GetSpeed(SelectSpeedType(target->m_movementInfo.GetMovementFlags()));
|
||||
else
|
||||
{
|
||||
if (!target->movespline->Finalized())
|
||||
targetSpeed = target->movespline->Velocity();
|
||||
else
|
||||
targetSpeed = target->GetSpeed(MOVE_RUN);
|
||||
}
|
||||
targetSpeed = target->GetSpeed(MOVE_RUN);
|
||||
|
||||
if (catchUp)
|
||||
velocity = targetSpeed;
|
||||
|
||||
@@ -30,6 +30,121 @@
|
||||
#include "Metric.h"
|
||||
#include "PhasingHandler.h"
|
||||
|
||||
// VCORE_POSITION_MMAP_BEGIN
|
||||
VcorePositionPathResult PathGenerator::AnalyzePositions(uint32 meshMapId, uint32 instanceMapId,
|
||||
uint32 instanceId, Position const& start, Position const& destination, uint16 includeFlags)
|
||||
{
|
||||
VcorePositionPathResult result;
|
||||
G3D::Vector3 const startPos(start.GetPositionX(), start.GetPositionY(), start.GetPositionZ());
|
||||
G3D::Vector3 const endPos(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
result.DirectDistance = (endPos - startPos).length();
|
||||
result.FinalDistance = result.DirectDistance;
|
||||
|
||||
if (!Trinity::IsValidMapCoord(startPos.x, startPos.y, startPos.z) ||
|
||||
!Trinity::IsValidMapCoord(endPos.x, endPos.y, endPos.z) || !includeFlags)
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::InvalidCoordinates;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!DisableMgr::IsPathfindingEnabled(meshMapId))
|
||||
return result; // NavMeshUnavailable
|
||||
|
||||
MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager();
|
||||
dtNavMeshQuery const* query = manager->GetNavMeshQuery(meshMapId, instanceMapId, instanceId);
|
||||
dtNavMesh const* mesh = query ? query->getAttachedNavMesh() : nullptr;
|
||||
if (!query || !mesh)
|
||||
return result;
|
||||
|
||||
// Detour uses Y,Z,X; world coordinates use X,Y,Z.
|
||||
float const from[3] = {startPos.y, startPos.z, startPos.x};
|
||||
float const to[3] = {endPos.y, endPos.z, endPos.x};
|
||||
for (float const* point : {from, to})
|
||||
{
|
||||
int tileX = -1, tileY = -1;
|
||||
mesh->calcTileLoc(point, &tileX, &tileY);
|
||||
if (tileX < 0 || tileY < 0 || !mesh->getTileAt(tileX, tileY, 0))
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::TileUnavailable;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
dtQueryFilter filter;
|
||||
filter.setIncludeFlags(includeFlags);
|
||||
filter.setExcludeFlags(0);
|
||||
float const extents[3] = {3.0f, 5.0f, 3.0f};
|
||||
float nearestStart[3] = {}, nearestEnd[3] = {};
|
||||
dtPolyRef startPoly = 0, endPoly = 0;
|
||||
if (dtStatusFailed(query->findNearestPoly(from, extents, &filter, &startPoly, nearestStart)) ||
|
||||
dtStatusFailed(query->findNearestPoly(to, extents, &filter, &endPoly, nearestEnd)) ||
|
||||
!startPoly || !endPoly)
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::NoPolygon;
|
||||
return result;
|
||||
}
|
||||
|
||||
// A distant projection is not proof that the requested world point is walkable.
|
||||
if (dtVdist(from, nearestStart) > 3.0f || dtVdist(to, nearestEnd) > 3.0f)
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::NoPolygon;
|
||||
return result;
|
||||
}
|
||||
|
||||
dtPolyRef polys[MAX_PATH_LENGTH] = {};
|
||||
int polyCount = 0;
|
||||
dtStatus const pathStatus = query->findPath(startPoly, endPoly, nearestStart, nearestEnd,
|
||||
&filter, polys, &polyCount, MAX_PATH_LENGTH);
|
||||
if (dtStatusFailed(pathStatus) || polyCount <= 0)
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::NoPath;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool const reachedEndPoly = polys[polyCount - 1] == endPoly;
|
||||
float reachableEnd[3] = {nearestEnd[0], nearestEnd[1], nearestEnd[2]};
|
||||
if (!reachedEndPoly &&
|
||||
dtStatusFailed(query->closestPointOnPoly(polys[polyCount - 1], nearestEnd, reachableEnd, nullptr)))
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::NoPath;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Use an explicit bounded straight-path representation, not a forced shortcut.
|
||||
constexpr int MaxPoints = 256;
|
||||
float straight[MaxPoints * 3] = {};
|
||||
int pointCount = 0;
|
||||
dtStatus const straightStatus = query->findStraightPath(nearestStart, reachableEnd, polys,
|
||||
polyCount, straight, nullptr, nullptr, &pointCount, MaxPoints);
|
||||
if (dtStatusFailed(straightStatus) || pointCount <= 0)
|
||||
{
|
||||
result.Result = VcorePositionPathResult::Status::NoPath;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.Points.reserve(pointCount);
|
||||
for (int i = 0; i < pointCount; ++i)
|
||||
{
|
||||
G3D::Vector3 const p(straight[i * 3 + 2], straight[i * 3], straight[i * 3 + 1]);
|
||||
if (!result.Points.empty())
|
||||
result.PathLength += (p - result.Points.back()).length();
|
||||
result.Points.push_back(p);
|
||||
}
|
||||
result.FinalDistance = (endPos - result.Points.back()).length();
|
||||
|
||||
bool const truncated = (pathStatus & DT_BUFFER_TOO_SMALL) ||
|
||||
(straightStatus & DT_BUFFER_TOO_SMALL) || pointCount >= MaxPoints ||
|
||||
polyCount >= MAX_PATH_LENGTH;
|
||||
if (truncated)
|
||||
result.Result = VcorePositionPathResult::Status::Truncated;
|
||||
else if (reachedEndPoly && result.FinalDistance <= 1.5f)
|
||||
result.Result = VcorePositionPathResult::Status::Complete;
|
||||
else
|
||||
result.Result = VcorePositionPathResult::Status::Partial;
|
||||
return result;
|
||||
}
|
||||
// VCORE_POSITION_MMAP_END
|
||||
|
||||
////////////////// PathGenerator //////////////////
|
||||
PathGenerator::PathGenerator(WorldObject const* owner) :
|
||||
_polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false),
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "MMapDefines.h"
|
||||
#include "MoveSplineInitArgs.h"
|
||||
#include <G3D/Vector3.h>
|
||||
#include <vector>
|
||||
|
||||
class Unit;
|
||||
class WorldObject;
|
||||
@@ -54,6 +55,34 @@ enum PathType
|
||||
PATHFIND_FARFROMPOLY = PATHFIND_FARFROMPOLY_START | PATHFIND_FARFROMPOLY_END, // start or end positions are far from the mmap poligon
|
||||
};
|
||||
|
||||
// VCORE_POSITION_MMAP_BEGIN
|
||||
// Ground-only navmesh probe without a Player or WorldObject.
|
||||
// meshMapId may differ from instanceMapId for phased/terrain-swapped maps.
|
||||
// The caller must run this on the map/world thread that owns the navmesh query.
|
||||
struct VcorePositionPathResult
|
||||
{
|
||||
enum class Status : uint8
|
||||
{
|
||||
InvalidCoordinates,
|
||||
NavMeshUnavailable,
|
||||
TileUnavailable,
|
||||
NoPolygon,
|
||||
NoPath,
|
||||
Partial,
|
||||
Complete,
|
||||
Truncated
|
||||
};
|
||||
|
||||
Status Result = Status::NavMeshUnavailable;
|
||||
float DirectDistance = 0.0f;
|
||||
float PathLength = 0.0f;
|
||||
float FinalDistance = 0.0f;
|
||||
std::vector<G3D::Vector3> Points;
|
||||
|
||||
bool IsComplete() const { return Result == Status::Complete; }
|
||||
};
|
||||
// VCORE_POSITION_MMAP_END
|
||||
|
||||
class TC_GAME_API PathGenerator
|
||||
{
|
||||
public:
|
||||
@@ -65,7 +94,13 @@ class TC_GAME_API PathGenerator
|
||||
PathGenerator& operator=(PathGenerator const& right) = delete;
|
||||
PathGenerator& operator=(PathGenerator&& right) = delete;
|
||||
|
||||
// Calculate the path from owner to given destination
|
||||
// Vcore: query loaded MMAP data between arbitrary coordinates; no character required.
|
||||
// The result describes ground navmesh reachability, not dynamic world collision.
|
||||
static VcorePositionPathResult AnalyzePositions(uint32 meshMapId, uint32 instanceMapId,
|
||||
uint32 instanceId, Position const& start, Position const& destination,
|
||||
uint16 includeFlags = NAV_GROUND);
|
||||
|
||||
// Calculate the path from owner to given destination
|
||||
// return: true if new path was calculated, false otherwise (no change needed)
|
||||
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false);
|
||||
bool CalculatePath(Position const& destination, bool forceDest = false);
|
||||
|
||||
@@ -108,12 +108,14 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
|
||||
}
|
||||
|
||||
/// WorldSession constructor
|
||||
WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter) :
|
||||
WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter, WorldSession::WorldSessionMode sessionMode) :
|
||||
m_muteTime(mute_time),
|
||||
m_timeOutTime(0),
|
||||
AntiDOS(this),
|
||||
m_GUIDLow(0),
|
||||
_player(nullptr),
|
||||
_sessionMode(sessionMode),
|
||||
_clientlessPendingPlayerGuid(),
|
||||
_security(sec),
|
||||
_accountId(id),
|
||||
_accountName(std::move(name)),
|
||||
@@ -147,12 +149,18 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
|
||||
_timeSyncNextCounter = 0;
|
||||
_timeSyncTimer = 0;
|
||||
|
||||
if (sock)
|
||||
if (IsNetworkSession() && sock)
|
||||
{
|
||||
m_Address = sock->GetRemoteIpAddress().to_string();
|
||||
ResetTimeOutTime(false);
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
|
||||
}
|
||||
else if (IsClientless())
|
||||
{
|
||||
// Clientless sessions deliberately have no remote endpoint.
|
||||
// Keep a stable diagnostic value for logs that include GetRemoteAddress().
|
||||
m_Address = "<clientless>";
|
||||
}
|
||||
|
||||
m_Socket[CONNECTION_TYPE_REALM] = sock;
|
||||
_instanceConnectKey.Raw = UI64LIT(0);
|
||||
@@ -185,7 +193,8 @@ WorldSession::~WorldSession()
|
||||
while (_recvQueue.next(packet))
|
||||
delete packet;
|
||||
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query
|
||||
if (IsNetworkSession())
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query
|
||||
}
|
||||
|
||||
bool WorldSession::PlayerDisconnected() const
|
||||
@@ -223,6 +232,12 @@ ObjectGuid::LowType WorldSession::GetGUIDLow() const
|
||||
/// Send a packet to the client
|
||||
void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/)
|
||||
{
|
||||
// A clientless session intentionally has no packet transport. Outbound
|
||||
// packets are a normal side effect of Player/Core code and are discarded
|
||||
// without producing "non existent socket" errors.
|
||||
if (IsClientless())
|
||||
return;
|
||||
|
||||
if (packet->GetOpcode() == NULL_OPCODE)
|
||||
{
|
||||
TC_LOG_ERROR("network.opcode", "Prevented sending of NULL_OPCODE to %s", GetPlayerInfo().c_str());
|
||||
@@ -340,13 +355,16 @@ void WorldSession::LogUnprocessedTail(WorldPacket const* packet)
|
||||
/// Update the WorldSession (triggered by World update)
|
||||
bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
{
|
||||
/// Update Timeout timer.
|
||||
UpdateTimeOutTime(diff);
|
||||
if (IsNetworkSession())
|
||||
{
|
||||
/// Update Timeout timer.
|
||||
UpdateTimeOutTime(diff);
|
||||
|
||||
///- Before we process anything:
|
||||
/// If necessary, kick the player from the character select screen
|
||||
if (IsConnectionIdle() && !HasPermission(rbac::RBAC_PERM_IGNORE_IDLE_CONNECTION))
|
||||
m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
|
||||
///- Before we process anything:
|
||||
/// If necessary, kick the player from the character select screen
|
||||
if (IsConnectionIdle() && !HasPermission(rbac::RBAC_PERM_IGNORE_IDLE_CONNECTION) && m_Socket[CONNECTION_TYPE_REALM])
|
||||
m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
|
||||
}
|
||||
|
||||
///- Retrieve packets from the receive queue and call the appropriate handlers
|
||||
/// not process packets if socket already closed
|
||||
@@ -478,7 +496,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
if (m_Socket[0] && m_Socket[0]->IsOpen() && _warden)
|
||||
_warden->Update();
|
||||
|
||||
if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
|
||||
if (IsNetworkSession() && !updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
|
||||
{
|
||||
// Send time sync packet every 5s.
|
||||
if (_timeSyncTimer > 0)
|
||||
@@ -523,8 +541,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_Socket[CONNECTION_TYPE_REALM])
|
||||
return false; //Will remove this session from the world session map
|
||||
if (IsNetworkSession() && !m_Socket[CONNECTION_TYPE_REALM])
|
||||
return false; // Will remove this network session from the world session map
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1244,20 +1262,36 @@ void WorldSession::InitializeSession()
|
||||
|
||||
void WorldSession::InitializeSessionCallback(CharacterDatabaseQueryHolder const& realmHolder)
|
||||
{
|
||||
// Shared session/account state used by both Network and Clientless players.
|
||||
LoadAccountData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::GLOBAL_ACCOUNT_DATA), GLOBAL_CACHE_MASK);
|
||||
LoadTutorialsData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS));
|
||||
|
||||
if (!m_inQueue)
|
||||
SendAuthResponse(AUTH_OK, false);
|
||||
else
|
||||
SendAuthWaitQue(0);
|
||||
if (IsNetworkSession())
|
||||
{
|
||||
if (!m_inQueue)
|
||||
SendAuthResponse(AUTH_OK, false);
|
||||
else
|
||||
SendAuthWaitQue(0);
|
||||
|
||||
ResetTimeOutTime(false);
|
||||
|
||||
SendAddonsInfo();
|
||||
SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
|
||||
SendTutorialsData();
|
||||
}
|
||||
|
||||
SetInQueue(false);
|
||||
ResetTimeOutTime(false);
|
||||
|
||||
SendAddonsInfo();
|
||||
SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
|
||||
SendTutorialsData();
|
||||
if (IsClientless() && !_clientlessPendingPlayerGuid.IsEmpty())
|
||||
{
|
||||
ObjectGuid playerGuid = _clientlessPendingPlayerGuid;
|
||||
_clientlessPendingPlayerGuid.Clear();
|
||||
|
||||
if (!BeginClientlessPlayerLogin(playerGuid))
|
||||
TC_LOG_ERROR("server.worldserver",
|
||||
"WorldSession::InitializeSessionCallback failed to continue clientless login for account %u, character GUID %u.",
|
||||
GetAccountId(), uint32(playerGuid.GetCounter()));
|
||||
}
|
||||
}
|
||||
|
||||
rbac::RBACData* WorldSession::GetRBACData()
|
||||
|
||||
@@ -475,7 +475,14 @@ struct PacketCounter
|
||||
class TC_GAME_API WorldSession
|
||||
{
|
||||
public:
|
||||
WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
|
||||
enum class WorldSessionMode : uint8
|
||||
{
|
||||
Network,
|
||||
Clientless
|
||||
};
|
||||
|
||||
WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter,
|
||||
WorldSessionMode sessionMode = WorldSessionMode::Network);
|
||||
~WorldSession();
|
||||
|
||||
bool PlayerLoading() const { return !m_playerLoading.IsEmpty(); }
|
||||
@@ -513,6 +520,10 @@ class TC_GAME_API WorldSession
|
||||
|
||||
AccountTypes GetSecurity() const { return _security; }
|
||||
uint32 GetAccountId() const { return _accountId; }
|
||||
WorldSessionMode GetSessionMode() const { return _sessionMode; }
|
||||
bool IsNetworkSession() const { return _sessionMode == WorldSessionMode::Network; }
|
||||
bool IsClientless() const { return _sessionMode == WorldSessionMode::Clientless; }
|
||||
bool HasNetworkTransport() const { return m_Socket[CONNECTION_TYPE_REALM] != nullptr; }
|
||||
Player* GetPlayer() const { return _player; }
|
||||
std::string const& GetPlayerName() const;
|
||||
std::string GetPlayerInfo() const;
|
||||
@@ -676,6 +687,20 @@ class TC_GAME_API WorldSession
|
||||
void HandleCharCreateOpcode(WorldPacket& recvPacket);
|
||||
void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& packet);
|
||||
|
||||
// Initializes shared account/session state and then starts the normal
|
||||
// Player DB-load/login pipeline for a registered Clientless session.
|
||||
bool InitializeClientlessPlayer(ObjectGuid playerGuid);
|
||||
bool HasPendingClientlessPlayerLogin() const
|
||||
{
|
||||
return IsClientless() && (!_clientlessPendingPlayerGuid.IsEmpty() || PlayerLoading());
|
||||
}
|
||||
|
||||
// Starts the normal Player DB-load/login pipeline without relying on
|
||||
// client character-enumeration state or a network login opcode.
|
||||
// The WorldSession must already be a registered Clientless session
|
||||
// with the correct account context.
|
||||
bool BeginClientlessPlayerLogin(ObjectGuid playerGuid);
|
||||
|
||||
void SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial);
|
||||
void HandleContinuePlayerLogin();
|
||||
void AbortLogin(WorldPackets::Character::LoginFailureReason reason);
|
||||
@@ -718,6 +743,8 @@ class TC_GAME_API WorldSession
|
||||
void HandleForceSpeedChangeAck(WorldPacket& recvData);
|
||||
void HandleMoveKnockBackAck(WorldPacket& recvPacket);
|
||||
void HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck& packet);
|
||||
void CompleteClientlessTeleport();
|
||||
uint64 GetClientlessTeleportSequence() const { return _clientlessTeleportSequence; }
|
||||
void HandleMoveWaterWalkAck(WorldPacket& recvPacket);
|
||||
void HandleFeatherFallAck(WorldPacket& recvData);
|
||||
void HandleMoveHoverAck(WorldPacket& recvData);
|
||||
@@ -1293,6 +1320,7 @@ class TC_GAME_API WorldSession
|
||||
void SendLoadCUFProfiles();
|
||||
|
||||
private:
|
||||
void CompleteNearTeleport(Player* playerMover);
|
||||
void ProcessQueryCallbacks();
|
||||
|
||||
QueryCallbackProcessor _queryProcessor;
|
||||
@@ -1353,6 +1381,9 @@ class TC_GAME_API WorldSession
|
||||
|
||||
ObjectGuid::LowType m_GUIDLow; // set logined or recently logout player (while m_playerRecentlyLogout set)
|
||||
Player* _player;
|
||||
WorldSessionMode _sessionMode;
|
||||
ObjectGuid _clientlessPendingPlayerGuid;
|
||||
uint64 _clientlessTeleportSequence = 0;
|
||||
std::shared_ptr<WorldSocket> m_Socket[2];
|
||||
std::string m_Address; // Current Remote Address
|
||||
// std::string m_LAddress; // Last Attempted Remote Adress - we can not set attempted ip for a non-existing session!
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,109 @@
|
||||
#ifndef VCORE_ADVENTURE_BEHAVIOR_MGR_H
|
||||
#define VCORE_ADVENTURE_BEHAVIOR_MGR_H
|
||||
#include "Common.h"
|
||||
#include "Position.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "AdventureBehaviorPolicy.h"
|
||||
#include "AdventureSocialActions.h"
|
||||
#include "AdventureInstancePolicy.h"
|
||||
#include "ClientlessCompanionMgr.h"
|
||||
#include <ctime>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
class Player;
|
||||
class ChatHandler;
|
||||
class GameObject;
|
||||
struct ClientlessIntent;
|
||||
struct AdventureLocation;
|
||||
struct AdventureMicroAction;
|
||||
struct ClientlessAdventureProfile;
|
||||
|
||||
class TC_GAME_API AdventureBehaviorMgr
|
||||
{
|
||||
public:
|
||||
static AdventureBehaviorMgr* instance();
|
||||
void Online(Player* player);
|
||||
void Offline(Player* player);
|
||||
void IntentChanged(Player* player, ClientlessIntent const* intent);
|
||||
void Update(Player* player, uint32 diff);
|
||||
bool Command(ChatHandler* handler, char const* args);
|
||||
void InterruptForCombat(Player* player);
|
||||
std::string CombatIntent(Player* player) const;
|
||||
private:
|
||||
enum class Phase {Idle, Travel, OnSite, Switching, Handover};
|
||||
struct RecoveryScene
|
||||
{
|
||||
bool Active=false, Approaching=false;
|
||||
std::string Point, Posture;
|
||||
uint32 Remaining=0, ApproachElapsed=0;
|
||||
Position Destination;
|
||||
bool HasDestination=false;
|
||||
uint32 SpaceCheckMs=0;
|
||||
};
|
||||
struct Record
|
||||
{
|
||||
bool Enabled=false, Schedule=false, Publishing=false, Queued=false, Dirty=true;
|
||||
Phase State=Phase::Idle;
|
||||
std::string Intent, Location, WantedIntent, WantedLocation, Detail, Micro;
|
||||
time_t Deadline=0;
|
||||
uint32 Date=0, Timer=0, MicroTimer=0, GestureTimer=0, RetryTimer=0;
|
||||
int Hour=-1;
|
||||
AdventureBehaviorPolicy::Day Plan;
|
||||
std::mt19937 Random;
|
||||
std::deque<std::string> ActionHistory, VariantHistory;
|
||||
std::deque<std::string> TargetHistory;
|
||||
AdventureSocialScene Social;
|
||||
AdventureInstancePolicy::Visit Instance;
|
||||
RecoveryScene Recovery;
|
||||
struct LeisureScene
|
||||
{
|
||||
bool Active=false, Flying=false, Moving=false, StopRequested=false, Returning=false, PlannedWalk=false, Progressive=false;
|
||||
std::string Kind;
|
||||
Position Origin;
|
||||
std::vector<Position> Route, WalkTrace;
|
||||
std::size_t Step=0, OutboundSteps=0;
|
||||
uint32 Elapsed=0, LegElapsed=0, PauseMs=0, CompanionWait=0, CompletedLegs=0;
|
||||
ClientlessCompanionScene Companion;
|
||||
} Leisure;
|
||||
std::unordered_set<std::string> Tried;
|
||||
Position Anchor;
|
||||
uint32 AnchorMap=0;
|
||||
ObjectGuid WorkObject;
|
||||
uint32 WorkEmote=0;
|
||||
bool WorkPending=false;
|
||||
};
|
||||
bool ResolveInstance(Player* player, Record& record);
|
||||
bool SaveInstance(Player* player, Record& record);
|
||||
bool RestoreInstance(Player* player, Record& record);
|
||||
bool UpdateInstance(Player* player, Record& record, time_t now);
|
||||
void FinishInstance(Player* player, Record& record);
|
||||
void Generate(Player* player, Record& record, uint32 date);
|
||||
void SetWanted(Player* player, Record& record, std::string const& intent, std::string const& location, time_t deadline);
|
||||
void Begin(Player* player, Record& record);
|
||||
void Fallback(Player* player, Record& record);
|
||||
void Queue(Player* player, Record& record, std::string const& action, std::string const& parameter, std::string const& value, bool hard = false);
|
||||
void ResetMicro(Player* player, Record& record);
|
||||
void Micro(Player* player, Record& record);
|
||||
AdventureSocialContext SocialContext(Player* player, Record& record);
|
||||
bool UpdateSocial(Player* player, Record& record, uint32 diff);
|
||||
bool LocalMove(Player* player, Record& record, Position const& target, float maxPath, bool riding=false);
|
||||
bool ProfessionWorkAvailable(Player* player,Record& record);
|
||||
bool FishingDirection(Player* player,float& orientation) const;
|
||||
bool LeisureAvailable(Player* player, Record const& record, AdventureMicroAction const& action) const;
|
||||
bool PlanLeisureWalk(Player* player, Record& record);
|
||||
bool StartLeisure(Player* player, Record& record, AdventureMicroAction const& action);
|
||||
bool UpdateLeisure(Player* player, Record& record, uint32 diff);
|
||||
void ResetLeisure(Player* player, Record& record);
|
||||
bool RecoveryAvailable(Player* player, Record const& record, AdventureMicroAction const& action) const;
|
||||
bool StartRecovery(Player* player, Record& record, AdventureMicroAction const& action, uint32 duration);
|
||||
bool UpdateRecovery(Player* player, Record& record, uint32 diff);
|
||||
std::string AreaNode(Player* player, AdventureLocation const& location);
|
||||
std::string PickLocation(Player* player, Record& record, std::string const& intent);
|
||||
bool Allowed(Player* player, AdventureLocation const& location, std::string const& intent) const;
|
||||
static float Affinity(std::unordered_map<std::string,float> const& values, std::string const& key, float fallback);
|
||||
std::unordered_map<uint32,Record> _records;
|
||||
};
|
||||
#define sAdventureBehaviorMgr AdventureBehaviorMgr::instance()
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef VCORE_ADVENTURE_BEHAVIOR_POLICY_H
|
||||
#define VCORE_ADVENTURE_BEHAVIOR_POLICY_H
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace AdventureBehaviorPolicy
|
||||
{
|
||||
inline std::string Normalize(std::string text)
|
||||
{
|
||||
std::string result;
|
||||
for (unsigned char c : text)
|
||||
if (std::isalnum(c)) result += char(std::tolower(c));
|
||||
return result;
|
||||
}
|
||||
inline std::string Classify(std::string const& name)
|
||||
{
|
||||
auto text = Normalize(name);
|
||||
auto has = [&](char const* s) { return text.find(s) != std::string::npos; };
|
||||
if (has("tavern") || has("gasthaus") || has("taverne") || has("lionspride") || has("gildedrose") || (has("inn") && !has("pinnacle") && !has("binding") && !has("inner"))) return "tavern";
|
||||
if (has("deadmines") || has("dungeon") || has("dungeons")) return "dungeon";
|
||||
if (has("mine") || has("mining") || has("quarry") || has("steinbruch")) return "mine";
|
||||
if (has("forge") || has("smith") || has("anvil") || has("workshop") || has("schmiede")) return "workshop";
|
||||
if (has("bank")) return "bank";
|
||||
if (has("forest") || has("woods") || has("wald") || has("marsh") || has("swamp")) return "wilderness";
|
||||
if (has("ruin") || has("crypt") || has("tomb") || has("cave") || has("cavern")) return "ruins";
|
||||
if (has("village") || has("town") || has("camp") || has("settlement")) return "settlement";
|
||||
return "landmark";
|
||||
}
|
||||
inline double Novelty(std::deque<std::string> const& history, std::string const& key)
|
||||
{
|
||||
double weight = 1;
|
||||
for (std::size_t i = 0; i < history.size(); ++i)
|
||||
if (history[i] == key) weight *= i + 1 == history.size() ? 0.08 : 0.45;
|
||||
return weight;
|
||||
}
|
||||
inline void Remember(std::deque<std::string>& history, std::string key)
|
||||
{
|
||||
history.push_back(std::move(key));
|
||||
if (history.size() > 12) history.pop_front();
|
||||
}
|
||||
inline std::size_t Choose(std::vector<double> const& weights, std::mt19937& random)
|
||||
{
|
||||
if (weights.empty() || std::none_of(weights.begin(), weights.end(), [](double w) { return w > 0 && std::isfinite(w); })) return weights.size();
|
||||
return std::discrete_distribution<std::size_t>(weights.begin(), weights.end())(random);
|
||||
}
|
||||
struct Slot
|
||||
{
|
||||
std::string Intent, Location;
|
||||
};
|
||||
using Day = std::array<Slot, 24>;
|
||||
// Dependency-free generation kernel. Callers provide weighted intent/location selection.
|
||||
template<class IntentPicker, class LocationPicker>
|
||||
Day Generate(std::mt19937& random, float wanderlust, IntentPicker intent, LocationPicker location)
|
||||
{
|
||||
Day day;
|
||||
for (unsigned hour = 0; hour < 24; )
|
||||
{
|
||||
std::string chosen = intent();
|
||||
unsigned end = std::min(24u, hour + std::uniform_int_distribution<unsigned>(1, 4)(random));
|
||||
std::string target = location(chosen);
|
||||
for (unsigned h = hour; h < end; ++h)
|
||||
{
|
||||
if (h != hour && std::bernoulli_distribution(std::clamp(double(wanderlust), 0.0, 1.0))(random)) target = location(chosen);
|
||||
day[h] = {chosen, target};
|
||||
}
|
||||
hour = end;
|
||||
}
|
||||
return day;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,287 @@
|
||||
#include "AdventureCombatMgr.h"
|
||||
#include "AdventureCombatPolicy.h"
|
||||
#include "AdventureBehaviorMgr.h"
|
||||
#include "ClientlessLuaEngine.h"
|
||||
#include "ClientlessPlayerMgr.h"
|
||||
#include "ClientlessActionExecutorMgr.h"
|
||||
#include "ClientlessTravelMgr.h"
|
||||
#include "Creature.h"
|
||||
#include "Corpse.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerAI.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "Map.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "WorldSession.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Opcodes.h"
|
||||
#include "GameTime.h"
|
||||
#include "Log.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
// Native player spell checks, cooldowns, rage and autoattacks. No charmer/fake AI
|
||||
// installation and no generated resources or synthetic damage.
|
||||
class AdventureCombatMgr::Fighter : public PlayerAI
|
||||
{
|
||||
public:
|
||||
explicit Fighter(Player* player):PlayerAI(player) { }
|
||||
void UpdateAI(uint32) override { }
|
||||
void Tick(Creature* target,uint32 diff)
|
||||
{
|
||||
_rend=_rend>diff?_rend-diff:0;_filler=_filler>diff?_filler-diff:0;
|
||||
me->SetFacingToObject(target);
|
||||
if(me->HasUnitState(UNIT_STATE_CASTING))return;
|
||||
if(me->getClass()==CLASS_WARRIOR && !me->HasAura(2457) && Cast(2457,me))return;
|
||||
if(!me->IsWithinMeleeRange(target))return; // MMAP approach is owned by manager.
|
||||
if(me->GetVictim()!=target)me->Attack(target,true);
|
||||
DoAutoAttackIfReady();
|
||||
if(me->getClass()!=CLASS_WARRIOR)return;
|
||||
if(!me->HasAura(6673) && Cast(6673,me))return;
|
||||
if(Cast(12294,target))return;
|
||||
if(!_rend && !target->GetAuraApplicationOfRankedSpell(772,me->GetGUID()) && Cast(772,target))
|
||||
{_rend=12000;return;}
|
||||
if(!_filler)for(uint32 id:{7384u,1464u,78u})if(Cast(id,target)){_filler=3000;break;}
|
||||
}
|
||||
private:
|
||||
bool Cast(uint32 id,Unit* target)
|
||||
{
|
||||
auto cast=VerifySpellCast(id,target);if(!cast)return false;
|
||||
uint32 actual=cast.first->GetSpellInfo()->Id;
|
||||
SpellCastTargets targets;targets.SetUnitTarget(cast.second);
|
||||
auto result=cast.first->prepare(targets);
|
||||
if(result==SPELL_CAST_OK)TC_LOG_INFO("server.adventurebot","COMBAT_CAST guid=%u target='%s' spell=%u",me->GetGUID().GetCounter(),target->GetGUID().ToString().c_str(),actual);
|
||||
return result==SPELL_CAST_OK;
|
||||
}
|
||||
uint32 _rend=0,_filler=0;
|
||||
};
|
||||
AdventureCombatMgr* AdventureCombatMgr::instance(){static AdventureCombatMgr mgr;return &mgr;}
|
||||
bool AdventureCombatMgr::Valid(Player* p,Creature* c,bool training) const
|
||||
{
|
||||
return c && c->IsAlive() && c->IsInWorld() && p->IsInPhase(c) && p->CanSeeOrDetect(c) &&
|
||||
p->IsValidAttackTarget(c) && !c->GetControllingPlayer() && !c->IsEvadingAttacks() &&
|
||||
(training?(c->GetScriptName()=="npc_training_dummy" && c->getLevel()<=p->getLevel()+2 && !c->isWorldBoss()):c->GetScriptName()!="npc_training_dummy");
|
||||
}
|
||||
bool AdventureCombatMgr::Reachable(Player* p,Creature* c) const
|
||||
{
|
||||
if(!p->IsWithinLOSInMap(c))return false;
|
||||
if(p->IsWithinMeleeRange(c))return true;
|
||||
Position end;c->GetNearPoint(p,end.m_positionX,end.m_positionY,end.m_positionZ,0.5f,c->GetAngle(p));
|
||||
ClientlessPathDiagnostics path;
|
||||
return sClientlessTravelMgr->AnalyzePath(p,end,path) && path.Complete && !path.Suspicious && path.PathLength<=100;
|
||||
}
|
||||
bool AdventureCombatMgr::Safe(Player* p,Creature* c) const
|
||||
{
|
||||
if(!Valid(p,c,false) || p->GetExactDist(c)>40 || (c->GetVictim() && c->GetVictim()!=p))return false;
|
||||
std::vector<Creature*> others;p->GetCreatureListWithEntryInGrid(others,0,35);
|
||||
unsigned hostiles=0;
|
||||
for(auto other:others)if(other->IsAlive() && p->IsInPhase(other) && p->IsHostileTo(other) &&
|
||||
other->GetExactDist(c)<12 && !other->GetControllingPlayer())++hostiles;
|
||||
// Include neutral quarry itself in the risk count.
|
||||
if(!p->IsHostileTo(c))++hostiles;
|
||||
auto maxMana=p->GetMaxPower(POWER_MANA);
|
||||
return AdventureCombatPolicy::SafeFirstAttack(p->getLevel(),c->getLevel(),p->GetHealthPct(),
|
||||
c->isElite(),c->isWorldBoss(),hostiles,p->GetPowerType()==POWER_MANA,
|
||||
maxMana?100.0f*p->GetPower(POWER_MANA)/maxMana:0) && Reachable(p,c);
|
||||
}
|
||||
Creature* AdventureCombatMgr::Dummy(Player* p) const
|
||||
{
|
||||
if(!p->IsAlive() || p->IsInCombat() || p->GetTransport() || p->IsInFlight() || p->IsBeingTeleported())return nullptr;
|
||||
Creature* best=nullptr;std::vector<Creature*> all;p->GetCreatureListWithEntryInGrid(all,0,60);
|
||||
for(auto c:all)if(Valid(p,c,true) && (!best || p->GetExactDist(c)<p->GetExactDist(best)) && Reachable(p,c))best=c;
|
||||
return best;
|
||||
}
|
||||
bool AdventureCombatMgr::TrainingAvailable(Player* p) const{return Dummy(p)!=nullptr;}
|
||||
bool AdventureCombatMgr::Start(Player* p,Record& r,Creature* c,bool training,bool defending,time_t until)
|
||||
{
|
||||
if(!Valid(p,c,training) || !p->IsAlive() || p->IsBeingTeleported() || p->GetTransport() || p->IsInFlight() || p->IsCharmed())return false;
|
||||
sAdventureBehaviorMgr->InterruptForCombat(p);
|
||||
sClientlessLuaEngine->DismountGroundMount(p,"combat-start");
|
||||
p->AttackStop();p->CastStop();p->StopMoving();p->GetMotionMaster()->Clear();p->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
r.AI=std::make_shared<Fighter>(p);r.Target=c->GetGUID();r.Training=training;r.Defending=defending;
|
||||
r.Suspended=true;r.Until=until;r.Timer=0;r.UnreachableMs=0;
|
||||
p->SetSelection(c->GetGUID());
|
||||
TC_LOG_INFO("server.adventurebot","COMBAT_START guid=%u target='%s' training=%u defending=%u until=%llu",p->GetGUID().GetCounter(),c->GetGUID().ToString().c_str(),training,defending,static_cast<unsigned long long>(until));
|
||||
return true;
|
||||
}
|
||||
bool AdventureCombatMgr::Train(Player* p,uint32 durationMs,time_t deadline)
|
||||
{
|
||||
auto c=Dummy(p);if(!c)return false;
|
||||
auto now=GameTime::GetGameTime();auto until=now+std::max(10u,std::min(durationMs/1000,180u));
|
||||
if(deadline && deadline<until)until=deadline;
|
||||
if(until<=now)return false;
|
||||
return Start(p,_records[p->GetGUID().GetCounter()],c,true,false,until);
|
||||
}
|
||||
bool AdventureCombatMgr::Attack(Player* p,uint32 spawn)
|
||||
{
|
||||
auto c=p->GetMap()->GetCreatureBySpawnId(spawn);
|
||||
return !p->IsInCombat() && Safe(p,c) && Start(p,_records[p->GetGUID().GetCounter()],c,false,false,0);
|
||||
}
|
||||
void AdventureCombatMgr::DamageTaken(Player* p,Unit* attacker,uint32 damage)
|
||||
{
|
||||
auto c=attacker?attacker->ToCreature():nullptr;
|
||||
if(!damage || !p->IsAlive() || !c || c->GetControllingPlayer())return;
|
||||
auto& r=_records[p->GetGUID().GetCounter()];
|
||||
if(std::find(r.Damagers.begin(),r.Damagers.end(),c->GetGUID())==r.Damagers.end())r.Damagers.push_back(c->GetGUID());
|
||||
}
|
||||
void AdventureCombatMgr::Finish(Player* p,Record& r)
|
||||
{
|
||||
TC_LOG_INFO("server.adventurebot","COMBAT_END guid=%u target='%s' training=%u",p->GetGUID().GetCounter(),r.Target.ToString().c_str(),r.Training);
|
||||
bool training=r.Training;
|
||||
p->AttackStop();p->CastStop();p->StopMoving();p->GetMotionMaster()->Clear();p->SetSelection(ObjectGuid::Empty);
|
||||
sClientlessTravelMgr->CancelTravel(p->GetGUID().GetCounter());
|
||||
if(training && std::all_of(p->getAttackers().begin(),p->getAttackers().end(),[](Unit* u)
|
||||
{auto c=u->ToCreature();return c && c->GetScriptName()=="npc_training_dummy";}))p->CombatStop(true); // Only the bounded dummy scene may end its own combat.
|
||||
r.AI.reset();r.Target.Clear();r.Training=false;r.Defending=false;r.UnreachableMs=0;r.Cooldown=10000;
|
||||
}
|
||||
void AdventureCombatMgr::Stop(Player* p)
|
||||
{
|
||||
auto it=_records.find(p->GetGUID().GetCounter());if(it!=_records.end())Finish(p,it->second);
|
||||
}
|
||||
void AdventureCombatMgr::Offline(Player* p){_records.erase(p->GetGUID().GetCounter());}
|
||||
Creature* AdventureCombatMgr::Proactive(Player* p) const
|
||||
{
|
||||
auto intent=sAdventureBehaviorMgr->CombatIntent(p);
|
||||
if(intent!="adventure" && intent!="profession")return nullptr;
|
||||
auto profile=sClientlessLuaEngine->GetAdventureProfile(p->GetGUID().GetCounter());
|
||||
if(intent=="profession" && (!profile || !profile->PrimaryProfessions.count("skinning")))return nullptr;
|
||||
if(intent=="adventure" && p->movespline->Finalized())return nullptr;
|
||||
Creature* best=nullptr;std::vector<Creature*> all;p->GetCreatureListWithEntryInGrid(all,0,AdventureCombatPolicy::SearchRadius);
|
||||
for(auto c:all)
|
||||
{
|
||||
if(best && p->GetExactDist(c)>=p->GetExactDist(best))continue;
|
||||
if(intent=="adventure")
|
||||
{
|
||||
if(!p->IsHostileTo(c))continue;
|
||||
bool nearPath=false;auto path=sClientlessTravelMgr->GetActivePath(p->GetGUID().GetCounter());
|
||||
if(!path)continue;
|
||||
auto const& points=*path;
|
||||
for(std::size_t i=1;i<points.size();++i)
|
||||
if(AdventureCombatPolicy::SegmentDistance(c->GetPositionX(),c->GetPositionY(),c->GetPositionZ(),points[i-1].GetPositionX(),points[i-1].GetPositionY(),points[i-1].GetPositionZ(),points[i].GetPositionX(),points[i].GetPositionY(),points[i].GetPositionZ())<=AdventureCombatPolicy::PathCorridor){nearPath=true;break;}
|
||||
if(!nearPath)continue;
|
||||
}
|
||||
else if(c->GetCreatureTemplate()->type!=CREATURE_TYPE_BEAST || !c->GetCreatureTemplate()->SkinLootId)continue;
|
||||
if(Safe(p,c))best=c;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
bool AdventureCombatMgr::Death(Player* p,Record& r)
|
||||
{
|
||||
if(!r.Dead)
|
||||
{
|
||||
if(r.AI)Finish(p,r);
|
||||
sAdventureBehaviorMgr->InterruptForCombat(p);r.Damagers.clear();r.Dead=true;r.Suspended=true;
|
||||
TC_LOG_INFO("server.adventurebot","DEATH_RELEASE guid=%u",p->GetGUID().GetCounter());
|
||||
}
|
||||
if(p->InBattleground() || p->InArena() || p->IsBeingTeleported())return true;
|
||||
if(!p->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_GHOST))
|
||||
{
|
||||
WorldPacket release(CMSG_REPOP_REQUEST,1);release<<uint8(0);p->GetSession()->HandleRepopRequestOpcode(release);
|
||||
if(auto corpse=p->GetCorpse())corpse->SaveToDB();
|
||||
p->SaveToDB();
|
||||
return true;
|
||||
}
|
||||
if(r.CemeteryPending)
|
||||
{
|
||||
r.CemeteryPending=false;
|
||||
p->ResurrectPlayer(0.5f,false);p->SpawnCorpseBones();
|
||||
TC_LOG_INFO("server.adventurebot","DEATH_CEMETERY_REVIVE guid=%u",p->GetGUID().GetCounter());
|
||||
return true;
|
||||
}
|
||||
auto corpse=p->GetCorpse();if(!corpse)return true;
|
||||
auto now=GameTime::GetGameTime();
|
||||
if(corpse->IsWithinDistInMap(p,CORPSE_RECLAIM_RADIUS,true))
|
||||
{
|
||||
if(now<corpse->GetGhostTime()+p->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP))return true;
|
||||
WorldPacket reclaim(CMSG_RECLAIM_CORPSE,8);reclaim<<corpse->GetGUID();p->GetSession()->HandleReclaimCorpseOpcode(reclaim);
|
||||
if(p->IsAlive())TC_LOG_INFO("server.adventurebot","DEATH_RECLAIM guid=%u",p->GetGUID().GetCounter());
|
||||
return true;
|
||||
}
|
||||
auto travel=sClientlessTravelMgr->GetStatus(p->GetGUID().GetCounter());
|
||||
if(travel && travel->State==ClientlessTravelState::Moving)return true;
|
||||
if(travel && (travel->State==ClientlessTravelState::Stuck || travel->State==ClientlessTravelState::PathRejected))
|
||||
{
|
||||
r.FailedCorpsePoints.push_back(travel->Target);
|
||||
sClientlessTravelMgr->CancelTravel(p->GetGUID().GetCounter());
|
||||
}
|
||||
if(now<r.NextCorpseSearch)return true;
|
||||
r.NextCorpseSearch=now+5;
|
||||
// Try a set of legal reclaim points, including near-side points around the
|
||||
// body; an unreachable exact corpse position alone never triggers fallback.
|
||||
bool pathFound=false;Position best;float shortest=1e30f;
|
||||
if(p->GetMapId()==corpse->GetMapId() && p->GetInstanceId()==corpse->GetInstanceId())for(unsigned ring=0;ring<3;++ring)for(unsigned i=0;i<(ring?12u:1u);++i)
|
||||
{
|
||||
Position end;float radius=ring==1?20.0f:ring==2?32.0f:0.0f;float angle=i*6.2831853f/12;
|
||||
float x=corpse->GetPositionX()+radius*std::cos(angle),y=corpse->GetPositionY()+radius*std::sin(angle);
|
||||
float z=p->GetMap()->GetHeight(p->GetPhaseShift(),x,y,corpse->GetPositionZ()+3,true,8);
|
||||
if(z<=INVALID_HEIGHT)continue;
|
||||
end.Relocate(x,y,z);
|
||||
if(end.GetExactDist(corpse)>CORPSE_RECLAIM_RADIUS-2)continue;
|
||||
if(std::any_of(r.FailedCorpsePoints.begin(),r.FailedCorpsePoints.end(),[&](Position const& failed){return failed.GetExactDist(end)<3;}))continue;
|
||||
ClientlessPathDiagnostics path;
|
||||
if(sClientlessTravelMgr->AnalyzePath(p,end,path) && path.Complete && !path.Suspicious && path.PathLength<shortest)
|
||||
{pathFound=true;best=end;shortest=path.PathLength;}
|
||||
}
|
||||
if(pathFound)
|
||||
{
|
||||
sClientlessTravelMgr->StartTravel(p,best);
|
||||
TC_LOG_INFO("server.adventurebot","DEATH_CORPSE_RUN guid=%u path=%.2f",p->GetGUID().GetCounter(),shortest);
|
||||
}
|
||||
else if(AdventureCombatPolicy::CemeteryFallback(now,corpse->GetGhostTime(),true))
|
||||
{
|
||||
// Native nearest graveyard relocation. No healer interaction, sickness,
|
||||
// durability repair/loss or resource cheat; native resurrection at 50%.
|
||||
r.CemeteryPending=true;
|
||||
p->RepopAtGraveyard();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool AdventureCombatMgr::Update(Player* p,uint32 diff)
|
||||
{
|
||||
if(!p->IsInWorld())return false;
|
||||
auto& r=_records[p->GetGUID().GetCounter()];
|
||||
r.Cooldown=r.Cooldown>diff?r.Cooldown-diff:0;
|
||||
if(p->IsBeingTeleported() || p->GetTransport() || p->IsInFlight() || p->IsCharmed())return r.AI || !p->IsAlive();
|
||||
if(r.Timer>diff){r.Timer-=diff;return r.AI || !p->IsAlive() || r.Dead;}
|
||||
r.Timer=500;
|
||||
if(!p->IsAlive())return Death(p,r);
|
||||
if(r.Dead){r.Dead=false;r.Suspended=false;r.NextCorpseSearch=0;r.FailedCorpsePoints.clear();r.Cooldown=30000;r.Timer=0;return false;}
|
||||
// First actual damager wins, including interrupting a proactive/training
|
||||
// target. Keep all subsequent damagers ordered for after that focus dies.
|
||||
if(!r.Defending)while(!r.Damagers.empty())
|
||||
{
|
||||
auto id=r.Damagers.front();r.Damagers.pop_front();auto c=ObjectAccessor::GetCreature(*p,id);
|
||||
if(!Valid(p,c,false))continue;
|
||||
if(r.AI)Finish(p,r);
|
||||
Start(p,r,c,false,true,0);break;
|
||||
}
|
||||
if(!r.AI && !p->IsInCombat() && !r.Cooldown)
|
||||
if(auto c=Proactive(p))Start(p,r,c,false,false,0);
|
||||
if(!r.AI)return false;
|
||||
auto c=ObjectAccessor::GetCreature(*p,r.Target);
|
||||
if(!Valid(p,c,r.Training) || (r.Until && GameTime::GetGameTime()>=r.Until) || p->GetExactDist(c)>80)
|
||||
{Finish(p,r);return true;}
|
||||
if(!Reachable(p,c))
|
||||
{
|
||||
r.UnreachableMs+=500;
|
||||
if(r.UnreachableMs>=20000){TC_LOG_WARN("server.adventurebot","COMBAT_TARGET_UNREACHABLE guid=%u",p->GetGUID().GetCounter());Finish(p,r);}
|
||||
return true;
|
||||
}
|
||||
r.UnreachableMs=0;
|
||||
if(!p->IsWithinMeleeRange(c))
|
||||
{
|
||||
auto nav=sClientlessTravelMgr->GetStatus(p->GetGUID().GetCounter());
|
||||
if(!nav || nav->State!=ClientlessTravelState::Moving || nav->Target.GetExactDist(c)>5)
|
||||
{
|
||||
Position end;c->GetNearPoint(p,end.m_positionX,end.m_positionY,end.m_positionZ,0.5f,c->GetAngle(p));
|
||||
sClientlessTravelMgr->StartTravel(p,end);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
sClientlessTravelMgr->CancelTravel(p->GetGUID().GetCounter());
|
||||
p->StopMoving();r.AI->Tick(c,500);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef VCORE_ADVENTURE_COMBAT_MGR_H
|
||||
#define VCORE_ADVENTURE_COMBAT_MGR_H
|
||||
#include "Common.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include <ctime>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include "Position.h"
|
||||
#include <vector>
|
||||
class Player;
|
||||
class Unit;
|
||||
class Creature;
|
||||
class TC_GAME_API AdventureCombatMgr
|
||||
{
|
||||
public:
|
||||
static AdventureCombatMgr* instance();
|
||||
bool Update(Player* player,uint32 diff);
|
||||
void DamageTaken(Player* player,Unit* attacker,uint32 damage);
|
||||
void Offline(Player* player);
|
||||
bool TrainingAvailable(Player* player) const;
|
||||
bool Train(Player* player,uint32 durationMs,time_t deadline=0);
|
||||
bool Attack(Player* player,uint32 creatureSpawnId);
|
||||
void Stop(Player* player);
|
||||
private:
|
||||
class Fighter;
|
||||
struct Record
|
||||
{
|
||||
std::shared_ptr<Fighter> AI;
|
||||
ObjectGuid Target;
|
||||
std::deque<ObjectGuid> Damagers;
|
||||
bool Training=false,Defending=false,Suspended=false,Dead=false,CemeteryPending=false;
|
||||
time_t Until=0,NextCorpseSearch=0;
|
||||
std::vector<Position> FailedCorpsePoints;
|
||||
uint32 Timer=0,UnreachableMs=0,Cooldown=0;
|
||||
};
|
||||
bool Start(Player* player,Record& record,Creature* target,bool training,bool defending,time_t until);
|
||||
bool Valid(Player* player,Creature* target,bool training) const;
|
||||
bool Safe(Player* player,Creature* target) const;
|
||||
bool Reachable(Player* player,Creature* target) const;
|
||||
Creature* Dummy(Player* player) const;
|
||||
Creature* Proactive(Player* player) const;
|
||||
bool Death(Player* player,Record& record);
|
||||
void Finish(Player* player,Record& record);
|
||||
std::unordered_map<uint32,Record> _records;
|
||||
};
|
||||
#define sAdventureCombatMgr AdventureCombatMgr::instance()
|
||||
#endif
|
||||
Loaded 100 of 197 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user