habe ich mich dazu entschlossen, das Thema nochmals aufzugreifen und es in Form eines etwas erweiterten Tutorials hier zu posten.
Um was geht es ?
Nun, es geht darum wie man, mit Hilfe von "send question to player", den Spieler etwas fragen kann. Mit etwas weiterer Sicht, lassen sich mit dieser Methode hervorragend Missionen aufbauen

1. Einführung
Um solche Fragen zu stellen und darauf zu reagieren brauchen wir immer 3 Dinge:
- eine Nachricht aus einem t-file
- ein Script, das die Nachricht aufbaut und an den Spieler schickt
- ein Script, das auf die Antwort des Spielers reagiert und diese
verarbeitet.
In jedem Abschnitt werde ich alle 3 Teile ausführen. Dabei nehme ich als Namen für das Senden-Script immer "Send" und als Reaktions-Script immer "callback".
2. Eine einfache Frage
Fangen wir mit einem ganz einfachen Beispiel an. Der Spieler soll auf die Frage "Möchten sie Geld ?" mit "Ja" oder "Nein" Antworten können. Je nach Antwort soll er dann Geld überwiesen bekommen oder nicht.
2.1. Der Textresource-Eintrag (t-file)
Für unsere Aufgabenstellung reicht ein einfacher Eintrag aus, der wie folgt aussehen kann:
Code: Select all
<page id="8888" title="Questions" descr="Texts for Questions">
<t id="100">Möchten sie etwas Geld haben ?\n\n
[select value="yes"]Aber immer doch[/select]\n
[select value="no"]Nö, hab genug[/select]
</t>
</page>
Nun..sieht ganz simple aus. Mit [Select] erzeugt ihr in der Nachricht einen Button, "value" enthält den Wert (später werden wir sehen das das auch mehrere sein können), der dann an unser Callback-Script übergeben wird, wenn der Spieler diesen Button drückt.
Natürlich könnt ihr alle möglichen Formatierungen für euren Text verwenden.
2.2. Das verschicken der Nachricht
Auch hier machen wir es uns erstmal ganz einfach, in dem wir das Script per Script-Editor starten müssen. Natürlich kann man alles mögliche als Auslöser verwenden (z.B. Spieler landet in einer bestimmten Station usw...). Aber wie gesagt, ich halte es hier mal ganz einfach:
Code: Select all
Script tut.send
Version: 1
for Script Engine Version: 32
Description
Sendet eine Frage an den Spieler
Arguments
Source Text
001 $message = read text: page=8888 id=100
002 send incoming question $message to player: callback='tut.callback'
003 return null

Wir laden den Text aus unserem t-File und schicken ihn an den Spieler. Der Parameter callback gibt das script an, das die Antwort des Spielers verarbeitet.
2.3. Die Reaktion
Nun, was noch fehlt, ist die Reaktion auf die Antwort des Spielers.
Code: Select all
Script tut.callback
Version: 1
for Script Engine Version: 32
Description
Empfaengt und wertet die Antwort aus
Arguments
* 1: antwort , Var/String , 'Antwort des Spielers'
Source Text
001 if $antwort == 'yes'
002 add money to player: 1000
003 send incoming message 'Wir haben ihnen 1000 Credits ueberwiesen' to player: display it=[TRUE]
004 end
005 if $antwort == 'no'
006 send incoming message 'Wie sie wollen, dann halt kein Geld' to player: display it=[TRUE]
007 end
008 return null
3. Mehr Buttons
Nun, sehr flexibel ist unsere obiges Beispiel nicht gerade. Also bauen wir es aus. Wir wollen, das der Spieler aus 3 Möglichkeiten auswählen kann.
3.1. t-files Eintrag
Zuerst fügen wir einen neuen Eintrag in unser t-file ein, der in etwa wie folgt aussehen sollte:
Code: Select all
<t id="101">
Möchten sie etwas Geld ?\n\n[select value="yes,1"]Ja, 1000 Credits wären nicht schlecht[/select]\n[select value="yes,2"]Ja, 100000 Credits hät ich gerne.[/select]\n[select value="no"]Nö, hab genug[/select]
</t>
Wie ihr sehen könnt, kann man im Value-Teil nicht nur einen Wert angeben, sonder auch mehrere, die mit einem Komma getrennt werden. Wieviele möglich sind, kann ich leider nicht sagen, hab das noch nicht ausprobiert.

