Was ist Maniascript?
Maniascript ist eine Programmiersprache wie Java oder C/C++. Ihr könnt sie verwenden, um automatisch generierte Texte auszugeben, interaktive Inhalte zu erstellen und noch vieles mehr.
In diesem Tutorial werdet ihr von Grund auf lernen, was eine Programmiersprache ist und wie man sie nutzen kann - Ihr braucht also keinerlei Vorkenntnisse! Erfahrenere Leser werden dementsprechend einige grundlegende Passagen überspringen können, doch ich empfehle jedem, das komplette Tutorial zu lesen. Nur so könnt ihr sichergehen, auch keine Besonderheit von Maniascript übersehen zu haben.


Syntax:
Obwohl Gugli bereits einen kleinen Thread für die Syntax von Maniascript erstellt hat, werde ich diese zusammen mit den Grundlagen einer Programmiersprache hier noch einmal wiederholen – Nur, um sicherzugehen, dass ihr alle dieses Tutorial versteht.


Variablen:
Das wichtigste in Programmiersprachen sind Variablen. Eine Variable hat einen Typ (Zahl, Text, Zustand, …), einen Namen und einen damit verbundenen Wert. Ich kann in einer Variable einen Wert speichern und später auf diesen Wert zugreifen, indem ich einfach den Namen dieser Variable benutze. Während der Laufzeit (Die Zeit, während der das Skript ausgeführt wird) kann ich die Werte ändern (=> Variabel ) und somit beispielsweise auf Eingaben reagieren.
Es gibt verschiedenen Variablen-Typen: (Man spricht auch von "Datentypen")

1.) Integer
Ein Integer ist einen ganzzahlige Zahl, d.h. sie besitzt keine Kommastellen. Ein Integer könnte beispielsweise die Werte 2, -54, 19274 oder 0 besitzen.

2.) Real
Ein Real ist eine reelle Zahl, kann also Kommastellen besitzen. Wie es in Programmiersprachen üblich ist, werden die Vorkommastellen mit den Nachkommastellen durch einen Punkt . getrennt und nicht durch ein Komma ,. Mögliche Werte wären also 5.2, 9123.1234 oder -0.01.
Hinweis: 4. Ist ein Real und kein Integer, da es einen Punkt besitzt! Ebenso ist 3.0 ein Real. Sobald ein Punkt enthalten ist, deutet dies auf mögliche Nachkommastellen hin, weshalb Maniascript diese Werte als Real erkennt.


3.) Boolean
Viele von euch werden schon das eine oder andere Mal den Begriff "Boolscher Wert" gehört haben. Die Grundidee ist relativ simpel – Ein Boolean ist ein Zustand mit 2 Möglichkeiten: Wahr oder falsch, ja oder nein, richtig oder falsch. Am häufigsten wird die Wahr/Falsch-Symbolik verwendet, weshalb man in Programmiersprachen die englischen Begriffe true (wahr) und false (falsch) dafür verwendet. In Maniascript werden diese im Gegensatz zu Java oder PHP großgeschrieben!
Die einzigen beiden Möglichkeiten für einen Wert eines Booleans sind also: True oder False.

4.) Text
Der Name sollte selbsterklärend sein. In einem Text wird eine Reihe an Zeichen gespeichert – Dargestellt wird ein Text in Maniascript durch umschließende doppelte Anführungszeichen. "
"Hallo! Ich bin destro." ist also ein Text. Genauso wären auch "0", "67.2" oder "True" Texte.
(Hier lässt sich schon ein kleines Problem erahnen: Wie soll man doppelte Anführungszeichen in Texten darstellen? Ganz einfach: Man "escapet" sie – Dies geschieht durch ein Voranstellen eines Backslashes \. Befindet sich ein Backslash vor einem Zeichen, so bekommt dieses eine neue Bedeutung, je nachdem um welches Zeichen es sich handelt. So ist \" ein Anführungstrich, \n ein Zeilenumbruch und \\ ein Backslash. Der Inhalt Destro sagt: "Hallo!" würde also als Text so aussehen: "Destro sagt: \"Hallo!\"")

Datentypen für Fortgeschrittene
Neben diesen simplen Datentypen bietet Maniascript auch ein wenig "fortgeschrittenere" Datentypen an - Diese können euch sehr hilfreich sein, vielleicht seid ihr eines Tages auch auf sie angewiesen.
Sich diesen Teil durchzulesen, kann sicherlich nicht schaden - Doch, falls ihr wirklich nur die Grundlagen von Maniascript beherrschen wollt, reichen euch (genauso wie den Codebeispielen in diesem Tutorial) die simplen Datentypen völlig aus.
Spoiler: Anzeigen...



Deklaration / Erstellen einer Variable:
Damit man eine Variable verwenden kann, muss diese natürlich erst einmal erstellt werden – Man spricht vom "Deklarieren" einer Variable. In Maniascript geschieht dies durch das Schlüsselwort declare, gefolgt vom Variablentyp (Siehe oben) und dem Variablennamen.
Würde ich also eine Variable vom Typ Integer (Ganzzahl) mit dem Namen anzahlSpieler (und vorerst noch keinem genauen Wert) erstellen wollen, müsste ich folgenden Code schreiben:
declare Integer anzahlSpieler;

Hier lässt sich auch gleich ein weiteres Merkmal einer Programmiersprache erkennen – Man muss ihr sagen, ab wo der aktuelle "Befehl" zu Ende ist (Es wird ein Befehl nach dem anderen ausgeführt ). Dies geschieht üblicherweise, so auch in Maniascript, durch ein Semikolon ;. Deshalb muss nach jedem Befehl (was aber nicht jede Zeile bedeutet!) ein Semikolon stehen.
Würde ich der Variable anzahlSpieler nun auch noch gleich einen Wert zuweisen wollen (Fachbegriff: Initialisieren), z.B. 12, würde das folgendermaßen aussehen:
declare Integer anzahlSpieler = 12;

Variablen weißt man Werte durch den Operator = zu. (Ein Operator ist ein Zeichen, was in der jeweiligen Programmiersprache einen spezielle Bedeutung besitzt - So bedeutet das =-Zeichen die Zuweisung eines neuen Wertes). Ich könnte den Wert nun irgendwo später im Code ändern durch:
anzahlSpieler = 4;

Hinweis: Beachtet hier, dass ich das declare nicht mehr benötige – Dieses brauche ich nur an einer einzigen Stelle und zwar dort, wo die Variable erstellt wird. Anschließend reicht der Variablenname.

Die beiden folgenden Codes würden also exakt das gleiche auslösen:
declare Integer anzahlSpieler = 12;

declare Integer anzahlSpieler;
anzahlSpieler = 12;

Hinweis: Variablen haben in Maniascript immer einen Wert – Wurde noch kein genauer Wert zugewiesen, so wird ein Standardwert für den jeweiligen Variablen-Typ verwendet.



Rechenoperatoren:
In Maniascript lässt sich natürlich wie in jeder Programmiersprache auch rechnen – Dies kann entweder direkt mit Zahlen, aber auch mit Variablen, die Zahlen gespeichert haben, geschehen.
Folgende Beispiele würde der Variable anzahlSpieler (Die an diesem Punkt schon exisitiert) den Wert 10 zuweisen:

Addition (Plus)
anzahlSpieler = 8 + 2;

Substraktion (Minus)
anzahlSpieler = 13 - 3;

Multiplikation (Mal nehmen)
anzahlSpieler = 2 * 5;

Division (Teilen)
anzahlSpieler = 40 / 4;

Verwendung von Klammern
anzahlSpieler = (2 + 3) * 2;

Hinweis: Die Zeichen +, -, *, /, ( und ) sind ebenso wie = Operatoren, da sie eine spezielle Bedeutung in Maniascript-Ausdrücken haben.


Man kann, wie bereits erwähnt, aber auch Variablen in die Berechnung mit einbeziehen:
declare Integer faktor = 5;
anzahlSpieler = 2 * faktor;

Im oberen Beispiel wird eine Variable mit dem Wert 5 erstellt und diese anschließend mit 2 mulitpliziert. Das Produkt wird der Variable anzahlSpieler zugewiesen.
Dieses Verwenden von Variablen ist sehr nützlich, da man so auch die alten Werte einer Variable verwenden kann. Folgender Code würde den Wert von anzahlSpieler um 1 erhöhen:
anzahlSpieler = anzahlSpieler + 1;

Zu dem Zeitpunkt der Berechnung besitzt anzahlSpieler noch den alten Wert – Dieser wird mit 1 addiert und die Summe wieder in anzahlSpieler gespeichert.


Logische Operatoren:
Bisher haben wir uns nur mit "normalen" Rechnungen beschäftigt - Zwei Zahlen wurden verrechnet und ergaben eine neue Zahl. Jedoch gibt es auch die sogenannten "logischen Operatoren", die einen Boolean zurückliefern.
Dabei kann man die Bedeutung der Operatoren so interpretieren, als ob sie eine Bedingung haben, die die verrechneten Werte erfüllen müsen, damit das Ergebnis True entspricht. Ist diese Bedingung nicht erfüllt, wird False zurückgegeben:

OperatorBedingung für TrueWertetabelle
< (Kleiner)Der erste Wert muss kleiner als der zweite sein.-4 < 23 = True
145 < 9253 = True
3 < 2.8 = False
<= (Kleiner gleich)Der erste Wert muss kleiner oder gleich dem zweiten sein.71 <= 0.56 = False
6 <= 6 = True
842 <= 21091 = True
== (Gleich)Der erste Wert muss gleich dem zweiten sein.51 == 51 = True
451 == 0 = False
9 == 9.0 = True
!= (Ungleich)Der erste Wert muss ungleich dem zweiten sein.15.9 != 15.9 = False
28 != -6 = True
515 != 33 = True
>= (Größer gleich)Der erste Wert muss größer oder gleich dem zweiten sein.99 >= 8 = True
63 >= 723 = False
0.002 >= 0.002 = True
> (Größer)Der erste Wert muss größer als der zweite sein.2 > 1 = True
15.01 > 7 = True
4 > 11 = False
&& (AND)Beide Werte müssen True ergeben.False && False = False
True && False = False
False && True = False
True && True = True
|| (OR)Mindestens einer der Werte True ergeben.False || False = False
True || False = True
False || True = True
True || True = True
! (NOT)(Besitzt nur 1 Operanden => Unärer Operator)
Der Wert muss False ergeben.
! True = False
! False = True

