Inhaltsverzeichnis
Lua-Interpreter
Einführung
In DEdK kann Lua nicht vollständig verwendet werden. Auf der einen Seite wurden Funktionen (teilweise völlig sinnlos) deaktiviert, auf der anderen Seite wird der Lua-Status nicht richtig gespeichert bzw. geladen. Wie kann man also diese Probleme lösen?
Der einzige Weg, ein „vollständigeres“ Lua zu verwenden, ist, den Lua-Interpreter in Lua zu schreiben.
Lua in Lua
Der Original-C-Code von Lua (5.0.2) wurde von mir nach Lua übertragen. Dadurch war es möglich, einige Funktionen wieder zu reaktivieren. Die neuen Coroutines/Threads werden korrekt gespeichert, da sie keine C-Threads mehr sind, sondern eigentlich Lua-Tables. Auch Metatables werden in dieser Re-Implementierung korrekt abgespeichert.
Lua-Interpreter einbinden
Den Lua-Interpreter kann man hier finden. Das Archiv enthält 13 Dateien. 11 dieser Dateien implementieren den Interpreter, erkennbar am vorangestellten LuaInterpreter.
Die Datei HOK_NewTriggerSystem.lua enthält ein neues Trigger-System, dass das alte von BB ersetzen soll.
Die letzte Datei HOK_MainLoader.lua lädt alle Dateien. Falls nötig, muss man die lokale Variable currFolder anpassen. Möchte man den Interpreter direkt ins Script hinzufügen, muss man den Inhalt der Dateien in der Ladereihenfolge in HOK_MainLoader.lua kopieren.
Lua-Code laden
Wie aber kann man diesen Interpreter verwenden?
Um Lua-Code zu laden, muss TriggerSystem.DoString() mit dem Code und, eventuell, mit einem Quellnamen aufgerufen werden. Dieser Code wird geladen und vom Lua-Interpreter ausgeführt.
Interaktion zwischen Alt-Lua und Neu-Lua
Die globalen Variablen bei Neu- und Alt-Lua sind nicht identisch.
Sollte ein Wert in den globalen Variablen bei Neu-Lua nil sein, so wird automatisch versucht, den Wert aus Alt-Lua zu laden.
Ein Wert kann von Neu-Lua nicht einfach in Alt-Lua gesetzt werden. Dies muss explizit getan werden. _GLOBALS repräsentiert die globalen Variablen von Alt-Lua.
Reaktivierte Funktionen
Folgende Funktionen wurden reaktiviert:
- loadstring()
- getfenv()
- setfenv()
- error()
Bekannte Probleme des Lua-Interpreters
- Bei Fehlermeldungen wird meist statt einem Variablennamen „?“ angezeigt; die Zeilenzahl stimmt aber überein.
- string.dump() kann kein Dump von Neu-Lua-Funktionen erstellen; genausowenig kann loadstring() Dumps laden.
- An Fehlermeldungen hängt auch die Zeilennummer des Asserts (LuaState.lua:…) dran
- Die Geschwindigkeit des Lua-Interpreters ist (logischerweise) deutlich niedriger wie die des Originals
Das Trigger-System
Vorteile
Für den Mapper selbst gibt es auf den ersten Blick keinen Unterschied. Die Trigger-Funktionen funktionieren (fast) alle wie immer. Wozu also?
Auf der einen Seite bietet das neue Trigger-System den entscheidenden Vorteil, dass die (Haupt-)Funktion eines Triggers/Jobs als Thread aufgerufen wird. Dies bedeutet, dass man die Funktionen Delay() und DelayShort() verwenden kann. Entscheidend ist, dass diese Threads auch gespeichert werden.
Auf der anderen Seite können problemlos neue Ereignisse hinzugefügt und ausgelöst werden. So wurden einige nicht-existente Ereignisse hinzugefügt.
Ein weiterer Vorteil ist, dass die Event-Funktionen immer, auch nach einem Delay(), dieselben Werte zurückgeben.
Interaktion von Alt-Lua
Mit TriggerSystem.AddNewEvent() können eigene Ereignisse hinzugefügt werden. Der einzige Parameter ist der Name des Ereignisses. Zurückgegeben wird die ID des Ereignises. Der Eintrag im Events-Table (von Neu-Lua) wird automatisch erstellt.
TriggerSystem.ExecuteEvent() löst ein Ereignis aus. Die Parameter sind die Ereignis-ID und, optional, ein Table, dass die Informationen für die Event-Funktionen enthält.
Ereignisse
Folgende Ereignisse sind vorhanden (mit Event-Funktionen)
Ereignis-Name | Beschreibung | Event-Funktionen |
---|---|---|
LOGIC_EVENT_GAME_STARTED | Wird ausgelöst, wenn das Spiel startet | - |
LOGIC_EVENT_EVERY_SECOND | Wird jede Sekunde ausgelöst | - |
LOGIC_EVENT_EVERY_TURN | Wird jeden Tick ausgelöst | - |
LOGIC_EVENT_DIPLOMACY_CHANGED | Wird ausgelöst, wenn sich die Diplomatie ändert | Event.GetDiplomacyState() - Diplomatie-Status Event.GetSourcePlayerID() - Spieler 1 Event.GetTargetPlayerID() - Spieler 2 |
LOGIC_EVENT_ENTITY_CREATED | Wird ausgelöst, wenn ein Entity erstellt wird | Event.GetEntityID() - ID des Entities |
LOGIC_EVENT_ENTITY_DESTROYED | Wird ausgelöst, wenn ein Entity zerstört wird | Event.GetEntityID() - ID des Entities |
LOGIC_EVENT_ENTITY_HURT_ENTITY | Wird ausgelöst, wenn ein Entity ein anderes verletzt | Event.GetEntityID1() - Angreifer Event.GetEntityID2() - Angegriffener |
LOGIC_EVENT_ENTITY_IN_RANGE_OF_ENTITY | ??? | Event.GetEntityID1() - Entity-ID 1 Event.GetEntityID2() - Entity-ID 2 Event.GetDistance() - Abstand |
LOGIC_EVENT_GOODS_TRADED | Wird ausgelöst, wenn an einem Marktplatz gehandelt wurde | Event.GetEntityID() - Marktplatz Event.GetBuyResource() - Die gekaufte Resource Event.GetBuyAmount() - Die Menge, die gekauft wurde Event.GetSellResource() - Die verkaufte Resource Event.GetSellAmount() - Die Menge, die verkauft wurde |
LOGIC_EVENT_TRIBUTE_PAID | Wird ausgelöst, wenn ein Tribut bezahlt wurde | Event.GetTributeUniqueID() - Tribut-ID Event.GetSourcePlayerID() - bezahlender Spieler Event.GetTargetPlayerID() - Spieler, der Rohstoffe bekommt |
LOGIC_EVENT_WEATHER_STATE_CHANGED | Wird ausgelöst, wenn sich das Wetter ändert | Event.GetOldWeatherState() - altes Wetter Event.GetNewWeatherState() - neues Wetter |
LOGIC_EVENT_RESEARCH_DONE | Wird ausgelöst, wenn eine Technologie fertig erforscht wurde (gefixt) | Event.GetTechnologyType() - Technologie-ID Event.GetPlayerID() - erforschender Spieler |
LOGIC_EVENT_UPGRADE_FINISHED | Wird ausgelöst, wenn ein Gebäude fertig ausgebaut wurde | Event.GetEntityID1() - alte ID Event.GetEntityID2() - neue ID |
LOGIC_EVENT_BUILDING_CONSTRUCTION_COMPLETE | Wird ausgelöst, wenn ein Gebäude fertiggestellt wird | Event.GetEntityID() - ID des Gebäudes Event.GetPlayerID() - bauender Spieler |
LOGIC_EVENT_CANNON_CONSTRUCTION_COMPLETE | Wird ausgelöst, wenn eine Kanone fertiggestellt wird | Event.GetEntityID() - ID der Kanone |
LOGIC_EVENT_PLAYER_STATE_CHANGED | Wird ausgelöst, wenn sich ein Spieler-Status ändert | Event.GetPlayerID() - Spieler Event.GetPlayerState() - neuer Status |
LOGIC_EVENT_PLAYER_DIED | Wird ausgelöst, wenn ein Spieler keine Einheit mehr besitzt (gefixt) | Event.GetPlayerID() - Spieler |