Außerdem könnt ihr sehen, das wir jetzt 3 Buttons definiert haben. Nach bisherigen Erkenntnissen sind max. 5 Buttons möglich, je Nachricht.
3.2. Abschicken
Nun, hier brauchen wir nicht viel zu ändern. Lediglich die Text-ID muß angepasst werden. Damit sieht das dann wie folgt aus:
Code: Select all
Script tut.send
Version: 1
for Script Engine Version: 32
Description
Sendet eine Frage an den Spieler
Arguments
Source Text
001 $message = read text: page=8888 id=101
002 send incoming question $message to player: callback='tut.callback'
003 return null
Da wir mehr Möglichkeiten in unserem Text haben, brauchen wir natürlich ein erweitertes Script für die Möglichkeiten.
Zuerstmal das Script:
Code: Select all
Script tut.callback
Version: 1
for Script Engine Version: 32
Description
Empfaengt und wertet die Antwort aus
Arguments
* 1: antwort , Var/String , 'Antwort des Spielers'
* 2: ID , Var/Number , 'ID-Kennung als 2. Parameter'
Source Text
001 if $antwort == 'yes'
002 if $ID == 1
003 add money to player: 1000
004 send incoming message 'Wir haben ihnen 1000 Credits ueberwiesen' to player: display it=[TRUE]
005 end
006 if $ID == 2
007 add money to player: 10000
008 send incoming message 'Wir haben ihnen 10.000 Credits ueberwiesen' to player: display it=[TRUE]
009 end
010 end
011 if $antwort == 'no'
012 send incoming message 'Wie sie wollen, dann halt kein Geld' to player: display it=[TRUE]
013 end
014 return null
Je nach Auswahl des Spielers, werden jetzt 1000,10000 oder keine Kohle überwiesen.
4. Jetzt wirds dynamisch
Was tun wir, wenn wir den Betrag dynamisch im Script setzten wollen ? Nun...lasst uns das ganze wieder etwas erweitern.
4.1. Der t-Files-Eintrag
Als erstes braucen wir mal wieder frische Einträge in unserer Textdatei. Wir fügen diesmal 2 hinzu, einen für die Frage, und einen für die Antwort.
Das ganze sieht dann wie folgt aus:
Code: Select all
<t id="102">
Möchten sie etwas Geld ?\n\n[select value="yes,%s"]Ja, %s Credits wären nicht schlecht[/select]\n[select value="yes,%s"]Ja, %s Credits hät ich gerne.[/select]\n[select value="no"]Nö, hab genug[/select]
</t>
<t id="201">Wir haben ihnen %s Credits überwiesen.</t>
4.2. Abschicken
Hier wirds jetzt etwas aufwendiger, da wir erstmal die Nachricht zusammenbauen müssen, bevor wir sie abschicken.
Das könnte dann wie folgt aussehen:
Code: Select all
Script tut.send
Version: 1
for Script Engine Version: 32
Description
Sendet eine Frage an den Spieler
Arguments
Source Text
001 $money1 = 1000
002 $money2 = 10000
003 $currentmoney = get player money
004 if $currentmoney < 1000000
005 $money1 = 10000
006 $money2 = 100000
007 end
008 if $currentmoney < 100000
009 $money1 = 100000
010 $money2 = 1000000
011 end
012 if $currentmoney < 10000
013 $money1 = 500000
014 $money2 = 5000000
015 end
016 $messsage = sprintf: pageid=8888 textid=102, $money1, $money1, $money2, $money2, null
017 send incoming question $messsage to player: callback='tut.callback'
018 return null
hat, desto weniger wird ihm angeboten.
Danach bauen wir unsere Meldung zusammen, und tragen die Beträge ein. Warum immer 2 mal den Betrag ? Nun, wie im T-file zu sehen ist, haben wir nicht nur den Text dynamisch gemacht, sondern auch den Value-Parameter. Um uns die Arbeit zu erleichtern, übergeben wir dem Callback-Script statt 1 oder 2 gleich den richtigen Betrag.