Hinweis: Logische Operatoren, deren Werte als Booleans interpretieren (&&, ||, !), nennt man auch "Boolsche Operatoren".



Arbeiten mit Text-Variablen:
Mit Variablen vom Typ Text lassen sich selbstverständlich keine grundlegenden Berechnungen wie Multiplikationen durchführen. Allerdings gibt es auch hier ein paar Möglichkeiten.
Da wäre zum Beispiel der ^-Operator. Mit ihm lassen sich Werte auf Textebene "aneinander knüpfen" (Also keine Addition im mathematischen Sinne – Die Texte bzw. Werte werden einfach aneinander gehängt):
declare Text begruessungsAnfang = "Hallo ";
declare Text vollstaendigeBegruessung = begruessungsAnfang ^ "destro";

Der Inhalt der Variable vollstaendigeBegruessung würde nach Ausführung dieses Codes folgenden Inhalt haben: "Hallo destro"
Aber nicht nur Texte lassen sich aneinander hängen – Ihr könnt ebenso andere Datentypen, z.B. Zahlen, in den Text einarbeiten:
declare Text nachricht = "Das doppelte von " ^ 5 ^ " ist " ^ (5*2);

Dieser Code würde folgenden Wert in der Variable nachricht speichern: "Das doppelte von 5 ist 10".




Kommentare:
Oft ist ein spezieller Codeteil sehr kompliziert, so dass man einen Kommentar hinterlassen will, um sich selber oder auch andere nicht zu verwirren und lange Sucharbeit zu verhindern. Ebenso könnte man seinen Namen gerne im Code hinterlassen oder das Datum, wann der jeweilige Codeabschnitt zum letzten Mal bearbeitet wurde. In diesem Fall bieten sich Kommentare an – Sie werden von Maniascript einfach ignoriert und auf keinen Fall in irgendeiner Weise ausgeführt.
Einzeilige Kommentare beginnen wie auch in anderen Programmiersprachen mit zwei Slashes // und erstrecken sich bis zum Zeilenende:
//Hallo – Ich bin ein Kommentar
declare Integer anzahlSpieler = 5; //Ich kann auch hinter einem Befehl stehen
//anzahlSpieler = 8;

Der Wert von anzahlSpieler würde nach Ausführung dieses Codes selbstverständlich 5 betragen und nicht 8, da der untere Befehl als Kommentar gekennzeichnet wurde und somit gar nicht erst beachtet geschweige denn ausgeführt wird.
Falls ihr vorhabt, einen längeren Kommentar zu schreiben und diesen nicht in eine Zeile quetschen wollt, könnt ihr einen mehrzeiligen Kommentar verwenden. Ihr markiert mit /* den Anfang des "Kommentarblocks" und mit */ dessen Ende:
/*Ich bin ein mehrzeiliger
Kommentar. Ich höre daher erst hier auf */

Mehrzeilige Kommentare sind zudem hilfreich, um längere Codepassagen nicht ausführen zu lassen (z.B. bei der Fehlersuche) – Man spricht vom "auskommentieren":
declare Integer anzahlSpieler = 4;
/*anzahlSpieler = 5;
anzahlSpieler = anzahlSpieler + 1;*/

Nach Ausführung des Codes würde der Wert von anzahlSpieler somit immer noch 4 betragen.




Funktionen:
Mithilfe von Funktionen lassen sich beliebig lange Programmabläufe zusammenfassen und mit einem einem einzigen Befehl aufrufen. Funktionen haben einen Namen und können zudem einen Rückgabewert besitzen - Dies müssen sie allerdings nicht. Jedoch muss dies eindeutig deklariert werden, entweder durch den Datentyp des Rückgabewertes (Integer, Boolean, Text, …) oder durch das Schlüsselwort Void (Englisch: Leer, Nichts), falls kein Wert zurückgegeben wird. Der Programmablauf einer Funktion bzw. der Code, den sie ausführen soll, wird in einem "Codeblock" (siehe voriges Kapitel: Codeblock-System ) in geschwungenen Klammern {...} zusammengefasst. Eine simple Funktion wird folgendermaßen deklariert:
Void meineFunktion(){
    //Hier kann ein beliebig langer Programmablauf stehen
}

Die obere Funktion besitzt keinen Rückgabewert (Void) und heißt meineFunktion - Diese Deklaration an sich führt noch keinen Code aus - Im späteren Programmablauf kann man schließlich über den Funktionsnamen mithilfe dieses Befehls den inneren Code der Funktion ausführen lassen:
meineFunktion();

Wie sich hier bereits erkennen lässt, eignen sich Funktionen sehr gut, um sich oft wiederholende Codeabschnitte zusammenzufassen. Eine mögliche Korrektur dieses Codes muss dann anschließend nur noch an einer Stelle getätigt werden. Zudem dienen Funktionen der Lesbarkeit des Codes, speziell für Funktionen und Variablen gilt es, aussagekräftige Namen zu finden – Nicht zu kurz, nicht zu lang, keine falschen Aussagen gebend, präzise, … gar nicht so leicht, aber es ist noch kein Meister vom Himmel gefallen. Trotzdem kann es nicht schaden, euren Funktionen von Anfang an passende Namen zu geben.


Funktionsparameter:
Oft tauchen im Code mehrere Stellen auf, die fast identisch sind, sich jedoch in kleinen Details unterscheiden. Beispiele:
anzahlSpieler = anzahlSpieler + 5;
irgendeineFunktion();

anzahlSpieler = anzahlSpieler + 8;
irgendeineFunktion();

declare Integer zaehler = 3;
anzahlSpieler = anzahlSpieler + zaehler;
irgendeineFunktion();

willkommensNachricht = "Hallo destroflyer";
willkommensNachricht = willkommensNachricht ^ ", Marcel";
willkommensNachricht = willkommensNachricht ^ ", Alinoa";

Wie sich erkennen lässt, passiert hier im Grunde mehrmals das gleiche. Allerdings könnte man einen solchen Ablauf nicht in eine "normale" Funktion einfügen und diese mehrmals aufrufen, da sich die einzelnen Codestücke minimal unterscheiden – Und zwar in den verwendeten Werten.
Die Lösung ist denkbar einfach: Irgendwie muss der Funktion, ein Wert übergeben werden, den diese anschließend weiterverarbeiten kann. Solche Werte nennt man "Parameter" einer Funktion.
(Im ersten der oberen Beispiele würde ich also z.B. eine Funktion namens anzahlSpielerErhoehen schreiben, die den benötigten Wert übergeben bekommt, diesen mit der Variable anzahlSpieler addiert und anschließend die Funktion irgendeineFunktion aufruft)

Funktionsparameter werden zwischen den runden Klammern (...) nach dem Funktionsnamen deklariert. Dabei steht zuerst der Datentyp, gefolgt von einem Namen, über den der Code im inneren der Funktion auf diesen Wert zugreifen kann.
Unsere Beispielfunktion soll 1 Parameter vom Typ Integer besitzen – Einen Rückgabewert braucht sie nicht (Void). Diese Funktion sähe so aus:
Void funktionMitParameter(Integer meinParameter){
    //Hier kann die übergebene Variable additionsWert verwendet werden
}

Die Funktion kann nun durch die Variable meinParameter auf den übergebenen Wert zugreifen. (Die Namen der Parameter können natürlich frei gewählt werden )

Doch wie sieht nun der Aufruf der funktionMitParameter-Funktion aus? Die Parameter werden wie in der Deklaration in den runden Klammern (...) angegeben:
funktionMitParameter(5);
declare Integer zaehler = 21;
anzahlSpielerErhoehen(zaehler);

Selbst der Wert einer Variable kann problemlos als Parameter übergeben werden, solange es sich um den gleichen Datentyp handelt. (In diesem Fall ist sowohl die Variable zaehler als auch der benötigte Funktionsparameter vom Typ Integer)

Funktionen können selbstverständlich beliebig viele Parameter haben – Diese werden innerhalb der runden Klammern durch Kommata , voneinander getrennt:
Void meineFunktion(Integer irgendeineZahl, Boolean einZustand, Real eineKommazahl){
    //Code innerhalb der Funktion
}

Der Aufruf sieht dementsprechend folgendermaßen aus:
meineFunktion(5, True, 22.1);

Hinweis: Funktionen können im Code nur dann aufgerufen werden, wenn sie bereits vorher deklariert wurden.



Rückgabewerte:
Wie bereits erwähnt, können Funktionen auch Werte zurückliefern – Dies ist vor allem bei Berechnungen hilfreich: Der Funktion wird einer oder mehrere Werte übergeben, diese führt die Berechnung aus und gibt das Ergebnis zurück.
Ich werde dies am Beispiel einer einfachen Funktion demonstrieren, die eine Zahl (Typ: Integer) als Funktionsparameter übergeben bekommt, diese quadriert und das Ergebnis (Typ: Integer) zurückliefert. Ich nenne diese Funktion quadrieren – Die Deklaration sähe wie folgt aus:
Integer quadrieren(Integer zahlZumQuadrieren)

Durch den Datentyp Integer vor der Funktion wird festgelegt: Diese Funktion liefert immer (!) einen Wert vom Typ Integer zurück. Innerhalb der Funktion erstellen wir vorerst eine Variable, in der wir das Quadrat speichern, nennen wir sie quadrat:
//Dieser Code befindet sich innerhalb der Funktion
declare Integer quadrat = zahlZumQuadrieren * zahlZumQuadrieren;

