*******************************************************
******** Wie man Power Patch Plug-Ins erstellt ********
*******************************************************

Das hier beschriebene Beispiel ist in FreeBasic geschrieben.
Wenn jemand so freundlich ist, es in C zu bersetzen, mge
er es mit bitte mailen: cherry@cherry.at.tf

Als erstes mssen die Lua-Headerfiles eingebunden werden:

 #Include Once "Lua/lua.bi"
 #Include Once "Lua/lauxlib.bi"
 #Include Once "Lua/lualib.bi"

Dann das Win32API-Headerfile:

 #Include Once "windows.bi"

Danach muss folgender UDT definiert werden:

 Type LuaDec
  FuncPtr As Any Ptr
  FuncName As ZString Ptr
 End Type


Danach mssen einige Dinge global deklariert werden:

 Dim Shared hWnd As HWND
 Dim Shared GamePath As String
 Dim Shared GetVar As Function Cdecl (index As Integer) As Integer
 Dim Shared SetVar As Function Cdecl (index As Integer, value As Integer) As Boolean
 Dim Shared Terminate As Function Cdecl () As Boolean

In hWnd wird spter das Fensterhandle des Spielfensters und in GamePath der Pfad des Spielordners gespeichert.
GetVar entspricht der Funktion, die in Lua bereitgestellt wurde, nur kann nur eine Variable abgefragt werden. SetVar entspricht der in Lua bereitgestellten Funktion. Terminate beendet das Spiel und den Patch.

Nun brauchen wir die Funktion "RegisterFunctions". Sie wird aufgerufen, wenn das Plug-In initialisiert wird. Sie hat 2 Parameter: index, ein Integer, und Declaration, ein Pointer zu einer LuaDec-Struktur. Ist die Zahl in Index 0 oder positiv, muss die Funktion Beschreibungen fr die bereitgestellten Funktionen in die LuaDec-Struktur schreiben und TRUE zurckgeben. Wurden schon alle Funktionen beschrieben, muss FALSE zurckgegeben werden. Bei Negativem index-Wert muss die Funktion Werte aus der LuaDec-Struktur lesen. Ich denke, im Beispiel sieht man gut, was gemeint ist:

 Public Function RegisterFunctions Cdecl Alias "RegisterFunctions" (index As Integer, Declaration As LuaDec Ptr) As Boolean
  Select Case index
   Case -1
    hWnd = *(Declaration).FuncPtr ' hWnd empfangen
    GamePath = *(*(Declaration).FuncName) ' GamePath empfangen
    Return TRUE
   Case -2
    GetVar = *(Declaration).FuncPtr ' GetVar empfangen
    Return TRUE
   Case -3
    SetVar = *(Declaration).FuncPtr ' SetVar empfangen
    Return TRUE
   Case -4
    Terminate = *(Declaration).FuncPtr ' Terminate empfangen
    Return TRUE
   
   [...]

   Case Else
    Return FALSE
  End Select
 End Function

Dort, wo "[...]" steht, kommen nun die eigentlichen Beschreibungen unserer Lua-Funktionen hinein. Nehmen wir an, wir haben die Funktionen "AddVar", im Code "LAddVar", "SubVar", im Code "LSubVar", "MulVar", im Code "LMulVar" und "DivVar", im Code "LDivVar", die mit den angegebenen Maker-Variablen rechnen sollen und die wir fr Lua zu Verfgung stellen wollen:

 Case 0
  *(Declaration).FuncPtr = @LAddVar
  *(Declaration).FuncName = StrPtr("AddVar")
  Return TRUE
 Case 1
  *(Declaration).FuncPtr = @LSubVar
  *(Declaration).FuncName = StrPtr("SubVar")
  Return TRUE
 Case 2
  *(Declaration).FuncPtr = @LMulVar
  *(Declaration).FuncName = StrPtr("MulVar")
  Return TRUE
 Case 3
  *(Declaration).FuncPtr = @LDivVar
  *(Declaration).FuncName = StrPtr("DivVar")
  Return TRUE

Das einzige, was jetzt noch fehlt, sind die eigentlichen Funktionen - diese knnen ganz normal erstellt werden (natrlich fr Lua "verstndlich"), z.B.:

 Function LAddVar Cdecl (L As lua_State Ptr) As Integer
  Dim numpar As Integer
  Dim sum As Integer
  numpar = lua_gettop(L)
  For i As Integer = 0 To numpar
   sum += GetVar(lua_tonumber(L, i)) ' Zahl aus angegebener Variable auslesen und zur Summe addieren
  Next i
  lua_pop(L, numpar)
  lua_pushnumber(L, sum)
  Return 1
 End Function