4.3. Die Reaktion
Jetzt wirds interresant, wir brauchen auch ein neues Callback-Script. Allerdings wird das jetzt Einfacher.
Hier das Script:
Code: Select all
Script tut.callback
Version: 1
for Script Engine Version: 32
Description
Empfaengt und wertet die Antwort aus
Arguments
* 1: antwort , Var/String , 'Antwort des Spielers'
* 2: Money , Var/Number , 'Der Betrag, den wir vergeben'
Source Text
001 if $antwort == 'yes'
002 add money to player: $Money
003 $mess = sprintf: pageid=8888 textid=201, $Money, null, null, null, null
004 send incoming message $mess to player: display it=[TRUE]
005 end
006 if $antwort == 'no'
007 send incoming message 'Wie sie wollen, dann halt kein Geld' to player: display it=[TRUE]
008 end
009 return null
5. Noch mehr Möglichkeiten
Neben Texten (Strings) und Zahlen, kann man grundsätzlich alle Daten im Value-Teil übergeben. Selbst Arrays und Objekte kann man hier unterbringen und im Callback-Script auswerten.
5.1. Arrays
Wenden wir uns zuerst dem t-file zu.
Die Nachricht selbst sieht sehr einfach aus:
Code: Select all
<t id="103">
Möchten sie irgendwas ?\n\n[select value="yes,{%s}"]Ja ich möchte.[/select]\n\n[select value="no"]Nein, hab alles.[/select]
</t>
Da ich das Array auch dynamisch aufbauen will, habe ich mir noch zwei Hilfs-Texte angelegt:
Code: Select all
<t id="300">%s</t>
<t id="301">%s,</t>
Der nächste Schritt ist das Senden-Script.
Code: Select all
Script tut.send
Version: 1
for Script Engine Version: 32
Description
Sendet eine Frage an den Spieler
Arguments
Source Text
001 * Hier bau ich mein Array auf
002 $myarray = array alloc: size=0
003 $myship = get player ship
004 $data = $myship -> get sector
005 append $data to array $myarray
006 $data = get player name
007 append $data to array $myarray
008 $data = $myship -> get name
009 append $data to array $myarray
010 * Jetzt bau ich den Hilfs-String auf
011 $count = size of array $myarray
012 $helpstring = ''
013 dec $count =
014 while $count > 0
015 $data = $myarray[$count]
016 $tmp = sprintf: pageid=8888 textid=301, $data, null, null, null, null
017 $helpstring = $helpstring + $tmp
018 dec $count =
019 end
020 $data = $myarray[0]
021 $tmp = sprintf: pageid=8888 textid=300, $data, null, null, null, null
022 $helpstring = $helpstring + $tmp
023 * Jetzt die eigentliche Nachricht
024 $messsage = sprintf: pageid=8888 textid=103, $helpstring, null, null, null, null
025 send incoming question $messsage to player: callback='tut.callback'
026 return null
Als nächstes baue ich mir meine dynamische Array-Liste zusammen. Wichtig ist, das beim letzten Eintrag kein Komma mehr folgt.
Schließlich baue ich meine Nachricht zusammen und schicke sie an den Spieler.
Ich weiß das das so nicht viel Sinn macht, aber es verdeutlicht, wie der Hase läuft