Auch hier lässt sich sofort erkennen: Der Code greift auf den übergebenen Funktionsparameter zahlZumQuadrieren zu und multipliziert diesen mit sich selbt (Quadrieren ) – Das Ergebnis wird in der Variable quadrat gespeichert.
Nun erfolgt die eigentliche Rückgabe des Wertes. Dies geschieht durch das Schlüsselwort return:
//Dieser Code befindet sich innerhalb der Funktion
return quadrat;

Hier können wir direkt die Variable quadrat zurückgeben – Wir könnten allerdings auch direkt das Ergebnis der Multiplikation zurückgeben und uns den Zwischenschritt mit der Variable sparen.
Der gesamte Code der Funktion quadrieren würde somit so aussehen:
Integer quadrieren(Integer zahlZumQuadrieren){
    declare Integer quadrat = zahlZumQuadrieren * zahlZumQuadrieren;
    return quadrat;
}

Aber wie lässt sich dieser Rückgabewert nun verarbeiten? Ganz einfach – Man kann den Aufruf der Funktion direkt als Wert benutzen:
declare Integer quadratVonDrei = quadrieren(3);

Überall, wo ein Wert stehen kann, könnt ihr die Funktion verwenden – Selbst Verschachtelungen (Rückgabewert als neuen Parameter benutzen) ist möglich:
declare Integer dreiHochVier = quadrieren(quadrieren(3));



Gültigkeitsbereich von Variablen:
Innerhalb einer Funktion könnt ihr problemlos Variablen auslesen und verändern - Doch dies ist nur mit Variablen möglich, die in dieser Funktion deklariert wurden. Ein kleines Beispiel, um dies zu verdeutlichen:
Void spielerAnzahlUmEinsErhoehen(){
    anzahlSpieler = anzahlSpieler + 1;
}

Void meineFunktion(){
    declare Integer anzahlSpieler = 0;
    spielerAnzahlUmEinsErhoehen();
}

Später führe ich an einer anderen Stelle im Code folgenden Befehl aus:
meineFunktion();

Auf den ersten Blick würde man denken, dass die Variable anzahlSpieler erstellt wird, und ihr Wert anschließend durch den Aufruf von spielerAnzahlUmEinsErhoehen um 1 erhöht wird. Das ist jedoch falsch!
Maniascript würde die Ausführung des oberen Skripts mit einem Fehler abbrechen. Dieser tritt in der Funktion spielerAnzahlUmEinsErhoehen auf: Hier wird die Variable anzahlSpieler verwendet, die (sofern man nur diese eine Funktion betrachtet) noch nicht deklariert wurde! Ob sie an irgendeiner anderen Stelle im Code eventuell schon erstellt wurde (Wie es ja in meineFunktion der Fall ist), ist unbedeutend.
Maniascript bietet für diese Fälle allerdings eine Möglichkeit, Variablen funktionenübergreifend zu deklarieren.

Variablen explizit verfügbar machen / declare for:
In Maniascript kann in Verbindung mit declare das Schlüsselwort for genutzt werden - Man spricht von einem "declare for" (Deutsch: Deklarieren für).
Mit diesem Hilfsmittel kann man eine Variable an eine "Elternvariable" knüpfen - An einer späteren Codestelle kann man anschließend über diese wieder auf die "Kindervariablen" zugreifen. So weit so gut, aber wie soll uns das bei funktionenübergreifenden Variablen nützen?
Ganz einfach: Wir knüpfen unsere zu deklarierende Variable an eine Variable, die einfach überall verfügbar ist. Solche Variablen nennt man "globale Variablen" - Maniascript bietet euch standardmäßig folgende globale Variablen an:

NameDatentypBeschreibung
CurrentLocalDateTextText
Achtung: Existiert nicht mehr oder wurde umbenannt
Beispiel: 2011/08/15 15:28:32
CurrentTimeTextText
Achtung: Existiert nicht mehr oder wurde umbenannt
Beispiel: 4:02:18.69
CurrentTimeIntegerDie Anzahl der Sekunden, die seit dem Starten von ManiaPlanet vergangen sind.
MouseLeftButtonBooleanEntspricht True, wenn gerade die linke Maustaste gedrückt ist, ansonsten False.
MouseMiddleButtonBooleanEntspricht True, wenn gerade die mittlere Maustaste gedrückt ist, ansonsten False.
MouseRightButtonBooleanEntspricht True, wenn gerade die rechte Maustaste gedrückt ist, ansonsten False.
KeyUpBooleanEntspricht True, wenn gerade die obere Pfeiltaste gedrückt ist, ansonsten False.
KeyRightBooleanEntspricht True, wenn gerade die rechte Pfeiltaste gedrückt ist, ansonsten False.
KeyDownBooleanEntspricht True, wenn gerade die untere Pfeiltaste gedrückt ist, ansonsten False.
KeyLeftBooleanEntspricht True, wenn gerade die linke Pfeiltaste gedrückt ist, ansonsten False.
KeyReturnBooleanEntspricht True, wenn gerade die Entertaste gedrückt ist, ansonsten False.
KeySpaceBooleanEntspricht True, wenn gerade die Leertaste gedrückt ist, ansonsten False.

Hinweis: Diese Variablen könnt ihr an jeder beliebigen Stelle eures Codes nutzen, ohne sie vorher zu deklarieren oder verfügbar zu machen.

Hinweis: Abhängig von der Anwendung des Skriptes (Manialink, EditorPlugin, ...) existieren noch andere globale Variablen - Diese sind im jeweiligen Kapitel unter "Anwendungen" aufgelistet.


Nun können wir unsere Variable, die in anderen Funktionen verfügbar sein soll (Oben: anzahlSpieler), an eine beliebige dieser globalen Variablen anknüpfen. Dies geschieht bei der normalen Deklarierung dieser Variable (declare), indem man ein for und dem Namen der neuen Elternvariable anhängt:
declare Integer anzahlSpieler for CurrentTime = 0;

Diese Änderung alleine reicht aber nicht - Maniascript würde beim oberen Beispiel wieder mit einem Fehler abbrechen, da die Variable anzahlSpieler in der Funktion spielerAnzahlUmEinsErhoehen immer noch nicht genau deklariert wurde. Doch wir sind schon ein großes Stück weiter:
Mit dieser ersten Änderung haben wir die Variable an eine globale Variable geknüpft, die auch in spielerAnzahlUmEinsErhoehen verfügbar ist - Alles, was wir jetzt noch tun müssen, ist in dieser Funktion sich von der globalen Variable anzahlSpieler wieder zurückzuholen.
Dies geschieht wiederum mit einem declare for, nur dass wir bei dieser Deklaration keinen Wert für die Variable angeben - In diesem Fall wird Maniascript den bereits vorhandenen Wert der Variable so belassen:
declare Integer anzahlSpieler for CurrentTime;

Achtung: Ihr müsst hier selbstverständlich die gleiche globale Variable verwenden, an die ihr die Variable vorher auch angknüpft habt.

TODO: Abschnitt umschreiben, declare for funktioniert nur mit Objekten


Der komplette Code, in dem die Variable anzahlSpieler funktionenübergreifend deklariert und verwendet wird sähe somit so aus:
Void spielerAnzahlUmEinsErhoehen(){
    declare Integer anzahlSpieler for CurrentTime;
    anzahlSpieler = anzahlSpieler + 1;
}

Void meineFunktion(){
    declare Integer anzahlSpieler for CurrentTime = 0;
    spielerAnzahlUmEinsErhoehen();
}

Nach Ausführung von spielerAnzahlUmEinsErhoehen in meineFunktion würde der Wert der Variable anzahlSpieler natürlich um 1 gestiegen sein. Anbei das selbe Schema noch einmal bildlich dargestellt:





Vordefinierte Funktionen
Maniaplanet bietet euch bereits ein paar vordefinierte Funktionen an - Diese könnt ihr problemlos überall in eurem Code verwenden.

NameParameterRückgabe-DatentypBeschreibung
log* wert-Oft will man sich während der Laufzeit bestimmte Werte ausgeben lassen, um zu überprüfen, ob alles wie gewollt läuft oder um eine Fehlerursache aufzuspüren. Hierzu bietet der Maniaplanet-Client einen eigenen Debugger an, der mit Strg + G geöffnet werden kann (Einmal drücken für die Minimalansicht (Nur das Ausgabefenster), zweimal für das vollständige Fenster).
Mithilfe der Funktion log (1 Parameter, kein Rückgabewert) könnt ihr Werte ins Ausgabefenster des Debuggers schreiben:
log(3);
log("Hallo");

Nach Ausführung dieses Codeschnipsels sollten in der Debugger-Ausgabe zwei neue Zeilen stehen – "3" und "Hallo". Die log-Funtion nimmt alle Datentypen als Parameter entgegen, wandelt diesen in einen Text um und gibt ihn aus.
assertBoolean wert-Die Funktion assert besitzt ebenso wie log einen Parameter und keinen Rückgabewert. Dieser muss vom Typ Boolean sein. Entspricht der übergebene Wert True, geschieht nichts – Ist er allerdings False, so wird das gesamte Skript gestoppt, als wäre ein Fehler aufgetreten.
Dies ist vor allem hilfreich, wenn es darum geht, keinen falschen Code ausführen zu lassen – So kann z.B. mit ein paar Aufrufen der assert-Funktion sichergestellt werden, dass keine falschen Werte in Berechnungen aufgenommen werden.
Der folgende Code würde dementsprechend nichts tun:
assert(True);
assert(4 == 4);

Einer der unteren Codes würde allerdings die Ausführung des gesamten Skriptes abbrechen:
assert(5 == 9);

