Projekt:Adventure 2.0/Autoren-Handbuch/Scripting-Anleitung

Bei Fragen oder Problemen am besten an Kamel:J* wenden, der das hier alles verbockt hat.

Im Adventure2 gibt es 2 Arten von Unterseiten: Die Spielseiten und die Item-Seiten:

Spiel- und Item-Seiten
Die Spielseiten werden (mehr oder weniger fortlaufend) durchnummeriert. Bitte die Vorlage:Adventure2/Seite verwenden! Das Bild sollte 550x300px groß sein, oder zumindest das richtige Seitenverhältnis haben. Mit Hilfe der imagemap-Extension können da drin auch gleich Bereiche definiert werden, mit denen man später irgendwas anstellen können soll. Dabei werden einfach die Links so gesetzt, dass sie nicht auf eine Wikiseite zeigen, sondern stattdessen mit "#" beginnen, gefolgt von irgendeinem Bezeichner. Wie auch sonst fast für alles, sind als einzige Zeichen für den Bezeichner die Kleinbuchstaben und der Unterstrich erlaubt.

Ein guter Online-Editor für das Zeug ist. Den Code findet man dann unten auf der Seite (ganz einfach bei "Code" aufklappen - ich habs da zuerst übersehen).

Die Itemseiten heißen einfach "item/" gefolgt vom Namen des Items in Kleinbuchstaben. Auch auf die Itemseite gehört ein Bild (50x50 Pixel oder wenigstens quadratisch, wenn's geht transparent). Bitte die Vorlage:Adventure2/Item verwenden!

Auf beiden Seitenarten können hinter dem Bild Ereignisse (sog. Events) festgelegt werden, die steuern, wie sich der Spieler durch's Adventure bewegen kann. Ereignisse sollten immer auf der Seite platziert werden, zu der sie gehören. Ereignisse auf Spielseiten können nur aufgerufen werden, wenn der Spieler sich auf der entsprechenden Seite befindet, Ereignisse auf Itemseiten nur dann, wenn der Spieler das Item besitzt.

Ereignisse
Die Ereignisse Werden mit der Vorlage:A2Event eingebunden. Da hinein kommt dann der Text für die Ereignis-Definition in der extra dafür entwickelten Mini-Programmiersprache A2l. Beim Drücken auf Vorschau und nach dem Abspeichern wird der Programmcode auf der entsprechenden Spiel- oder Itemseite ausgegeben. Wenn alles geklappt hat, steht dort der Code genau so wie er eingegeben wurde. Wenn etwas schief gegangen ist, malt der Parser die Zeile rot an und schreibt drunter, was das Problem ist. Der Pfeil ↑ zeigt dabei (meistens) auf das erste fehlerhafte Wort.

Ereignisse in A2l
Das Grundgerüst eines Ereignisses sieht etwa so aus: event [name]; on ; [if ;] [do ;] end. Die spitzen und eckigen Klammern gehören nicht wirklich da hin: die spitzen (<>) signalisieren einen Platzhalter, die eckigen ([]) bedeuten, dass der Inhalt darin auch weggelassen werden kann, wenn er nicht gebraucht wird.

Event-Name
Man darf jedem Event einen Namen geben. Das ist vor allem nützlich, um anderen sagen zu können, um welches Event es geht, oder für die Fehlersuche. Der Eventname darf aus beliebigen Kleinbuchstaben und Unterstrichen bestehen.

Trigger
Es können ein oder mehrere Trigger definiert werden, die festlegen, was der Auslöser für das Ereignis sein soll. Möglich sind dabei:
 * ausgelöst beim Betreten einer Seite oder beim Laden eines Spielstands
 * ausgelöst beim Betreten einer Seite oder beim Laden eines Spielstands


 * ausgelöst vor dem Verlassen einer Seite - Vorsicht, vielleicht noch mit Nebeneffekten verbunden
 * ausgelöst vor dem Verlassen einer Seite - Vorsicht, vielleicht noch mit Nebeneffekten verbunden


 * ausgelöst beim Klicken auf eine Region auf der Spielseite
 * hier ohne das "#"-Zeichen)
 * hier ohne das "#"-Zeichen)


 * ausgelöst beim Klicken auf ein Item
 * ausgelöst beim Klicken auf ein Item


 * ausgelöst, wenn Item1 auf Item2 gezogen wird
 * drag&drop). Hier ist es oft sinnvoll auch  zu verwenden, so dass man auch mit dem anderen Item anfangen kann
 * drag&drop). Hier ist es oft sinnvoll auch  zu verwenden, so dass man auch mit dem anderen Item anfangen kann


 * ausgelöst, wenn das Item auf eine Bildregion gezogen wird
 * ausgelöst, wenn das Item auf eine Bildregion gezogen wird


 * ausgelöst beim Hinzufügen des Items zum Inventar
 * ausgelöst beim Hinzufügen des Items zum Inventar


 * ausgelöst beim Entfernen des Items aus dem Inventar
 * ausgelöst beim Entfernen des Items aus dem Inventar

