Aufruf von Scriptfunktionen

Durch den Aufruf einer Scriptfunktion wird der Script der Funktion ausgeführt. Dabei kann die aufrufende Scriptfunktion Parameter an die Funktion übergeben und den Rückgabewert der Funktion verwerten.

Aufruf einer lokalen Funktion

Befindet sich die Funktion, die aufgerufen werden soll, im selben Script wie die aufrufende Funktion, so ist dies ein "lokaler" Funktionsaufruf. Dabei wird die Funktion direkt über ihren Namen aufgerufen.

Beispiel:

func TestFunktion()
{
  Log("Die Test-Funktion wurde aufgerufen!");
}

func Aufruf()
{
  TestFunktion();
}
Wird hier die Funktion Aufruf() ausgeführt, so wird die Funktion TestFunktion() aufgerufen, welche eine entsprechende Nachricht ins Log ausgibt.

Aufruf einer Funktion in einem anderen Objekt

Will man eine Funktion im Script eines anderen Objekts aufrufen, so reicht der Name nicht aus, um einen Aufruf ausführen zu können. Es muss zusätzlich das Objekt angegeben werden, in dem die aufzurufende Funktion steht.

Beispiel:

Script Objekt A (ID AAAA):
func Activate()
{
  Log("Activate wurde in Objekt A aufgerufen!");
  Explode(20);
}
Script Objekt B:
func Activate()
{
  var obj = FindObject(AAAA, -1, -1, -1, -1);
  obj->Activate();
}	
Der Script der Funktion Activate() in Objekt B sucht sich als erstes das nächstliegende Objekt vom Typ A (also mit der ID AAAA) und speichert es in der Veriable obj. Danach wird die Funktion Activate() im Script von diesem Objekt aufgerufen. Dazu wird zuerst das aufzurufende Objekt angegeben, gefolgt von dem Pfeil-Operator, der einen Objektaufruf markiert. Danach folgt der Funktionsname der aufzurufenden Funktion nebst der Parameterliste (in diesem Fall werden keine Parameter übergeben).
Es wird also durch den Aufruf von Activate() in Objekt B bewirkt, dass das nächstliegende Objekt vom Typ A in die Luft gejagt wird. Es handelt sich also im Beispiel um eine Art sehr primitiver Fernsteuerung für Objekt A (Der Aufruf erzeugt z.B. einen Fehler, wenn kein Objekt A existiert).

Anmerkungen

Die Speicherung des Objektzeigers in der Variable obj im Beispiel ist nicht erforderlich. Die folgende Schreibweise der Funktion Activate() in B ist gleichwertig:
func Activate()
{
  FindObject(AAAA, -1, -1, -1, -1)->Activate();
}
Es kann zusätzlich zum Namen der aufzurufenden Funktion noch die ID der Definition der Scriptfunktion mit angegeben werden. Das macht den Aufruf zum einen in vielen Fällen leicht schneller, außerdem können so auch überladene Funktionen im Zielscript aufgerufen werden (siehe #include/#appendto).
func Activate()
{
  var obj = FindObject(AAAA, -1, -1, -1, -1);
  obj->AAAA::Activate();
}

Aufruf globaler Funktionen ohne Objekt- oder Definitionskontext

Seit LC [336] ist es möglich, #strict 3 oder höher vorausgesetzt, global definierte Funktionen mit global->Function() ohne Kontext aufzurufen. global->~ ist ebenfalls möglich. Wichtig ist aber, dass zwischen "global" und "->" kein Leerzeichen sein darf. Damit ist es zum Beispiel möglich, bei Funktionen, die objektlokale Koordinaten erwarten, globale Koordinaten anzugeben, ohne die eigenen Koordinaten davon abzuziehen.
Das folgende Script erstellt einen Flint an den globalen Koordinaten 10/10, sogar wenn es innerhalb eines Objektes ausgeführt wird:
global->CreateObject(FLNT, 10, 10, NO_OWNER);

Indirekter Aufruf von Skriptfunktionen

In manchen Situationen kann allerdings auch ein "indirekter" Aufruf durch die Engine-Funktionen Call und Verwandte sinnvoll sein. Hier wird der Funktionsname als String übergeben, was den Aufruf einer Funktion "nach Namen" ermöglicht.

Beispiel:

func TestFunktion()
{
  Log("Die Test-Funktion wurde aufgerufen!");
}

func Aufruf()
{
  Call("TestFunktion");
}
Ein solcher indirekter Aufruf ist allerdings in der Regel deutlich langsamer als der direkte Aufruf, da bei Call die entsprechende Funktion erst zur Laufzeit im Script gesucht werden muss. Beim direkten Aufruf steht die aufzurufende Funktion dagegen in der Regel bereits zur Zeit des Parsens (also beim Start der Engine) fest, weshalb dieser Aufruf besser optimiert werden kann und deshalb schneller ist.
Dieser Nachteil ist aber gleichzeitig in bestimmten Situationen eine Stärke von Call: es ist möglich, zur Laufzeit zu entscheiden, welche Funktion aufgerufen werden soll. Eine Anwendung soll das folgende Beispiel deutlich machen:
func TestFunktion()
{
  Call(Format("Aufruf%d", Random(3)));
}

func Aufruf0() { Log("Die erste Funktion wurde aufgerufen!"); }
func Aufruf1() { Log("Die zweite Funktion wurde aufgerufen!"); }
func Aufruf2() { Log("Die dritte Funktion wurde aufgerufen!"); }
Hier wird in TestFunktion() eine zufällige Funktion aufgerufen (mittels Random und Format wird zufällig einer der drei Strings "Aufruf1", "Aufruf2" oder "Aufruf3" an Call übergeben).
Call muss hier verwendet werden, da erst zur Laufzeit bestimmt wird, welche Funktion aufgerufen wird. Außerdem wird bei jeder Ausführung von TestFunktion() eine andere Scriptfunktion ausgewählt, die aufgerufen wird. Dies wäre mit einem direkten Aufruf nicht möglich.
Außer Call können auch andere Zugriffsarten indirekt erfolgen, siehe dazu ObjectCall und GameCall. Besondere Beachtung verdienen außerdem noch PrivateCall und ProtectedCall. Sie ermöglichen die Umgehung der Aufrufbeschränkung und existieren nur in der "Indirekt-Aufruf-Version".
PeterW, Mai 2003