declare Boolean meinZustand = False;
assert(meinZustand);
substringText text, Integer anfang, Integer laengeText teilText
TODO: Mittlerweile in der TextLib verfügbar - Beschreibung muss noch angepasst werden.
Mithilfe der Funktion substring lässt sich ein bestimmter Teil eines Textes extrahieren. Der zurückgegebene Teil beginnt an der Zeichenstelle anfang des übergebenen Textes text an und ist laenge Zeichen lang.

Beispiele:
declare Text spielerName = "destroflyer";

//Würde "destro" zurückliefern
declare Text spielerNameAnfang = substring(spielerName, 0, 6);

//Würde "flyer" zurückliefern
declare Text spielerNameEnde = substring(spielerName, 6, 5);

//Würde "rofl" zurückliefern
declare Text aufDemBodenRollendLachend = substring(spielerName, 4, 4);




Arrays, Lists:
Um dieses Thema nicht zu kompliziert zu beginnen (), werde ich zuerst eine kleine Einführung darin geben, was ein Array überhaupt ist und wofür es sich nutzen lässt:
Oft benötigt man in seinem Programm eine Liste an Werten – Wenn ihr z.B. die Namen aller eurer Strecken in eurem Skript verwenden möchtet, müsstet ihr ja für jeden Namen eine eigene Variable erstellen. Für diesen Fall bieten Programmiersprachen im Normalfall das Hilfsmittel des Arrays an: Ein Array ist eine feste Sammlung an Werten.
In Maniascript basieren Arrays auf dem Key-Value-Prinzip (Fachbegriff: Assoziative Arrays), d.h. jeder Wert im Array (Man spricht von den einzelnen Elementen) besitzt einen individuellen (!) Schlüssel, über den der restliche Code auf dieses Element zugreifen kann.
Der Schüssel und der Wert können jeden beliebigen Datentyp haben (Unabhängig voneinander, jedoch müssen alle Schlüssel untereinander und alle Elemente untereinander denselben Datentyp besitzen!), im Normalfall verwendet man allerdings ganze Zahlen (Integer), die die Reihenfolge der Elemente im Array darstellen – Das erste Element besitzt den Schlüssel 0 (Der Computer beginnt immer bei 0 an, zu zählen – Ihr könntet natürlich auch bei 1 anfangen, ich würde es euch aber nicht empfehlen, da die 0 als Key des ersten Elements einfach der Standard ist ), das zweite Element den Schlüssel 1, das dritte den Schlüssel 2, und so weiter.
In vielen Situationen bietet es sich aber auch an, andere Datentypen als Schlüssel zu verwenden, z.B. Texte. Außerdem kann der Schlüssel ebenso wie der Wert eine Bedeutung haben – Inwiefern ihr das Key-Value-Prinzip nutzt, ist euch überlassen – Man kann sich aber auf jeden Fall eine Menge Arbeit sparen, wenn man mit Arrays umgehen kann.

Wie kann ich Arrays in Maniascript nutzen?
Da es sich bei einem Array letztlich auch nur um eine Variable mit einem speziellen Datentyp handelt, müssen wir lediglich die Deklaration des Variablen-Typs ein klein wenig ändern: Statt des simplen Datentyps wie z.B. "Integer" oder "Boolean" deklariert man einen Array-Typ, indem man zuerst den Datentyp der Elemente schreibt und dahinter in eckigen Klammern [...] den Datentyp der Schlüssel. Ein Array, dessen Werte Texte und dessen Schlüssel Integers sind, erstellt man also folgendermaßen:
declare Text[Integer] meinArray;

Dieses Array wäre momentan aber selbstverständlich noch leer (Keine Elemente) – Wenn man ihm direkt die benötigten Elemente zuweisen will, kann man dies in folgender Schreibweise tun:

[Key1=>Value1, Key2=>Value2, Key3=>Value3, ...]

Es wird also immer zuerst ein Key, dann ein => und schließlich der zugehörige Wert genannt. Diese einzelnen Key-Value-Paare sind durch Kommata , voneinander getrennt sind. Diesen Teil, mitsamt der eckigen Klammen, könnt ihr als Wert verwenden und mithilfe des =-Operators der Variable zuweisen.

Beispiel: Ich möchte gerne ein Array, dessen Keys vom Typ Integer sind und das Booleans als Werte besitzt. In diesem Array sollen folgende Elemente (Key-Value-Paare) enthalten sein:

  • Key: 2, Value: True
  • Key: 5, Value: False
  • Key: 42, Value: True


Das gewünschte Array würde man in Maniascript so formulieren:
declare Boolean[Integer] meinArray = [2=>True, 5=>False, 42=>True];


Array-Zugriff:
Nun haben wir zwar ein Array erstellt, können aber noch nicht damit umgehen. Das erste, was wir dazu lernen müssen, ist das Abfragen einzelner Werte des Arrays. Wie bereits erwähnt, greift man über den (eindeutigen!) Schlüssel auf die entsprechenden Werte zu. Hierzu nennt man ganz normal die Array-Variable und schreibt hinter ihr in eckigen Klammern [...] den Schlüssel des gewünschten Elements. Maniascript erstellt daraus anschließend den gewünschten Wert.
Würde ich also gerne das Element mit dem Schlüssel 42 aus meinem vorher erstellten Array geliefert bekommen, könnte ich dieses folgendermaßen abfragen:
declare Boolean gewuenschtesElement = meinArray[42];

Hierbei muss man natürlich immer besonders auf die Datentypen der Elemente im Array achten.
Auf dieselbe Weise lassen sich auch neue Werte in das Array eintragen bzw. bereits vorhandene überschreiben – Alles, was wir dazu tun müssen, ist dem entsprechenden Arrayeintrag (Mithilfe der eckigen Klammern deklariert) mithilfe des =-Operators einen neuen Wert zuzuweisen:
meinArray[10] = False;

Existiert bereits ein Wert für den Schlüssel, der in den eckigen Klammern angegeben wurde, wird dieser mit dem neuen überschrieben – Falls noch kein Element mit diesem Schlüssel vorhanden ist, wird ein neues Key-Value-Paar innerhalb des Arrays erstellt.
Hinweis: Es würde nichts am Array ändern, den Wert abzufragen, in einer Variable zu speichern (Siehe Beispiel weiter oben) und dieser Variable anschließend einen neuen Wert zuzuweisen. Man würde somit nur diese Variable bearbeiten - Die "Verbindung" zum Array besteht nur, wenn dies explizit mit dem Array-Variablennamen und den eckigen Klammern deklariert wird!


Die Array-Länge / count:
In vielen Situationen benötigt man die Länge (Anzahl der Elemente) eines Arrays - Wenn ich z.B. in einem Array die Logins aller aktuellen Spieler auf meinem Server speichere, kann ich mithilfe durch Länge dieses Arrays die aktuelle Spielerzahl auslesen, ohne dass ich mich darum in einer extra Variable kümmern muss.
Hierfür bietet Arrays die Variable count an (siehe Kapitel: Variablen von Objekten), die immer die aktuelle Länge des zugehörigen Arrays enthält - Sie kann ausgelesen werden, indem man hinter den Arraynamen einen Punkt . und den Variablennamen count schreibt:
declare Text[Integer] spielerLogins = [0=>”destroflyer”, 1=>"xbody", 2=>"hylis"];
declare Integer anzahlSpieler = spielerLogins.count;

Der obere Code würde somit bewirken, dass die Variable anzahlSpieler den Wert 3 enthält (Denn das Array spielerLogins beeinhaltet drei Elemente).

Array-Methoden
Ein Array besitzt in Maniascript auch eigene Methoden (Innere Funktionen) - Diese werden wie innere Variablen durch den Arraynamen gefolgt von einem Punkt . und dem Funktionsnamen (Evtentuelle Parameter wie gewohnt in runden Klammern (...)) aufgerufen.
Anbei eine Tabelle der Methoden, die sich auf jedes Array anwenden lassen:

NameParameterRückgabe-DatentypBeschreibungCode-Beispiel
exists* wertBooleanLiefert True zurück, falls im Array ein Element-Wert mit dem Wert des Parameters wert exisiert. Ansonsten False.
declare Boolean existiertSpielerDestroflyer = spielerArray.exists("destroflyer");
existskey* schluesselBooleanLiefert True zurück, falls im Array ein Element-Schlüssel mit dem Wert des Parameters schluessel exisiert. Ansonsten False.
declare Boolean existiertVierterSpieler = spielerArray.existskey(3);
remove* wertBooleanEntfernt das Element, das den gleichen Wert wie der Parameter wert besitzt. Liefert zurück, ob der Vorgang erfolgreich (True) war oder nicht (False).
declare Boolean spielerEntfernenErfolgreich = spielerArray.remove("hylis");
removekey* schluesselBooleanEntfernt das Element, dessen Schlüssel den gleichen Wert wie der Parameter schluessel besitzt. Liefert zurück, ob der Vorgang erfolgreich (True) war oder nicht (False).
declare Boolean erstenSpielerEntfernenErfolgreich = spielerArray.remove(0);
add* wert-Dem Array wird ein neues Element mit dem Wert des Parameters wert hinzugefügt.
spielerArray.add("xbody");
sort-ArrayEine sortierte Kopie des Arrays wird zurückgegeben (Das betroffene Array selber wird nicht verändert!).
Hinweis: Hierbei wird das Array wird nach den Werten sortiert.
declare Text[Integer] sortierteSpielerArray = spielerArray.sort();
keyof* wert* / ArrayLiefert den Schlüssel eines Elementes mit dem gleichen Wert wie der Parameter wert. Falls kein solches Element existiert, wird ein Array zurückgegeben.
declare Integer schluesselVonDestroflyer = spielerArray.keyof("destroflyer");

Hinweis: Ein Array ist, obwohl es Variablen und Methoden besitzen kann, kein Objekt! (Siehe Kapitel: Klassen, Objekte)