Wer das letzte Beispiel nicht versteht, der soll in einem Tutorial zu Lua nachlesen.

Jetzt noch der Code im Ganzen:

 #Include Once "Lua/lua.bi"
 #Include Once "Lua/lauxlib.bi"
 #Include Once "Lua/lualib.bi"

 #Include Once "windows.bi"

 Type LuaDec
  FuncPtr As Any Ptr
  FuncName As ZString Ptr
 End Type

 Dim Shared hWnd As HWND
 Dim Shared GamePath As String
 Dim Shared GetVar As Function Cdecl (index As Integer) As Integer
 Dim Shared SetVar As Function Cdecl (index As Integer, value As Integer) As Boolean
 Dim Shared Terminate As Function Cdecl () As Boolean

 Function LAddVar Cdecl (L As lua_State Ptr) As Integer
  Dim numpar As Integer
  Dim sum As Integer
  numpar = lua_gettop(L)
  For i As Integer = 0 To numpar
   sum += GetVar(lua_tonumber(L, i)) ' Zahl aus angegebener Variable auslesen und zur Summe addieren
  Next i
  lua_pop(L, numpar)
  lua_pushnumber(L, sum)
  Return 1
 End Function

 Function LSubVar Cdecl (L As lua_State Ptr) As Integer
  Dim numpar As Integer
  Dim diff As Integer
  numpar = lua_gettop(L)
  For i As Integer = 0 To numpar
   diff -= GetVar(lua_tonumber(L, i)) ' Zahl aus angegebener Variable auslesen und von der Differenz subtrahieren
  Next i
  lua_pop(L, numpar)
  lua_pushnumber(L, diff)
  Return 1
 End Function

 Function LMulVar Cdecl (L As lua_State Ptr) As Integer
  Dim numpar As Integer
  Dim prod As Integer
  numpar = lua_gettop(L)
  For i As Integer = 0 To numpar
   prod *= GetVar(lua_tonumber(L, i)) ' Zahl aus angegebener Variable auslesen und mit dem Produkt multiplizieren
  Next i
  lua_pop(L, numpar)
  lua_pushnumber(L, prod)
  Return 1
 End Function

 Function LDivVar Cdecl (L As lua_State Ptr) As Integer
  Dim numpar As Integer
  Dim quo As Integer
  numpar = lua_gettop(L)
  For i As Integer = 0 To numpar
   quo /= GetVar(lua_tonumber(L, i)) ' Zahl aus angegebener Variable auslesen und Quotient mit dieser Zahl dividieren
  Next i
  lua_pop(L, numpar)
  lua_pushnumber(L, quo)
  Return 1
 End Function

 Public Function RegisterFunctions Cdecl Alias "RegisterFunctions" (index As Integer, Declaration As LuaDec Ptr) As Boolean
  Select Case index
   Case -1
    hWnd = *(Declaration).FuncPtr ' hWnd empfangen
    GamePath = *(*(Declaration).FuncName) ' GamePath empfangen
    Return TRUE
   Case -2
    GetVar = *(Declaration).FuncPtr ' GetVar empfangen
    Return TRUE
   Case -3
    SetVar = *(Declaration).FuncPtr ' SetVar empfangen
    Return TRUE
   Case -4
    Terminate = *(Declaration).FuncPtr ' Terminate empfangen
    Return TRUE
  Case 0
   *(Declaration).FuncPtr = @LAddVar
   *(Declaration).FuncName = StrPtr("AddVar")
   Return TRUE
  Case 1
   *(Declaration).FuncPtr = @LSubVar
   *(Declaration).FuncName = StrPtr("SubVar")
   Return TRUE
  Case 2
   *(Declaration).FuncPtr = @LMulVar
   *(Declaration).FuncName = StrPtr("MulVar")
   Return TRUE
  Case 3
   *(Declaration).FuncPtr = @LDivVar
   *(Declaration).FuncName = StrPtr("DivVar")
   Return TRUE
   Case Else
    Return FALSE
  End Select
 End Function

Nun mssen wir das PlugIn noch kompilieren, nennen wir es z.B. "VarCalc.dll", und mit dem Configurator einbinden.

Jetzt knnen wir es mit Lua ansprechen, z.B.:

SetVar(40, MulVar(35, 36, 38)) -- Multipliziert Variable Nr. 35, 36 und 38 miteinander und speichert das Ergebnis in Variable 40

Ich hoffe, ich habe dieses Thema verstndlich erklrt!

mfG Cherry