Die Platzhalter sind durch die Namen der Items/Seiten/Regionen zu ersetzen. Es können auch mehrere Trigger, per Komma getrennt, angegeben werden; das Ereignis tritt dann bei jedem der angegebenen Trigger ein.

Condition
Manchmal sollen bestimmte Voraussetzungen erfüllt sein, damit das Ereignis auch tatsächlich durch den Trigger ausgelöst wird. Das können sein:
 * oder
 * der Spieler muss sich auf der angegebenen Seite aufhalten


 * oder
 * der Spieler muss das angegebene Item im Inventar haben


 * wahr wenn irgendeine der durch Komma getrennten Bedingungen wahr ist
 * wahr wenn irgendeine der durch Komma getrennten Bedingungen wahr ist


 * wahr wenn alle der durch Komma getrennten Bedingungen wahr sind
 * wahr wenn alle der durch Komma getrennten Bedingungen wahr sind


 * wahr wenn die Bedingung innen falsch ist und anders herum
 * wahr wenn die Bedingung innen falsch ist und anders herum

Wenn keine Bedingung gebraucht wird, kann sie weggelassen werden.

Action
Das was dann passieren soll, wird durch eine oder mehrere, mit Komma getrennte, Aktionen angegeben:
 * Auf eine andere Spielseite wechseln
 * Auf eine andere Spielseite wechseln


 * Ein Item hinzufügen
 * Ein Item entfernen
 * Ein Item entfernen
 * Ein Item entfernen


 * oder
 * Text ausgeben. Für wörtliche Rede kannst du die deutschen Anführungszeichen innendrin verwenden (die findest du rechts in den Klick-Sonderzeichen)
 * Beispiel:


 * Starte den Timer und führe alle Aktionen die danach kommen erst aus, wenn der Timer durchgelaufen ist. Wenn der Timer vorher gestoppt wird oder die Seite verlassen wird, werden die Dinge danach nicht ausgeführt.
 * Es kann immer nur ein Timer laufen. Wenn schon ein Timer läuft, macht  gar nix. Der Timer wird unten rechts in der Ecke dem Spieler angezeigt.
 * Beispiel:
 * Beispiel:


 * Den Timer abbrechen
 * Den Timer abbrechen


 * und
 * Overlays anzeigen oder ausblenden. ( Absatz zu Overlays)


 * Frage den Benutzer was er tun will, oder bau einen Dialog zusammen: Hinter der Frage können mehrere mit Komma getrennte Optionen angegeben werden. gibt den Namen für die Option an ist der Text, der dem Benutzer für die Option angezeigt wird. Die Namen können dann mit  benutzt werden wie Bildregionen. Statt der doppelten können auch hier wieder einfache Anführungszeichen verwendet werden.
 * Beispiel:
 * Beispiel:


 * und
 * Musik und Geräusche im Adventure steuern. ( Audio)

Die Aktion kann weggelassen werden, was allerdings nicht so richtig viel Sinn macht (dann lieber weg mit dem ganzen Ereignis).