Kontrollstrukturen:
Mit den bereits gelernten Techniken könnt ihr jedoch nur Programme erstellen, die unabhängig von Variablen immer das gleiche tun bzw. die gleichen Befehle nacheinander ausführen. In eigentlich allen Programmiersprachen, darunter auch Maniascript, gibt es aber auch Wege, um das Programm unterschiedliche Wege gehen zu lassen. Damit ist z.B. eine Abzweigung gemeint - Je nach dem, wie ein bestimmter Wert aussieht, soll das Programm einen anderen Codeabschnitt ausführen.
Mittels sogenannter "Kontrollstrukturen" kann man auf diese Weise den Programmablauf beeinflussen – Nicht nur Verzweigungen sind möglich, auch beispielsweise Schleifen, in denen Code mehrmals ausgeführt wird, sind erstellbar. Geschickt ineinander verschachtelt lassen sich mit ihnen viele Probleme geschickt lösen.
Eine Kontrollstruktur besitzt in der Regel einen "inneren Codeblock", der abhängig von der Kontrollstruktur z.B. einmal, mehrmals oder auch gar nicht ausgeführt wird (Es gibt noch weitere Möglichkeiten ). Er wird wie bei Funktionen in geschwungenen Klammern {...} hinter den Namen der Kontrollstruktur deklariert:
Kontrollstruktur{
    //Innerer Code
}

Ebenso können auch Kontrollstrukturen Parameter besitzen, und je nach Wert anders reagieren. Diese werden wie bei Funktionen in runden Klammern (...) angegeben:
Kontrollstruktur(parameter1, parameter2, …){
    //Innerer Code
}

Weitere allgemeine Details möchte ich an diesem Punkt noch nicht erwähnen, sondern bei den jeweiligen Kontrollstrukturen erklären. Ich denke, so ist es einfacher zu verstehen als alle Zusammenhänge auf abstrakter (~ allgemeiner) Ebene zu nennen.

If
Mit der Kontrollstruktur if könnt ihr die bereits genannten "Verzweigungen" des Codes bewirken. Ein if besitzt einen Parameter und ist mit einer Abfrage vergleichbar: Der Parameter vom Typ Boolean wird betrachtet und je nach dem, ob er True oder False entspricht, wird der innere Code des ifs ausgeführt oder nicht:
if(boolscherWert){
    //Innerer Code des if
    //(Wird bei (boolscherWert == True) ausgeführt
}

if ist eine der meistgenutzten Kontrollstrukturen, die Anzahl der Einsatzmöglichkeiten ist nahezu unendlich:
//Ist das Spielermaximum erreicht?
if(anzahlSpieler > spielerMaximum){
    //Spieler wieder vom Server werfen?
}

//Handelt es sich beim Spieler um destroflyer
if(spielerLogin == "destroflyer"){
    //Dem User 1000 Planets überweisen
}



Else
else ist nicht das Gegenteil von if, sondern vielmehr eine Ergänzung (else kann nur in Verbindung mit einem if genutzt werden!). Diese Kontrollstruktur besitzt keine Parameter, sondern nur einen inneren Codeblock. Deklariert man direkt hinter einem if ein else, so wird dessen Code ausgeführt, falls die Abfrage des vorigen ifs fehlschlägt:
if(boolscherWert){
    //Innerer Code des if
    //(Wird bei (boolscherWert == True) ausgeführt
}
else{
    //Innerer Code des else
    //(Wird bei (boolscherWert == False) ausgeführt
}

Mit einem else könnt ihr nun die mehrmals angesprochene Verzweigung erstellen:

//Vorheriger Code
if(spielerLogin == "destroflyer"){
    log("destroflyer ist da.");
}
else{
    log("Jemand, der nicht destroflyer ist, ist da");
}
//Nachfolgender Code

Im oberen Codebeispiel führt das Programm immer zuerst den "vorherigen Code" aus, bis es auf das if trifft – Nun geht es je nach dem, ob die Variable spielerLogin den Wert "destroflyer" enthält oder nicht, entweder den Weg über den Code des ifs oder den des elses, bis der Programmfluss schließlich wieder beim "nachfolgenden Code" zusammenläuft.


While
Ein while stellt in Programmiersprachen wie Maniascript eine klassische Schleife dar. Ebenso wie bei der Kontrollstruktur if wird hier ein bool’scher Ausdruck als Parameter verlangt – Der innere Code wird anschließend so lange ausgeführt wie der Wert des Parameters True ist: (Man sollte darauf achten, dass dies irgendwann nicht mehr der Fall ist - Sonst würd das Programm endlos weiterlaufen )
declare Integer anzahlSpieler = 10;
while(anzahlSpieler > 0){
    anzahlSpieler = anzahlSpieler – 1;
}

Würde man den oberen Code ausführen, würde der innere Code des whiles genau zehn Mal ausgeführt werden – Die Variable anzahlSpieler (Startwert: 10) wird bei jedem Durchlauf um 1 verringert, was zwangsläufig dazu führt, dass sie einen negativen Wert bekommt (10 -> 9 -> 8 -> ... -> 2 -> 1 -> 0 -> -1). Somit ergibt der bool’sche Ausdruck, der als Parameter für das while benutzt wird, ab diesem Punkt False und die Schleife wird abgebrochen.
Lest euch den oberen Abschnitt noch einmal genau durch, falls ihr etwas nicht verstanden habt, denn Schleifen sind essentiell für größere Programme – Fast immer, wenn ihr große Datenmengen (Stichwort: Arrays) besitzt, seid ihr darauf angewiesen, dass euer Programm automatisch die vielen Schritte erledigt.

Mit einem while kann man jedoch auch gezielt eine Endlosschleife (Schleife, die niemals unterbrochen wird) erzeugen. Dazu kann man einfach als Parameter den Wert True übergeben, der ja bekanntlich niemals False ergeben kann:
while(True){
    //Endlosschleife
}



For
for ist lediglich eine leicht abgewandelte Version des whiles – Hier gebt ihr nicht an, wie lange der Code ausgeführt wird, sondern wie oft. Hierfür verlangt for drei Parameter: Eine Variable (Auch Schleifenvariable genannt, meist wird hier die Variable i genutzt) und zwei Integers, den Start- und den Endwert.
Das Ganze funktioniert anschließend so:

1.) Maniascript weißt der von euch angegebenen Variable den übergebenen Startwert zu
2.) Nun wird überprüft, ob die Schleifenvariable bereits einen höhere Wert als den Endwert enthält
2.1.) Ja - Schleife abbrechen
2.2.) Nein - Inneren Code ausführen, den Wert der Schleifenvariable um 1 erhöhen und wieder zurück zu Schritt 2.)

Mit anderen Worten: Die Differenz ((Endwert+1) – Startwert) entspricht der Anzahl, wie oft der innere Code ausgeführt werden soll. Vorteil hierbei ist, dass ihr innerhalb des fors natürlich die Schleifenvariable abfragen und verarbeiten könnt:
for(i, 0, 10){
    log(i);
}

Der obere Code würde euch zehnZeilen in der DebuggerKonsole ausgeben – Zuerst "0”, dann "1”, dann "2”, und so weiter bis "10”.
Hinweis: Für (Schleifenvariable = EndWert) wird der innere Code nicht ausgeführt, da bei dieser Konstellation die Schleife in Schritt 2.) abgebrochen wird

Selbstverständlich könnt ihr auch während der Schleife den Wert der Schleifenvariable ändern – Maniascript wird euren Code immer nach dem oberen Schema ausführen – Achtung: Wenn ihr die Schleifenvariable innerhalb der Schleife modifiziert, achtet darauf, keine (ungewollten) Endlosschleifen zu erzeugen.

Maniascript bietet dem Programmierer auch die Wahl, das Schleifenintervall selbst feszulegen - Hierbei handelt es sich um die Zahl, die nach jedem Durchlauf auf die Schleifenvariable addiert wird, standardmäßig 1. Hierzu gibt man einfach einen vierten Parameter (Datentyp: Integer) an:
//Schleifenintervall = 2
for(i, 0, 10, 2){
    log(i);
}

Somit würde hier nur jede zweite Zahl ausgegeben werden, da die Schleifenvariable immer um 2 hochgezählt wird, bis sie einen größeren Wert als 10 enthält.

Foreach
Die foreach-Kontrollstruktur ist wie while und for eine Schleifenart – Jedoch ist sie speziell auf Arrays zugeschnitten. Wie bereits erwähnt, spielen Arrays bei großen Datenmengen eine Rolle – Und hierzu gehören selbstverständlich auch passende Schleifen wie foreach, die durch das komplette Array iterieren. Dieser Begriff (iterieren) wird euch in diesem Tutorial noch häufiger begegnen - Er bedeutet so viel wie "durch das Array laufen und jeweils Element für Element betrachten".
Die foreach-Schleife iteriert nun also durch das Array, speichert ein Element in einer Variable ab und führt den inneren Code aus (Der auf diese Variable natürlich zugreifen kann ) - Dies wird einmal für jedes Element im Array durchgeführt. (In chronologischer Reihenfolge (Reihenfolge, in der die Elemente eingefügt wurden))
Die Syntax der Parameter für die foreach-Schleife weicht ein wenig vom Standard ab: Die Kontrollstruktur benötigt 2 Parameter: Das Array und die Variable, in der das jeweilige Element gespeichert wird. Deklariert wird diese Kontrollstruktur wie folgt:
foreach(aktuellesElement in meinArray){
    //Innerer Code
}

Wie ihr seht, schreibt man in die runden Klammern (...) zuerst den Namen der Variable für das zu aktuelle Element, gefolgt von einem in und dem Namen des Arrays.

Beispiel: Nehmen wir an, wir hätten ein Array, in dem wir die Logins von ein paar Spielern gespeichert haben – Zum Beispiel so:
declare Text[Integer] spielerLogins = [0=>”destroflyer”, 1=>"xbody", 2=>"hylis"];