Jetzt das Callback-Script:
Code: Select all
Script tut.callback
Version: 1
for Script Engine Version: 32
Description
Empfaengt und wertet die Antwort aus
Arguments
* 1: antwort , Var/String , 'Antwort des Spielers'
* 2: array , Value , 'Das arrray'
Source Text
001 if $antwort == 'yes'
002 * Der Einfachheit wegen indiziere ich das array direkt.
003 $Sector = $array[2]
004 $spielername = $array[1]
005 $schiffname = $array[0]
006 $message = sprintf: fmt='Der Spieler %s, befindet sich mit seinem Schiff %s im Sektor %s', $spielername, $schiffname, $Sector, null, null
007 send incoming message $message to player: display it=[TRUE]
008 end
009 if $antwort == 'no'
010 send incoming message 'Bitte dann eben nicht' to player: display it=[TRUE]
011 end
012 return null
Danach bau ich mir meine Nachricht auf und gebe sie schließlich aus.
5.2. Objekte
Auch beliebige Objekte kann ich übergeben. Das ganze funktioniert so:
Zuerst mal das t-file:
Code: Select all
<t id="104">
Interresse an Informationen ?\n\n\n[select value="yes,%s"] Aber immer doch [/select]\n\n[select value="no"] Nein, bin nicht Neugierig. [/select]
</t>
Das Send-Script
Code: Select all
Script tut.send
Version: 1
for Script Engine Version: 32
Description
Sendet eine Frage an den Spieler
Arguments
* 1: objekt , Var/Ship/Station , 'objekt der begierde'
Source Text
001 $helpstring = $objekt -> serialise object
002 * Jetzt die eigentliche Nachricht
003 $messsage = sprintf: pageid=8888 textid=104, $helpstring, null, null, null, null
004 send incoming question $messsage to player: callback='tut.callback'
005 return null
Um das Schiff oder die Station als String übergeben zu können, muss ich es erstmal mit Hilfe der routine "serialize object" umwandeln. Das Ergebniss kann ich dann ganz normal als String in die Nachricht einfügen und die Nachricht abschicken.
Das Callback-Script
Code: Select all
Script tut.callback
Version: 1
for Script Engine Version: 32
Description
Empfaengt und wertet die Antwort aus
Arguments
* 1: antwort , Var/String , 'Antwort des Spielers'
* 2: Objekt , Var/Ship/Station , 'Das Objekt'
Source Text
001 if $antwort == 'yes'
002 $Sector = $Objekt -> get sector
003 $schiffname = $Objekt -> get name
004 $message = sprintf: fmt='Das Objekt heisst %s und ist im Sektor %s', $schiffname, $Sector, $Sector, null, null
005 send incoming message $message to player: display it=[TRUE]
006 end
007 if $antwort == 'no'
008 send incoming message 'Bitte dann eben nicht' to player: display it=[TRUE]
009 end
010 return null
ich im Script-Editor habe (hier ermittle ich den Sektor und den Namen des Objekts).
6. Sonstiges
Natürlich kann man Arrays und Objekte auch kombinieren. Auch ein Array in einem Array läßt sich so übertragen (mehrere geschweifte Klammern ineinander verschachtelt]. Die Möglichkeiten die sich dadurch bieten sind sehr vielfälltig.
Ich hoffe das diese Tutorial euch weiterhilft. Sollte ich weitere Erkenntnisse zum Thema finden, erlangenso werd ich das Tutorial natürlich ergänzen.
*Edit Erweiterung vom 22.09.2006
7. BBS-Methode
Im Gegensatz zur Methode über Send-Question, werden hier die Texte im BBS dargestellt. Das ist vor allem für die Missionsprogrammierung wichtig. Im Grundprinzip läuft diese Quest-Programmierung wie ein AL-Plugin ab (vgl. Handbuch mCSI-Handbook).
Wie auch bei der ersten Methode (Send-Question), brauchen wir folgendes:
- Eine Nachricht in einem t-file
- Ein Script, um unsere Mission zu registrieren
- Ein Script, das auf die verschiedenen Ereignisse reagiert
7.1. Die Nachricht.
Hier bestehen die gleichen Möglichkeiten wie oben aufgeführt. Für unser Beispiel halten wir es einfach und stellen eine typische Ja/Nein-Frage.
Code: Select all
<page id="8888" title="Beispieltexte" descr="Beispieltexte für Tutorial">
<t id="200">Möchten sie die Mission annehmen ?\n\n
[select value="yes"]Ja, immer her damit.[/select]\n
[select value="no"]Nein, keine Zeit.[/select]\n
</t>
<t id="201">Vielen Dank das sie die Mission übernehmen.</t>
<t id="202">Die Mission ist beendet.</t>
</page>
7.2. Registrieren der Mission
Wie bei AL-Plugins muß man Quest-Scripts erstmal anmelden/registrieren. Meist macht man das im Initialisierungsscript (setup.xxxxxx). Ein solches Script kann wie folgt aussehen:
Code: Select all
Script al.plugin.tutorial
Version: 1
for Script Engine Version: 32
Description
Registrierscript für Tutorialbeispiel
Arguments
Source Text
001 load text: id=9999
002 register quest script 'tutorial.quest' instance multiple=500
003 return null
001 wie üblich, das laden der Textdatei
002 hier wird unser Script, das die Ereignisse der Quest-Engine verarbeiten soll, registriert.
instance multiple=500 gibt dabei an, wie oft die Mission gleichzeitig laufen kann.
7.3. Das eigentlich Missions-Script
Hier geht sozusagen die eigentliche Mission-Aktion los. Je nach Ereigniss, werden hier verschiedene Aktionen durchgeführt.
Code: Select all
Script plugin.merc.guild.bbs
Version: 1
for Script Engine Version: 32
Description
Unser Missionsscript
Arguments
* 1: Object , Value , 'Quest Object'
* 2: Event , Var/String , 'Event String'
* 3: Data , Value , 'Object Data Array'
* 4: choice , Var/String , 'Question Anwser'
Source Text
001 if $Event == 'init' or $Event == 'reinit'
002 [THIS] -> call script 'mission.tutorial.init' :
003
004 else if $Event == 'prio'
005 $rank.fight = get fight rank
006 if $rank.fight >= 25000
007 return 100
008 else
009 return 0
010
011 else if $Event == 'offer'
012 $Message = sprintf: pageid=8888 textid=200, null, null, null, null
013 set quest state with message: quest=$Object state=[Quest.Offered] msg=$Message
014
015 else if $Event == 'display'
016 [THIS] -> call script 'mission.tutorial.display' :
017
018 else if $Event == 'select'
019 if $choice == 'yes'
020 $Message = sprintf: pageid=8888 textid=201, null, null, null, null
021 set quest state with message: quest=$Object state=[Quest.Accepted] msg=$Message
022 else
023 set quest state with message: quest=$Object state=[Quest.Abort] msg=null
024 end
025 else if $Event == 'accept'
026 [THIS] -> call script 'mission.tutorial.action' :
027
028 else if $Event == 'check'
029
030 $finale = [THIS] -> call script 'mission.tutorial.checkfinal' :
031 if $finale
032 $Message = sprintf: pageid=8888 textid=202, null, null, null, null
033 set quest state with message: quest=$Object state=[Quest.Finished] msg=$Message
034 else
035 [THIS] -> call script 'mission.tutorial.action2' :
036 end
037 end
Parameter:
$Object -> Ein Quest-Objekt, das von X automatisch generiert wird. Es
identifiziert die Mission eindeutig.
$Event -> Das Ereigniss das ausgelöst wurde
$data -> Objekt-Daten
$choice -> der Value-Eintrag aus der Nachricht
Dieser wird nur beim 'select'-Ereignis mitgeliefert,
ansonsten ist er NULL
Events:
init/reinit : Wird beim Initialisieren der Mission aufgerufen. Hier können
dann z.B. spezielle Missions-Stationen/Schiffe erzeugt werden
usw.
prio : Dieses Event wird aufgerufen, wenn die Engine wissen muss
mit welcher Priorität die Mission angezeigt werden soll. Je
höher der Rückgabewert desto wahrscheinlicher ist die Anzeige
in der BBS. In unserem Beispiel sagen wir, wenn der Spieler
einen Kampfrang "Kämpfer" oder höher hat,
dann soll die Mission angeboten werden, ansonsten garnicht.
offer : Wenn die Mission angeboten werden soll. Hier wird die
Nachricht zusammengebaut. Wichtig ist dabei, das sie via
"set quest state" ausgeben wird, damit die Quest-Engine weiß,
jawohl diese Mission wird jetzt angeboten.
display : Wird aufgerufen, wenn die Mission in der BBS vorhanden ist
und angezeigt wird.
select : Der wohl wichtigste Punkt. Der Spieler hat aus unserem
Missionsangebot einen Button gedrückt. Je nach dem ob er Ja
oder Nein gedrückt hat, sagen wir Danke
und es geht weiter, oder die Mission wird abgebrochen.
accept : Wird aufgerufen wenn der Spieler die Mission angenommen
hat. Hier wird jetzt die eigentliche Missions-Aktion gestartet.
check : Wird periodisch aufgerufen. Hier muß geprüft werden ob die
Mission weiterlaufen soll, oder ob sie schon erfüllt wird.
Wichtig ist, das ihr immer mit "set quest state with message" arbeitet, damit die Quest-Engine auch mitbekommt, wie es mit der Mission steht, und ggf. entsprechend reagieren kann.
So..ich hoffe das hilft euch weiter