Testen
Ob der eigene Code zumindest syntaktisch okay ist, kann man schon in der Vorschau sehen. Wenn einfach nur der Code (mit Zeilennummern) angezeigt wird, ist alles gut gegangen; wenn eine Zeile rot markiert wurde, hat der Parser dich nicht verstanden. Schau dir in dem Fall die Fehlermeldung an (steht in blauem Text unter der roten Zeile) und korrigiere deinen Code.

Anschließend kannst du dir dann anschaun, wie sich deine Seiten und Dinge im Adventure verhalten. Dazu benutzt du am besten die Debug-Version, da kannst du dann nämlich direkt auf bestimmte Spielseiten springen oder Items laden. Außerdem kannst du dort im Event-Log sehen, welche Trigger ausgeführt wurden (schwarz) und welche Events dadurch ausgelöst wurden (grün) bzw. aufgrund nicht erfüllter Bedingungen nicht ausgelöst wurden (rot+kursiv).

Kommentare
Code kann kommentiert werden, so dass andere Autoren wissen warum da irgendwas so gemacht wurde, wie es gemacht wurde. Kommentare sind im C/C++-Style, das heißt an beliebiger Stelle entweder  (bis zum Ende der Zeile) oder   (geht auch innerhalb einer Zeile oder über mehrere Zeilen).

Audio
Anders als in der restlichen Kamelopedia bitte nicht mit dem Widget einbinden – denn im Adventure 2.0 gibt es drei getrennte Audiokanäle, die vom Spieler einzeln an- und ausgeschaltet werden können: Musik, Hintergrunz und Geräusche.

Beispielcode
Im Code sind die englischen Bezeichnungen zu verwenden: event; on enter(23); do play(music, "Adventure Soundtrack.oga"); end.

Musik-Kanal (music)
Hier kommt Hintergrundmusik rein. Musik wird immer weitergespielt: Wenn das Stück zuende ist, geht's von vorn los und die Musik bleibt bestehen, wenn man die Seite wechselt.

Hintergrunz-Kanal (background)
Gedacht für Hintergrundgeräusche der Szenerie, also Geräusche, die es in der Spielwelt tatsächlich gibt: Donnergrollen, Insektensummen, Livemusik. Auch Hintergrunz wird im Endlosdurchlauf gespielt. Wenn man die Seite wechselt, hören die Geräusche auf.

Es empfiehlt sich den Musikkanal anzuhalten, damit die Geräusche auch richtig zur Geltung kommen:

event; on enter(27); do stop(music), play(background, "audio.oga"); end.

Geräusche-Kanal (noise)
Was in diesen Kanal reinkommt, wird nur ein einziges mal abgespielt. Gedacht für kurze Töne oder Geräusche, die durch Dinge verursacht werden, die passieren, oder die der Spieler tut: Zersplitterndes Glas, ein platzender Autoreifen, Klicken eines Lichtschalters.

Seiten- und Itemklassen
Ich benutze hier einfach mal ein Beispiel:

Manchmal hat man Seiten oder Items die sich aus irgendeinem Grund ähnlich verhalten. Geht man etwa in einen dunklen Raum wird es dann hell, wenn man ein Licht dabei hat - egal ob Fackel oder Taschenlampe. Dafür kann man dann den Items Fackel und Taschenlampe eine gemeinsame Klasse zuweisen, indem man auf die Itemseiten schreibt: item; provides :light; end. Weitere Klassen würde man einfach mit Komma getrennt dahinter schreiben. Die Itemklasse kann man dann auf der entsprechenden Spielseite in der Condition mit  abfragen.

Andersherum gibt es natürlich auch bestimmte Items, die sich in bestimmten Umgebungen anders verhalten - z.B. kann man unterwasser die Fackel nicht anmachen. Dafür kommt dann auf die Spielseite: page; provides @underwater; end. Die lässt sich dann in der Condition auf der Itemseite mit  wieder abfragen.

Auch die remove-Funktion unterstützt die Angabe einer Klasse - in dem Fall werden dann alle Elemente entfernt, die auf die Klasse passen: z.B:

In den meisten Triggern lassen sich ebenfalls Klassen verwenden. Um das triggernde Item zu entfernen kann in der Action die Syntax  verwendet werden - ist dann add/remove/activate etc. und index die Nummer des Operanden (eigentlich immer 1, außer bei combine, da ist auch die 2 möglich). Passt die angegebene Triggerfunktion nicht, dann passiert einfach stattdessen nichts. Beispiel: event; on activate(:light); if page(4); do remove(${activate1}), print("Du versuchst Licht zu machen, aber im Dunkeln ist das extrem schwierig. Deine Lampe fällt dir dabei auf den Boden und geht kaputt."); end.

Overlays
Overlays ermöglichen das hinzufügen und wegnehmen von Objekten auf einer Seite - das können Gegenstände sein, oder aber irgendwas ganz anderes. Warum das nötig ist zeigt folgendes Beispiel: In einem Raum sollen 6 Gegenstände vom Spieler in beliebiger Reihenfolge aufgenommen werden können. Wenn man das versucht, mit einzelnen Seiten umzusetzen braucht man eine für jede Kombination von noch vorhandenen Gegenständen: also 2^6 = 64. Damit das nicht sein muss, platziert man alle Gegenstände mit Overlays auf der Seite. Es werden dann nur so viele Overlays benötigt, wie Gegenstände auf der Seite sind.

Overlays werden mit der Vorlage:Adventure2/Overlay eingefügt:

Der Parameter  steht für den Namen des Overlays,   für die css-Angaben: hier sollten mindestens   (oder  ) und   (oder  ) gesetzt werden, vielleicht auch noch. ist der Inhalt des Overlays. Beispiel:

Das Bild:Hammer.png enthält dann den anzuzeigenden Inhalt, d.h. hier den Hammer, so wie er im Bild dargestellt werden soll, natürlich mit transparentem Hintergrund. Da für jedes Overlay auch ein Klick-und-drop-Bereich definiert wird, sollten keine breiten transparenten Ränder usw. im Bild sein und der Bereich auch nicht unnötig mit  oder   groß gemacht werden.

Für Overlays gibt es zwei eigene Aktionen:  und , mit denen sich Overlays anzeigen oder verstecken lassen.

Ist  nicht gesetzt, so wird das Item beim Betreten der Seite angezeigt, ansonsten nicht. Wenn beides möglich sein soll (z.B. je nachdem, ob der Spieler das Item schon im Inventar hat), kann man  zunächst setzen, und wenn nötig, das Overlay beim Betreten der Seite einblenden:

event enter; on enter(30); if not(have(hammer)); do showOverlay(hammer); end.

Am Rande sei noch bemerkt, dass sich mit Overlays, etwa zusammen mit Widgets, auch andere Dinge realisieren lassen, wie z.B. Eingabefelder.

Pseudo-Items (Zustände)
Items, die mit einem Unterstrich beginnen, sind Pseudo-Items. Das bedeutet, sie werden nicht unten im Inventar angezeigt, codieren dafür aber irgendeinen Zustand. Der Spieler sieht sie also nicht, von der Scripting-Seite her lassen sie sich aber verwenden wie ganz normale Items.

Pseudo-Items machen das Adventure kompliziert: Bitte daher nur dort benutzen, wo es wirklich Sinn ergibt. Bitte dokumentiere im Quellcode mit /* Kommentaren */ ausführlich, was das Pseudo-Item codiert, und wann das Pseudo-Item benutzt wird und warum der Zustand überhaupt nötig ist. Denk dran, dein Item wird niemand je zu Gesicht bekommen, achte also darauf, dass spieltechnisch Sinn ergibt, dass sich der Zustand ändert.

Auch muss nicht jede Änderung im Adventure gespeichert werden: Es ist relativ egal, wenn eine vom Spieler geöffnete Tür später wieder zu ist (zumindest wenn sie sich einfach wieder öffnen lässt), die Tür braucht also keinen eigenen Status. Und die sich daraus ergebenden Inkonsistenzen schieben wir einfach auf den Hausmeister …

Links
Debug-Version, Seiten- und Itemübersicht Items-Bilder, Seiten-Bilder zum Autorenhandbuch | zur Projektseite