Nun wollen wir alle diese Logins auf der DebuggerKonsole ausgeben lassen – Die Lösung ist wie immer denkbar einfach: Wir iterieren mithilfe einer foreach-Schleife durch das Array und geben im inneren Code der Kontrollstruktur das jeweilige Element (Hier: Der jeweilige Login) aus:
declare Text[Integer] spielerLogins = [0=>”destroflyer”, 1=>"xbody", 2=>"hylis"];
foreach(aktuellerLogin in spielerLogins){
    log(aktuellerLogin);
}

Nach Ausführung würdet ihr drei neue Zeilen in der Debugger-Ausgabe sehen: "destroflyer", "xbody" und "hylis".

foreach unterstützt aber auch das Abfragen der Schlüssel und nicht nur der Werte – Wollt ihr in eurem inneren Code auch den Schlüssel des aktuellen Elements verfügbar haben, deklariert ihr die Schleife einfach folgendermaßen:
foreach(aktuellerSchluessel => aktuellesElement in meinArray){
    //Innerer Code
}

Ihr fügt also lediglich den Namen der Variable, in dem der jeweils aktuelle Schlüssel gespeichert werden soll und ein => vorne in die runden Klammern (...) ein.
Um beim oberen Beispiel mit den Spieler-Logins zu bleiben - Wir könnten hiermit nun auch den entsprechenden Schlüssel des Login-Elements im Array ausgeben lassen:
declare Text[Integer] spielerLogins = [0=>”destroflyer”, 1=>"xbody", 2=>"hylis"];
foreach(aktuellerSchluessel => aktuellerLogin in spielerLogins){
    log(aktuellerSchluessel ^ ": " ^ aktuellerLogin);
}

Somit würden wir folgende drei Zeilen im Debugger loggen: "0: destroflyer", "1: xbody", "2: hylis".


Switch
Ein switch ist im Gegensatz zu den vorigen Kontrollstrukturen relativ speziell – Im Grund besteht er aus einer Reihe von Abfragen, die euch bei einer Fallunterscheidung helfen können. Hier wird nur ein Parameter verlangt: Der Ausdruck (z.B. eine Variable oder ein Vergleich), der untersucht werden soll.
Maniascript vergleicht anschließend den Wert dieses Ausdrucks mit einer Reihe von angegebenen Möglichkeiten. Welche Möglichkeiten es allerdings gibt und wie das Programm auf sie reagieren soll, bestimmt ihr selbstverständlich. (Die Kontrollstruktur übernimmt lediglich die Arbeit der vielen Vergleiche)
Man spricht hier bei den erwähnten Möglichkeiten von den sogenannten "Fällen" (Deutsch: Fall, Englisch: case). Im inneren Code definiert ihr folgendermaßen alle Fälle, die ihr benötigt und welcher Code bei welchem Fall ausgeführt werden soll:
switch(anzahlSpieler){
    case 0:{
        //Programmcode Nr.1
    }
    case 27:{
        //Programmcode Nr.2
    }
    case 42:{
        //Programmcode Nr.3
    }
}

Wie ihr vielleicht bereits erahnen könnt, gebt ihr die verschiedenen Fälle mit case an, gefolgt von dem möglichen Fall und einem Doppelpunkt :. Der anschließende Codeblock (Innererhalb der geschwungenen Klammern {...}) wird ausgeführt, sofern der zu untersuchende Ausdruck denselben Wert wie der deklarierte Fall besitzt.
Würde die Variable anzahlSpieler also den Wert 0 besitzen, würde "Programmcode Nr.1" ausgeführt werden. Hätte sie dagegen den Wert 27, würde Maniascript den "Programmcode Nr.2" ausführen und so weiter...
Diese Kontrollstruktur ist besonders hilfreich, wenn eine Vielzahl an Möglichkeiten für eine Variable existieren und auf jeden dieser möglichen Fälle anders reagiert werden muss.

Für den Fall, dass der aktuelle Wert des übergebenen Ausdrucks nicht von euch deklariert wurde, passiert bei der Ausführung des switches nichts. Falls ihr aber wollt, dass in einem solchen Fall (Der ja vielleicht beabsichtigt ist) ein "Standard-Code" ausgeführt wird, könnt ihr folgendes schreiben:
switch(anzahlSpieler){
    case 0:{
        //Programmcode Nr.1
    }
    case 42:{
        //Programmcode Nr.2
    }
    default:{
        //Programmcode Nr.3
    }
}

Deklariert wird ein solcher "Standardfall" mit dem Schlüsselwort default (Englisch: default, Deutsch: Standard)). Würde der Wert der Variable anzahlSpieler also weder 0 noch 42 sein, würde immer der "Programmcode Nr.3" ausgeführt werden.
Achtung: Bei einem switch muss mindestens 1 möglicher Fall deklariert sein - Andernfalls liefert der Compiler einen Fehler.



Direktiven
Direktiven bezeichnen in Maniascript spezielle Zeilen am Anfang eines Skriptes. Eine Direktive startet immer mit einer Doppelkreuz # und ist einzeilig. Es existieren folgende Direktiven:

DirektiveBeschreibung
#RequiredContext benoetigterKontextDer benötigte Kontext des Skriptes. Dieser kann angegeben werden, um zu verhindern, dass das Skript an der falschen Stelle ausgeführt wird, z.B ein EditorPlugin als GameMode
#Const name wertDeklariert eine Konstante namens name, deren Wert wert entspricht. Der Wert einer Konstanten kann während des Skriptes nicht verändert werden.
#Setting parameter wertAus Sicht des Skriptes, besitzt #Setting dieselbe Wirkung wie #Const - Eine Konstante namens parameter mit dem Wert wert wird angelegt.
Werte, die allerdings mit #Setting angegeben wurden, können von außerhalb des Skriptes verändert bzw. eingegeben werden. (Englisch: Setting, Deutsch: Option)
#Include "scriptName" as nameLädt die Programmbibliothek oder Datei namens scriptName und bindet ihre Funktionen an den Namensraum name.

Hinweis: Diese Zeilen stellen keine noramlen Programmbefehle dar und benötigen dementsprechend kein Semikolon ; am Ende der Zeile.

TODO: Codebeispiele für die verschiedenen Direktiven



Skripte anhalten:
Maniascript bietet euch mithilfe des Schlüsselwort yield einen Befehl, der das Programm für die kleinstmögliche Zeiteinheit anhält und die Anzeige, z.B. den Manialink, aktualisiert: (In dieser Zeit könnt ihr auf keine Events oder ähnliches reagieren!)
yield; //Das Skript hält kurz an und aktualisiert die Anzeige

Auf den ersten Blick mag die kleine "Pause" wenig Sinn haben, doch wenn ihr diesen Befehl mit ein paar geschickten Kontrollstrukturen kombiniert, könnt ihr nette Effekte erzielen.
Auf diese Weise bietet uns Maniascript bereits zwei vordefinierte Funktionen, die auf dem yield-Befehl basieren (Oder zumindest mit diesem erklärt werden können ).

sleep
Die sleep-Funktion (Kein Rückgabewert) besitzt einen Parameter vom Typ Integer - Dieser stellt die Anzahl Millisekunden dar, die das Skript anhalten soll. Folgender Aufruf würde die Ausführung des Programms somit genau eine Sekunde lang anhalten:
sleep(1000);

Laut Nadeo lässt sich der genaue Ablauf im Inneren der Funktion sleep so erklären:
Void sleep(Integer dauerInMillisekunden){
    Start = Now;
    while(Now < Start + dauerInMillisekunden){
        yield;
    }
}

Wie ihr seht, hält diese Funktion das Skript so lange immer ein kleines Stückchen an (per yield), bis die übergebene Zahl an Millisekunden vergangen ist.


wait
Mithilfe von wait könnt ihr euer Skript so lange stoppen, bis eine bestimmte Bedingung erfüllt ist, also ein von euch übergebener bool'scher Ausdruck True ergibt. Dieser bool'sche Ausdruck ist der einzige Parameter der wait-Funktion, die ebenso wie sleep keinen Wert zurückliefert.

Als kleines Beispiel nehme ich eine Eingabefläche für den User - Wir haben bereits eine Funktion sindAlleTextfelderAusgefuellt (ohne Parameter) geschrieben, die einen Boolean zurückliefert. Dieser sagt aus, ob der User alle Textfelder ausgefüllt hat (Wie genau das funktioniert, interessiert uns an diesem Punkt gar nicht).
Nun wollen wir, dass das Skript direkt nach der letzten Eingabe des Users weiter ausgeführt wird, ohne dass erst ein Button oder ähnliches gedrückt werden muss. Die Lösung ist relativ simpel: Wir benutzen die wait-Funktion und übergeben ihr als Parameter die Funktion sindAlleTextfelderAusgefuellt.
Maniascript wird anschließend das aktuelle Programm solange unterbrechen, bis die Funktion sindAlleTextfelderAusgefuellt den Wert True zurückliefert.
//Manialink ist geladen
wait(sindAlleTextfelderAusgefuellt());
//Eingaben auswerten

Hinweis: wait berechnet natürliches ebenso wie die Kontrollstrukturen while oder for den übergebenen bool'schen Ausdruck jedes Mal neu. Beachtet daher, dass Funktionen, die in euren Ausdrücken vorkommen, evtl. sehr oft aufgerufen werden!

Auch für wait bietet Nadeo eine offizielle Erklärung mithilfe des yield-Befehls:
while(!boolscherAusdruck){
    yield;
}



Klassen, Objekte:
Oft werden die eigenen Programme so komplex, dass man bestimmte Zusammenhänge und Werte nicht mehr in einfachen Variablen speichern kann. Nehmen wir beispielsweise eine Userliste: Das Programm soll eine Liste der aktuell eingeloggten User, ihren Profilbildern und ihrer Email-Adresse anzeigen – Wer fleißig den vorigen Teil des Tutorials gelesen hat, dem fällt bestimmt sofort das Stichwort "Array" ein. Klar, denn wir könnten die User in einem Array speichern... Doch wenn wir genauer nachdenken, fällt uns auf, dass wir pro User aber drei Einträge (Login, Profilbild, Email) und nicht nur einen benötigen. Wir könnten zwar ein paar Arrays verschachteln, aber das würde das Problem bei der nächsten Änderung des Codes nur noch verschlimmern. Die Lösung für solche Situationen, in denen mehrere Variablen zu einem einzigen Objekt zusammengefasst werden sollen, heißt "Objektorientierte Programmierung" (OOP):
Das Grundkonzept der objektorientierten Programmierung besteht darin, Klassen zu definieren. Eine Klasse stellt einen "komplexen" Objekttyp dar – Es könnte also z.B. eine Auto-, eine Server- oder eine User-Klasse geben. Nachdem wir eine solche Klasse definiert haben, können wir problemlos Variablen dieses Typs erstellen, beispielsweise eine User-Variable (So könnten wir im oberen Beispiel unser Array mit Objekten unserer User-Klasse befüllen).

Wir erschaffen auf diese Weise anders gesagt eigene Variablentypen. Der Vorteil hierbei ist, dass wir die Eigenschaften unserer Klassen selber festlegen – Wir definieren (!) also bei der Auto-Klasse im wahrsten Sinne des Wortes, was für das Programm ein "Auto" sein soll. Dies geschieht, indem wir der Klasse beliebig viele Variablen zuweisen können, wir könnten also sagen: Ein Objekt der Klasse Auto besteht aus:

  • Name (Text)
  • Höchstgeschwindigkeit (Integer)
  • Hersteller (Text)

Wenn wir jetzt später im Code eine Variable vom Typ Auto erstellen, besitzt diese automatisch in ihrem Inneren diese drei Variablen Name, Höchstgeschwindigkeit und Hersteller, auf die wir nun zugreifen können.
Überall, wo Variablen zusammengehören, kann man also Klassen definieren, um sich selber das Handling zu erleichtern und andererseits, um die Zusammenhänge zwischen den einzelnen Werten genau festzulegen. Besonders bei größeren Programmen ist es sehr wichtig, objektorientierte Programmierung richtig einzusetzen, da man sich sonst in einem langgezogenen Code wiederfindet, der alle möglichen Variablen erst einzeln abfragen muss, diese auf irgendeine noch kompliziertere Weise verarbeitet und am Ende versucht, das ganze relativ normal aus- bzw. zurückzugeben – Informatiker sprechen hierbei vom sogenannten "Spaghetti-Code".

Deklarieren einer Klasse:
Momentan bietet Maniascript noch keine Möglichkeit, eigene Klassen zu erstellen - Die bereits vorhandenen (vordefinierten) Klassen können jedoch problemlos genutzt werden.

Zugriff auf Objekte:
Mithilfe eines Punktes . könnt ihr auf Eigenschaften (Variablen) und Methoden (Funktionen) eines Objektes zugreifen - Dazu schreibt ihr ihn hinter den Namen des Objektes, gefolgt vom Aufruf der gewünschten Variable bzw. Funktion:
meinObjekt.anzahlSpieler = 11;
meinObjekt.spielerAnzeigeFunktion();


Maniascript-Anwendungen:
Ab diesem Punkt widmen wir uns dem spannenderen Teil des Tutorials - Denn selbstverständlich würde all dies, die komplette Syntax, der professionelle Sprachaufbau etc. nur wenig Sinn machen, wenn man nichts mit Maniascript anfangen könnte. Aus diesem Grund basiert Maniaplanet selber (!) zu einem gewissen Teil auf Maniascript.
Dies hat den Vorteil, dass von euch geschriebene Skripte sich quasi überall einklinken können - Sei es im Startmenü, im MediaTracker, auf einem Manialink oder gar ein selbst geschriebener Spielmodus. Die Möglichkeiten sind nahezu unbegrenzt und man kann in Zukunft sicher noch mehr erwarten.
In diesem Tutorial findet ihr die aktuell bekannten Anwendungsmöglichkeiten für Maniascript - Es wird stets versucht, diese Liste aktuell zu halten.




Allgemein:
Der folgende Abschnitt stellt eine Auflistung verschiedener Hinweise dar, die ihr bei jeder Anwendung von Maniascript beachten solltet.

main()
Maniaplanet bietet uns zwei Möglichkeiten, ein Skript in den jeweiligen Kontext einzufügen - Falls das Skript relativ simpel ist und nicht in mehrere Funktionen etc. unterteilt ist, können wir die benötigten Befehle direkt hinschreiben. (An welcher Stelle, ist von der Anwendung (z.B. ob es sich um einen Manialink oder ein EditorPlugin handelt) abhängig, spielt hierfür aber keine Rolle )
Einfacher Code wie dieser kann also direkt hingeschrieben werden:
declare Integer anzahlSpieler = 5;
anzahlSpieler = anzahlSpieler + 1;
log(anzahlSpieler);

In diesem Fall wird unser Skript direkt nach dem Ladevorgang des Skriptes ausgeführt (Das obere Programm würde die Zeile "6" auf der DebuggerKonsole ausgeben ). Diese Methode ist relativ hilfreich für einzelne Befehle oder kurze Skripte, die keine weitere Unterteilung benötigen.

Wenn euer Code jedoch weitaus komplexer ist, bietet sich die main-Funktion an - Mehr noch, sobald ihr mindestens 1 Funktion in eurem Code erstellen wollt, müsst ihr diese Variante nutzen!
main stellt eine Funktion ohne Parameter oder Rückgabedeklaration dar und wird von Maniaplanet direkt nach Laden ausgeführt:
Integer plusEins(Integer zahl){
    return (zahl + 1);
}

main(){
    declare Integer anzahlSpieler = 5;
    anzahlSpieler = plusEins(anzahlSpieler);
    log(anzahlSpieler);
}

Dieser Manialink würde ebenso die Zeile "6" im Debugger ausgeben.
Achtung: Die main-Funktion besitzt im Gegenteil zu sonstigen Funktionen keine Deklaration des Rückgabewertes!
(Funktionen müssen normalerweise mit dem Schlüsselwort Void eindeutig deklarieren, dass sie keinen Wert zurückliefern)

Achtung: Bei dieser Methode darf kein Code außerhalb einer Funktion stehen.





Maniascript in Manialinks:
Wie bereits erwähnt, bietet Maniaplanet auch eine Möglichkeit an, Maniascript direkt in Manialinks einzubinden. Doch was genau soll man mit einem Skript dort bewirken? Die Antwort liegt auf der Hand: Interaktivität.
Maniaplanet stellt eurem Skript eine bereits vordefinierte Sammlung an Variablen, Methoden und Events zur Verfügung, über die ihr den Manialink steuern könnt. Sei es, um die Position oder Hintergrundgrafik eines Elementes zu ändern, den Text einer Nachricht zu modifizieren oder ein eigenen Minispiel zu programmieren.
Doch bevor ich erkläre, wie genau ihr euer Skript in den Manialink einfügt, werde ich auf die grundlegenden Dinge eingehen, die ihr benötigt, um vom Programm aus auf den Manialink zuzugreifen.
Hinweis: Wer sich bereits mit Javascript und dem Handling eines DOMs auskennt, wird hier vieles wiederfinden.

Hinweis: Ich werde in diesem Tutorial nicht auf den Aufbau eines Manialinks oder die entsprechende XML-Syntax eingehen - Ich empfehle euch, sofern noch nicht gelesen, zuerst Marcels Manialink-Tutorial zu betrachten.


Verfügbare Klassen / Manialink-Elemente:
Wie ihr bereits wisst, gibt es viele Arten von Manialink-Elementen - Da wären Labels, Quads, Entries und noch viele mehr.
Nadeo hat sich bereits für uns die Mühe gemacht, jeweils eigene Klassen für diese Elemente zu schreiben und diese mit schönen Variablen und vorgefertigten Methoden auszustatten.
In der Regel fängt eine solche Klasse für ein Manialink-Element mit "CGameManialink" an, gefolgt vom jeweiligen Element-Typ, z.B. "Label". Momentan existieren folgende Klassen:

CGameManialinkControl
Die Klasse CGameManialinkControl stellt die Elternklasse aller Manialink-Element-Klassen dar - Sie beeinhaltet die Grundeigenschaften, die jedes positionarbare Element auf einem Manialink haben kann.

Variablen:
NameDatentypBeschreibung
ControlCControlBase
IdTextDie ID des Manialink-Elementes.
PosnXRealDie (zum Elternelement) relative X-Koordinate des Manialink-Elementes.
PosnYRealDie (zum Elternelement) relative Y-Koordinate des Manialink-Elementes.
PosnZRealDie (zum Elternelement) relative Z-Koordinate des Manialink-Elementes.

Methoden:
NameParameterRückgabe-DatentypBeschreibung
Hide--Macht das Element auf dem Manialink unsichtbar.
Show--Macht das Element auf dem Manialink sichtbar.
Unload--Löscht das Element komplett vom Manialink. (Ein anschließender Aufruf des Objektes resultiert in einem Error!)


CGameManialinkFrame
Spoiler: Anzeigen...



CGameManialinkQuad
Spoiler: Anzeigen...


CGameManialinkLabel
Spoiler: Anzeigen...


CGameManialinkEntry
Spoiler: Anzeigen...


CGameManialinkFileEntry
Spoiler: Anzeigen...


Die Page-Variable:
Zwar kennen wir jetzt die einzelnen Klassen, über die wir die Manialink-Elemente modifizieren können, uns fehlt aber immer noch die wirkliche Schnittstelle zum Manialink (Der Punkt, an dem wir endlich auch mal ein solches Objekt geliefert bekommen ).
Hierzu bietet Maniaplanet uns unter anderem die Page-Variable an - Sie ist überall (!) verfügbar und stellt im Prinzip dem gesamten Manialink als Objekt der Klasse CGameManialinkPage dar.
Mithilfe der Page-Variable können wir beispielsweise Elemente über ihre ID (XML-Attribut: id) ansprechen oder das DOM (Die "Baum-Struktur" ) des Manialinks durchsuchen.
Hinweis: Das Javascript-Pendant zu Page ist document.


Variablen und Methoden
Spoiler: Anzeigen...


Das Controls-Array:
Da das Manialink-Element <frame> natürlich innere Elemente besitzt bzw. besitzen kann, bietet ein CGameManialinkFrame-Objekt dem Programmierer standardmäßig ein Array zur Verfügung, das dem Aufbau des Manialinks entspricht (Die XML-Struktur wird im Array mithilfe von Verschachtelungen wiedergespiegelt). Die einzelnen Elemente dieses Arrays sind die auf dem Manialink existierenden Elemente, die eine von CGameManialinkControl abgeleitete Klasse (siehe oben) besitzen.
Um diesen Aufbau nocheinmal bildlich zu erklären, hier ein kleiner Beispiel-Manialink:
<manialink version="1">
    <label posn="0 0 0" text="$oMein Manialink"/>
    <quad posn="-160 90 -10" sizen="320 180" bgcolor="000F"/>
    <frame posn="0 -10 0">
        <quad posn="0 0 0" sizen="60 10" halign="center" valign="center" bgcolor="09FF"/>
        <label posn="0 0 0" halign="center" valign="center" text="Hallo"/>
    </frame>
    <label posn="-155 -85 0" valign="bottom" text="$iDies ist ein Test-Manialink"/>
</manialink>

Am einfachsten ist es, sich hier das Objekt Page.MainFrame zu betrachten - Dieses ist wie gesagt das Wurzelelement selber als Frame dargestellt und beeinhaltet somit die inneren Manialink-Elemente.
Das entsprechende Page.MainFrame.Controls-Array würde folgendermaßen aussehen:

Page.MainFrame: Objekt (CGameManialinkFrame){
    Controls: Array{
        [0] => Objekt (CGameManialinkLabel)
        [1] => Objekt (CGameManialinkQuad)
        [2] => Objekt (CGameManialinkFrame){
            Controls: Array{
                [0] => Objekt (CGameManialinkQuad)
                [1] => Objekt (CGameManialinkLabel)
            }
        }
        [3] => Objekt (CGameManialinkLabel)
    }
}

Hinweis: Alle Objekte, die dem Manialink-Element <frame> entsprechen, beeinhalten eine solche Variable Controls (Array), über die man auf die inneren Elemente (der ersten, darunter liegenden "Ebene") zugreifen kann - So entsteht letzendlich in einem Controls-Array die der Manialink-Struktur entsprechende Verschachtelung (Durch beliebig viele Schichten an Frames, die wiederum andere Frames enthalten können)



Event-Handling:
Da Maniascript aber auch für Interaktivität in Manialinks gedacht war, können wir per Skript auf Events reagieren - Ein Event ist eine vom User ausgelöste Situation, z.B. ein Mausklick, ein Tastendruck oder wenn der User mit dem Cursor über ein bestimmtes Element fährt.
Maniaplanet besitzt auch hier eine eigene Klasse für Events: CGameManialinkScriptEvent. Diese beeinhaltet in folgenden Variablen genauere Informationen zum jeweiligen Event:

NameDatentypBeschreibung
TypeEnumDie Variable Type enthält den Typ des Events, also ob es sich beispielsweise um einen Mausklick oder einen Tastendruck handelt. Sie kann folgende Werte haben: (Die untere Liste stellt somit die verfügbaren Events in Manialinks dar)
  • CGameManialinkScriptEvent::Type::MouseClick
  • CGameManialinkScriptEvent::Type::MouseOver
  • CGameManialinkScriptEvent::Type::MouseOut
  • CGameManialinkScriptEvent::Type::KeyPress
ControlIdTextFalls es sich um eines der Maus-Events (MouseClick, MouseOver, MouseOut) handelt, enthält diese Variable das id-Attribut des Manialinkelements, das das Event ausgelöst hat. Falls dieses Element kein id-Attribut besitzt, enthält sie den Wert "Unassigned".
CharPressedTextFalls es sich um eines der Tasten-Events (KeyPress) handelt, enhält diese Variable eine eindeutige Nummer, die die Taste darstellt, die das Event ausgelöst hat.


Event-Abfrage / PendingEvents:
Selbstverständlich muss euch Maniaplanet eine Möglichkeit bieten, die aktuell ausgelösten Events abzufragen. Hierzu könnt ihr die Variable PendingEvents benutzen, die ein stets aktuelles Array der gerade ausgelösten Events enthält. Die einzelnen Elemente in diesem Array sind Objekte einer der oben genannten Event-Klassen, z.B. CGameManialinkScriptEvent::Type::MouseClick.

In der Regel müsst ihr während der Laufzeit durch dieses Array iterieren (es Element für Element durchlaufen) und jedes Event einzeln behandeln (Denn es können ja auch mehrere Events gleichzeitig ausgelöst werden ). Hierzu kommen euch zwei der gelernten Kontrollstrukturen zur Hilfe: foreach und switch.
Mithilfe der foreach-Schleife iteriert ihr durch das PendingEvents-Array und untersucht nun für jedes einzelne Event (Zwischengespeichert in Event) dessen Typ (Variable Type des Objekts, siehe oben) - Die verschiedenen Möglichkeiten, also Event-Typen, (die für euer Skript eine Bedeutung haben) könnt ihr dann mit einem switch unterscheiden:
foreach(Event in PendingEvents){
    switch(Event.Type){
        case CGameManialinkScriptEvent::Type::MouseClick:{
            //Dieser Code wird ausgeführt, wenn gerade ein Mausklick ausgelöst wurde
        }
        case CGameManialinkScriptEvent::Type::KeyPress:{
            //Dieser Code wird ausgeführt, wenn gerade eine Taste gedrückt wurde
        }
    }
}



Die Event-Schleife:
Wie ihr sicherlich bereits vermutet habt, bringt es euch nicht wirklich viel, einmal das aktuelle PendingEvents-Array zu durchlaufen. Wer weiß, ob genau in diesem Bruchteil einer Sekunde, in der ihr diese Variable abfragt, ein Event ausgelöst wurde?
Aus diesem Grund verwendet man in Programmen eine sogenannte "Event-Schleife" (In Spielen auch "Game-Loop" genannt) - Diese ist im Grunde genommen eine Endlosschleife, die nichts anderes macht als ständig abzufragen, ob Events ausgelöst wurden, gegebenenfalls auf diese zu reagieren und anschließend die Anzeige zu aktualisieren (Endlosschleife: while mit Parameter True, Anzeige aktualisieren: yield).
Eine einfache Event-Schleife sähe somit so aus:
while(True){
    foreach(Event in PendingEvents){
        //Das aktuelle Event untersuchen, z.B. mit switch(Event.Type){ ... }
    }
    yield;
}

Hinweis: Dieser Code tut nichts anderes als ständig das Array PendingEvents auf Inhalte zu durchsuchen und die Anzeige zu aktualisieren - Beachtet daher, dass euer Skript anschließend nur noch in dieser Schleife agieren kann!
Eine solche Endlosschleife mag auf den ersten Blick keine elegante Lösung sein, doch sie ist die einzige Möglichkeit, zu einem beliebigen (!) Zeitpunkt auf ein Event zu reagieren.

Achtung: Achtet immer darauf, dass ihr innerhalb eurer Event-Schleife ein yield verwendet! Falls dies nicht der Fall ist, würde das Skript endlos weiterlaufen, ohne dass irgendeine Anzeige beim User aktualisiert wird - Dieser hätte dann den Eindruck, dass sich das Spiel aufgehängt hat bzw. "eingefroren" (Englisch: Freeze) ist.


Maniascript-Integration / <script>:
Nachdem ihr nun wisst, wie ihr von Maniascript aus auf den Manialink, dessen Elemente und ausgelöste Events zugreift, müsst ihr ein solches Skript nur noch einfügen. In Manialinks geschieht dies mithilfe des <script>-Elementes.
Dieses wird wie ein normales Element in die XML-Struktur eingefügt, wobei das eigentliche Skript innerhalb des <script>s geschrieben wird:
<manialink version="1">
    <script><!--
        //Das Skript
    --></script>
</manialink>

Hinweis: Um das XML-Dokument valide zu halten, wird der gesamte Code innerhalb des <script>s als XML-Kommentar <!--...--> gekennzeichnet


Um noch einmal die beiden verschiedenen Varianten zum Einfügen eines Skriptes (Stichwort: main) aufzugreifen, sind hier zwei eingefügte Skripte, die exakt die selbe Wirkung hätten:
<manialink version="1">
    <script><!--
        declare Integer anzahlSpieler = 5;
        anzahlSpieler = anzahlSpieler + 1;
        log(anzahlSpieler);
    --></script>
</manialink>

<manialink version="1">
    <script><!--
        main(){
            declare Integer anzahlSpieler = 5;
            anzahlSpieler = plusEins(anzahlSpieler);
            log(anzahlSpieler);
        }
        
        Integer plusEins(Integer zahl){
            return (zahl + 1);
        }
    --></script>
</manialink>

Wie ihr seht, kann ich wie bereits erwähnt, den Code direkt in den Script-Tag schreiben oder diesen mithilfe von Funktionen verschachteln. Im letzteren Fall ruft Maniaplanet die Funktion main nach Ladevorgang des Manialinks automatisch auf.




EditorPlugins:
In Arbeit...


Aufgabe: Schreibe ein Skript, das blabla blubb di bumm.
Spoiler: Anzeigen...