Macros for Dummies - A MapTool Macro-Tutorial (german)

Doc requests, organization, and submissions

Moderators: dorpond, trevor, Azhrei

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.8.2 - Eingabeformular: Die Erklärung

Die Spieler sollen ihre Charakterwerte natürlich auch ändern können. Für den Charaktereditor nutzen wir erneut ein HTML-Formular, benötigen also wieder zwei Makros. Erstelle das Formular-Makro "charedit" in deinem Library-Token.

Du kennst das Spielchen bereits, der Aufbau ist ähnlich wie bei den anderen Formularen. Konzentrieren wir uns also wieder auf die zweite Zelle der äußeren Tabelle, die auch alle Eingabefelder enthält. Schauen wir uns erst den gesamten Inhalt der Zelle an:

Code: Select all

[h: selectKrieger = ""]
[h: selectSchurke = ""]
[h: selectMagier = ""]

[h,switch(Klasse):
  case "Krieger": selectKrieger = "selected='selected'";
  case "Schurke": selectSchurke = "selected='selected'";
  case "Magier": selectMagier = "selected='selected'";
  default: selectKrieger = "selected='selected'"
]

[r: strformat("
  <table style='border-spacing: 0px'>
    <tr>
      <td>
        Klasse:
      </td>
      <td>
        <select name='nKlasse'>
          <option %s>Krieger</option>
          <option %s>Schurke</option>
          <option %s>Magier</option>
        </select>
      </td> 
    </tr>
    <tr>
      <td>
        Kraft:
      </td>
      <td>
        <input type='text' name='nKraft' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
    <tr>
      <td>
        Geschick:
      </td>
      <td>
        <input type='text' name='nGeschick' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>  
    <tr>
      <td>
        Klugheit:
      </td>
      <td>
        <input type='text' name='nKlugheit' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
    <tr>
      <td>
        Grundangriff:
      </td>
      <td>
        <input type='text' name='nAngriff' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
    <tr>
      <td>
        Grundverteidigung:
      </td>
      <td>
        <input type='text' name='nVerteidigung' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
    <tr>
      <td>
        Rüstung:
      </td>
      <td>
        <input type='text' name='nRuestung' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
    <tr>
      <td>
        Maximale HP:
      </td>
      <td>
        <input type='text' name='nHP' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
  </table>
", selectKrieger, selectSchurke, selectMagier, Kraft, Geschick, Klugheit, Angriff, Verteidigung, Ruestung, HPmax)]
Der Teil mit der Tabelle sollte dich vor keine Rätsel stellen. Hier befinden sich mal wieder die ganzen Eingabefelder, die wir beim Charaktereditor natürlich mit den aktuellen Charakterwerten vorbelegen. An erster Stelle steht dabei eine Dropdown-Liste um die Charakterklasse auszuwählen. Schauen wir uns diese näher an:

Code: Select all

<select name='nKlasse'>
  <option %s>Krieger</option>
  <option %s>Schurke</option>
  <option %s>Magier</option>
</select>
Wie du siehst wird innerhalb der einzelnen Listeneinträge (<option>) jeweils noch eine Variable notiert, bzw. ausgegeben. Diese dient zur Vorauswahl der aktuellen Klasse des Charakters. Gehen wir etwas näher darauf ein. Vor der Tabelle werden folgende Variablen definiert:

Code: Select all

[h: selectKrieger = ""]
[h: selectSchurke = ""]
[h: selectMagier = ""]
Diese Variablen werden alle bei den passenden Listeneinträgen ausgegeben. Da sie aber nur leere Strings enthalten, bewirken sie dort einfach gar nichts. Daher werden nach der Definition der Variablen noch den Wert einer dieser Variablen ändern. Dafür nutzen wir eine SWITCH-Anweisung:

Code: Select all

[h,switch(Klasse):
  case "Krieger": selectKrieger = "selected='selected'";
  case "Schurke": selectSchurke = "selected='selected'";
  case "Magier": selectMagier = "selected='selected'";
  default: selectKrieger = "selected='selected'"
]
Kannst du erkennen was dort passiert? Je nachdem welche Klasse der Charakter aktuell besitzt, wird der Variable für den passenden Listeneintrag der Wert selected='selected' zugewiesen. Dadurch können wir also bestimmen welcher Eintrag in der Liste beim Aufruf des Eingabeformulars angezeigt wird, nämlich der Eintrag mit der aktuellen Charakterklasse.

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.8.3 - Datenverarbeitung: Das Makro

Code: Select all

[h: "<!-- Daten aus Eingabeformular empfangen und in Variable speichern -->"]

[h: daten = macro.args]

[h: "<!-- Eingabeformular schliessen -->"]

[h: closeDialog("chareditor")]

[h: "<!-- Daten aus Eingabeformular in Variablen speichern  -->"]

[h: nKlasse = getStrProp(daten, "nKlasse")]
[h: nKraft = getStrProp(daten, "nKraft")]
[h: nGeschick = getStrProp(daten, "nGeschick")]
[h: nKlugheit = getStrProp(daten, "nKlugheit")]
[h: nAngriff = getStrProp(daten, "nAngriff")]
[h: nVerteidigung = getStrProp(daten, "nVerteidigung")]
[h: nRuestung = getStrProp(daten, "nRuestung")]
[h: nHP = getStrProp(daten, "nHP")]

[h: "<!-- Usereingaben pruefen -->"]

[h,if(nKraft == "" || nGeschick == "" || nKlugheit == "" || nAngriff == "" || nVerteidigung == "" || nRuestung == "" || nHP == ""): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Es müssen alle Felder ausgefüllt werden. Bitte wiederhole den Vorgang.", 0)]

[h,if(isNumber(nKraft) == 0 || isNumber(nGeschick) == 0 || isNumber(nKlugheit) == 0 || isNumber(nAngriff) == 0 || isNumber(nVerteidigung) == 0 || isNumber(nRuestung) == 0 || isNumber(nHP) == 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(nKraft != round(nKraft) || nGeschick != round(nGeschick) || nKlugheit != round(nKlugheit) || nAngriff != round(nAngriff) || nVerteidigung != round(nVerteidigung) || nRuestung != round(nRuestung) || nHP != round(nHP)): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(nKraft <= 0 || nGeschick <= 0 || nKlugheit <= 0 || nAngriff <= 0 || nVerteidigung <= 0 || nRuestung <= 0 || nHP <= 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Es ist mindestens ein Wert von "1" nötig. Bitte wiederhole den Vorgang.", 0)]

[h: "<!-- Daten aus Eingabeformular in Properties speichern -->"]

[h: Klasse = nKlasse]
[h: Kraft = nKraft]
[h: Geschick = nGeschick]
[h: Klugheit = nKlugheit]
[h: Angriff = nAngriff]
[h: Verteidigung = nVerteidigung]
[h: Ruestung = nRuestung]
[h: HPmax = nHP]

[h: "<!-- Charakterbogen aufrufen und aktualisieren  -->"]

[macro("charbogen@Lib:makros"): ""]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.8.4 - Datenverarbeitung: Die Erklärung

Kommen wir zur Verarbeitung des Eingabeformulars, das ist zum Glück ganz einfach. Erstelle das neue Makro "chareditProcess" im Library-Token.

Wie immer rufen wir erst die Daten des Eingabeformulars ab und schließen das Eingabefenster:

Code: Select all

[h: daten = macro.args]

[h: closeDialog("chareditor")]
Dann speichern wir die Usereingaben in einzelnen Variablen:

Code: Select all

[h: nKlasse = getStrProp(daten, "nKlasse")]
[h: nKraft = getStrProp(daten, "nKraft")]
[h: nGeschick = getStrProp(daten, "nGeschick")]
[h: nKlugheit = getStrProp(daten, "nKlugheit")]
[h: nAngriff = getStrProp(daten, "nAngriff")]
[h: nVerteidigung = getStrProp(daten, "nVerteidigung")]
[h: nRuestung = getStrProp(daten, "nRuestung")]
[h: nHP = getStrProp(daten, "nHP")]
Natürlich müssen die Usereingaben wieder überprüft werden:

Code: Select all

[h,if(nKraft == "" || nGeschick == "" || nKlugheit == "" || nAngriff == "" || nVerteidigung == "" || nRuestung == "" || nHP == ""): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Es müssen alle Felder ausgefüllt werden. Bitte wiederhole den Vorgang.", 0)]

[h,if(isNumber(nKraft) == 0 || isNumber(nGeschick) == 0 || isNumber(nKlugheit) == 0 || isNumber(nAngriff) == 0 || isNumber(nVerteidigung) == 0 || isNumber(nRuestung) == 0 || isNumber(nHP) == 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(nKraft != round(nKraft) || nGeschick != round(nGeschick) || nKlugheit != round(nKlugheit) || nAngriff != round(nAngriff) || nVerteidigung != round(nVerteidigung) || nRuestung != round(nRuestung) || nHP != round(nHP)): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(nKraft <= 0 || nGeschick <= 0 || nKlugheit <= 0 || nAngriff <= 0 || nVerteidigung <= 0 || nRuestung <= 0 || nHP <= 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Es ist mindestens ein Wert von "1" nötig. Bitte wiederhole den Vorgang.", 0)]
Jetzt wo wir die geänderten Charakterwerte haben, müssen wir sie nur noch in den passenden Properties speichern:

Code: Select all

[h: Klasse = nKlasse]
[h: Kraft = nKraft]
[h: Geschick = nGeschick]
[h: Klugheit = nKlugheit]
[h: Angriff = nAngriff]
[h: Verteidigung = nVerteidigung]
[h: Ruestung = nRuestung]
[h: HPmax = nHP]
Schlussendlich aktualisieren wir wieder den Charakterbogen:

Code: Select all

[macro("charbogen@Lib:makros"): ""]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.9 - Initiative

18.9.1 - Das Makro

Code: Select all

[h: "<!-- Initiative berechnen und eintragen -->"]

[h: ini.wurf = 1d6]
[h: ini.ergebnis = Geschick + ini.wurf]

[h: addToInitiative(0, ini.ergebnis)]

[h: "<!-- Ausgabe in der Chatbox -->"]

[r: strformat("
<table style='border-spacing: 0px; background-color: #cfe9cf; border: 2px solid #008000'>
  <tr>
    <td style='font-weight: bold; padding: 5px; border-right: 1px solid' valign='middle'>
      Initiative
    </td>
    <td style='padding: 5px 2px 5px 5px' valign='middle'>
      Geschick:<br>
      Wurf mit W6:
    </td>
    <td style='text-align: right; padding: 5px 5px 5px 2px; border-right: 1px solid' valign='middle'>
      %s<br>
      %s
    </td>
    <td style='font-size: 14pt; font-weight: bold; padding: 5px' valign='middle'>
      %s
    </td>
  </tr>
</table>
", Geschick, ini.wurf, ini.ergebnis)]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.9.2 - Die Erklärung

Der Initiativewert eines Charakter berechnet sich aus seinem Geschick und einem Wurf mit einem W6. Erstelle zunächst das Makro "iniWurf" in deinem Library-Token. Im Charakterbogen hast du dieses Makro ja schon verlinkt.

Der Code für das Makro ist ganz einfach. Zuerst wird mit einem W6 gewürfelt und die Initiative berechnet:

Code: Select all

[h: ini.wurf = 1d6]
[h: ini.ergebnis = Geschick + ini.wurf]
Dann wird die Initiative des Tokens in das Initiativefenster von MapTool eingetragen. Dafür benutzen wir die Funktion addToInitiative():

Code: Select all

[h: addToInitiative(0, ini.ergebnis)]
Der erste Parameter bestimmt ob es Duplikate des Token im Initiativefenster geben darf, der Token also mehrmals eingetragen werden darf. Bei "1" (True) darf es Duplikate geben und bei "0" (False) nicht. Der zweite Parameter ist der Initiativewert der in das Initiativefenster eingetragen werden soll.

Fehlt nur noch die Ausgabe des Initiativewurfs in der Chatbox:

Code: Select all

[r: strformat("
<table style='border-spacing: 0px; background-color: #cfe9cf; border: 2px solid #008000'>
  <tr>
    <td style='font-weight: bold; padding: 5px; border-right: 1px solid' valign='middle'>
      Initiative
    </td>
    <td style='padding: 5px 2px 5px 5px' valign='middle'>
      Geschick:<br>
      Wurf mit W6:
    </td>
    <td style='text-align: right; padding: 5px 5px 5px 2px; border-right: 1px solid' valign='middle'>
      %s<br>
      %s
    </td>
    <td style='font-size: 14pt; font-weight: bold; padding: 5px' valign='middle'>
      %s
    </td>
  </tr>
</table>
", Geschick, ini.wurf, ini.ergebnis)]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10 - Inventar

18.10.1 - Inventarfenster: Das Makro

Code: Select all

[h: "<!-- Eingabefenster oeffnen und HTML-Aufbau notieren -->"]

[dialog("inventar", "width=428; height=400; temporary=1; input=0; noframe=0"):
  {
    [r: "
    <html>
      <head>
        <title>
          Inventar
        </title>
      </head>
      <body style='background-color: #a4c8a4'>
    "]

        [h: "<!-- Variable fuer Ueberschrift des Inventars definieren -->"]
    
        [h: neu.item.link = macroLink("Neuer Gegenstand", "inventarNeu@Lib:makros")]

        [h: "<!-- Ueberschrift 1 fuer Inventar ausgeben -->"]
    
        [r: strformat("
        <table style='border-spacing: 0px; color: #ffffff; border: 2px solid #008000; background-color: #008000; width: 400'>
          <tr>
            <td style='font-weight: bold; width: 200'>
              Inventar
            </td>
            <td style='text-align: right; width: 200' valign='bottom'>
              <span style='font-size: 10pt; color: #ffffff; text-decoration: none'>(%s)</span>
            </td>
          </tr>
        </table>
        ", neu.item.link)]

        [h: "<!-- Beginn der Tabelle fuer Inventar -->"]

        [r: "
        <table style='border-spacing: 0px; border: 2px solid #008000; border-top: none; background-color: #ffffff; width: 400'>
          <tr style='font-style: italic; border-bottom: 1px solid'>
            <td style='text-align: center; width: 50'>
              Anzahl
            </td>
            <td style='width: 250'>
              Gegenstand
            </td>
            <td style='text-align: center; width: 100'>
               
            </td>
          </tr>
        "]

        [h: "<!-- Ausgabe wenn kein Inventar vorhanden -->"]

        [r,if(json.isEmpty(Inventar) == 1), code:
          {
            <tr>
              <td>
                 
              </td>
              <td>
                Keine Gegenstände vorhanden
              </td>
              <td>
                 
              </td>
            </tr>
          };{}
        ]

        [h: "<!-- Erste Item-Nummer fuer Schleife festlegen -->"]

        [h: item.nummer = 0]

        [h: "<!-- Schleife fuer Item-Ausgabe starten -->"]

        [r,foreach(item, Inventar, ""), code:
          {

            [h: "<!-- Variablen fuer Schleifenausgabe definieren -->"]

            [h: anzahl = json.get(item, "Anzahl")]
            [h: gegenstand = json.get(item, "Gegenstand")]

            [h: edit.link = macroLink("Editieren", "inventarEdit@Lib:makros", "", item.Nummer)]
            [h: loeschen.link = macroLink("Löschen", "inventarLoeschen@Lib:makros", "", item.Nummer)]

            [h: "<!-- Schleifenausgabe der Items -->"]

            [r: strformat("
            <tr>
              <td style='text-align: center'>
                %s
              </td>
              <td>
                %s
              </td>
              <td style='text-align: center' valign='bottom'>
                <span style='font-size: 10pt; color: #000000; text-decoration: none'>%s | %s</span>
              </td>
            </tr>
            ", anzahl, gegenstand, edit.link, loeschen.link)]

            [h: "<!-- Item-Nummer erhoehen -->"]

            [h: item.nummer = item.Nummer + 1]
          }
        ]

        [h: "<!-- Tabelle des Inventars schliessen -->"]

        [r: "
        </table>
        "]

    [h: "<!-- HTML-Bereich und Dialog-Fenster schliessen -->"]

    [r: "
      </body>
    </html>
    "]
  }
]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.2 - Inventarfenster: Die Erklärung

Die Auflistung des Inventars wollen wir in einem separaten Fenster erledigen. Also erstelle das neue Makro "inventar" im Library-Token.

Als erstes notieren wir den Code für das Dialog-Fenster und den HTML-Aufbau:

Code: Select all

[dialog("inventar", "width=428; height=400; temporary=1; input=0; noframe=0"):
  {
    [r: "
    <html>
      <head>
        <title>
          Inventar
        </title>
      </head>
      <body style='background-color: #a4c8a4'>
    "]
In der Überschrift des Inventarfensters geben wir einen Link aus um neue Gegenstände hinzuzufügen. Diesen Link speichern wir in einer Variable:

Code: Select all

[h: neu.item.link = macroLink("Neuer Gegenstand", "inventarNeu@Lib:makros")]
Jetzt die Überschrift für das Inventar. Dafür nutzen wir eine eigene Tabelle:

Code: Select all

[r: strformat("
  <table style='border-spacing: 0px; color: #ffffff; border: 2px solid #008000; background-color: #008000; width: 400'>
    <tr>
      <td style='font-weight: bold; width: 200'>
        Inventar
      </td>
      <td style='text-align: right; width: 200' valign='bottom'>
        <span style='font-size: 10pt; color: #ffffff; text-decoration: none'>(%s)</span>
      </td>
    </tr>
  </table>
", neu.item.link)]
Fangen wir mit dem eigentlichen Inventar an. Auch dafür erstellen wir eine Tabelle und eine weitere Überschriftenzeile, ähnlich wie bei der Waffenliste im Charakterbogen:

Code: Select all

[r: "
<table style='border-spacing: 0px; border: 2px solid #008000; border-top: none; background-color: #ffffff; width: 400'>
  <tr style='font-style: italic; border-bottom: 1px solid'>
    <td style='text-align: center; width: 50'>
      Anzahl
    </td>
    <td style='width: 250'>
      Gegenstand
    </td>
    <td style='text-align: center; width: 100'>
       
    </td>
  </tr>
"]
Die Tabelle wird noch nicht geschlossen, denn jetzt kommt Zeile für Zeile die Auflistung des Inventars. Zuerst prüfen wir aber ob überhaupt Inventargegenstände vorhanden sind, und geben eine entsprechende Info-Zeile aus falls nicht. Da das Inventar ja in einem JSON-Array gespeichert wird, nutzen wir zur Prüfung die Funktion json.isEmpty(), die eine 1 (True) oder eine 0 (False) zurückliefert. Als Parameter geben wir das betroffene JSON-Array an, also das Property "Inventar".

Code: Select all

[r,if(json.isEmpty(Inventar) == 1), code:
  {
    <tr>
      <td>
         
      </td>
      <td>
        Keine Gegenstände vorhanden
      </td>
      <td>
         
      </td>
    </tr>
  };{}
]
Wenn es jedoch Gegenstände im Inventar gibt geben wir diese nun Zeile für Zeile mit einer FOREACH-Schleife aus. Da wir gleichzeitig auch Links erstellen wollen brauchen wir für jeden Eintrag auch den aktuellen Index der Liste. Bei einem JSON-Array beginnt der Index ja immer bei "0", also legen wir auch "0" als erste Nummer fest:

Code: Select all

[h: item.nummer = 0]
Jetzt notieren wir schnell die Schleife:

Code: Select all

[r,foreach(item, Inventar, ""), code:
  {

  }
]
Die einzelnen Einträge im JSON-Array des Inventar-Propertys bestehen aus JSON-Objects. Diese JSON-Objects haben immer zwei Felder mit entsprechenden Werten. Ein Feld für den Namen des Gegenstandes, und ein Feld für die Anzahl dieses Gegenstandes. Ein Eintrag für einen Inventargegenstand könnte also z. B. so aussehen:

Code: Select all

{"Anzahl":5, "Gegenstand":"Proviant"}
Kommen wir jetzt zum Inhalt der Schleife. Zuerst brauchen wir die Daten des aktuellen Eintrags, bzw. JSON-Objects, also den eigentlichen Gegenstand und die Anzahl. Um diese Daten aus dem JSON-Object abzurufen nutzen wir die Funktion json.get(), bei der wir als Parameter das aktuelle JSON-Object und den Namen des gewünschten Feldes angeben.

Code: Select all

[h: anzahl = json.get(item, "Anzahl")]
[h: gegenstand = json.get(item, "Gegenstand")]
Dann erstellen wir Links zu Makros um den aktuellen Eintrag zu editieren und zu löschen. Dabei geben wir die Index-Nummer des aktuellen Eintrags als Daten weiter.

Code: Select all

[h: edit.link = macroLink("Editieren", "inventarEdit@Lib:makros", "", item.Nummer)]
[h: loeschen.link = macroLink("Löschen", "inventarLoeschen@Lib:makros", "", item.Nummer)]
Und schließlich erzeugen wir eine Tabellenzeile für den aktuellen Eintrag. In der ersten Zelle zeigen wir die Anzahl an, in der zweiten Zelle den Namen des Gegenstandes, und in der dritten Zelle platzieren wir die Links zum Editieren und Löschen.

Code: Select all

[r: strformat("
  <tr>
    <td style='text-align: center'>
      %s
    </td>
    <td>
      %s
    </td>
    <td style='text-align: center' valign='bottom'>
      <span style='font-size: 10pt; color: #000000; text-decoration: none'>%s | %s</span>
    </td>
  </tr>
", anzahl, gegenstand, edit.link, loeschen.link)]
Als letzten Befehl in der Schleife erhöhen wir noch die Index-Nummer für die Liste, also das JSON-Array:

Code: Select all

[h: item.nummer = item.Nummer + 1]
Damit ist die Schleife beendet. Jetzt noch die Tabelle für das Inventar schließen:

Code: Select all

[r: "
</table>
"]
Und den HTML-Bereich sowie das Dialog-Fenster schließen:

Code: Select all

    [r: "
      </body>
    </html>
    "]
  }
]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.3 - Gegenstand hinzufügen (Formular): Das Makro

Um einen neuen Gegenstand zum Inventar hinzuzufügen benutzen wir, wer hätte es gedacht, mal wieder ein HTML-Formular, benötigen also wieder zwei Makros. Erstelle das Formular-Makro "inventarNeu" in deinem Library-Token. Der Inhalt des Makros unterscheidet sich nicht sehr von den anderen Formularen die wir schon erstellt haben, eine Erklärung spare ich mir also. Schaue dir das Makro einfach nur genau an.

Code: Select all

[h: "<!-- Eingabefenster oeffnen und HTML-Aufbau notieren -->"]

[dialog("inventarNeu", "width=308; height=239; temporary=1; input=0; noframe=0"):
  {
    [r: "
    <html>
      <head>
        <title>
          Gegenstand hinzufügen
        </title>
      </head>
      <body>
    "]

        [h: "<!-- Beginn des Eingabeformulars -->"]

        [h: processLink = macroLinkText("inventarNeuProcess@Lib:makros")]
        [r: strformat("<form action='%s'>", processLink)]

          [h: "<!-- Beginn der aeusseren Tabelle -->"]

          [r: "
          <table style='border-spacing: 0px; border: 2px solid #008000; background-color: #ffffff; width: 280'>
            <tr>
              <td style='text-align: center'>

                <!-- Tabelle fuer Ueberschrift -->

                <table style='border-spacing: 0px; margin-top: 10px; margin-bottom: 10px; width: 240'>
                  <tr>
                    <td style='font-size: 14pt; font-weight: bold; color: #ffffff; text-align: center; background-color: #008000'>
                      Neuer Gegenstand
                    </td>
                  </tr>
                </table>

          <!-- Weiterfuehrung der aeusseren Tabelle -->

              </td>
            </tr>
            <tr>
              <td style='text-align: center'>

                <!-- Tabelle fuer Eingabefelder -->

                <table style='border-spacing: 0px'>
                  <tr>
                    <td>
                      Anzahl:
                    </td>
                    <td>
                      <input type='text' name='iAnzahl' size='2' maxlength='2'>
                    </td> 
                  </tr>
                  <tr>
                    <td>
                      Gegenstand:
                    </td>
                    <td>
                      <input type='text' name='iName' size='15' maxlength='27'>
                    </td> 
                  </tr>  
                </table>

          <!-- Abschluss der aeusseren Tabelle mit Senden-Button -->

              </td>
            </tr>
            <tr>
              <td style='text-align: center; padding: 10px'>
                <input type='submit' name='processButton' value='Gegenstand eintragen'>
              </td>
            </tr>
          </table>

        <!-- Formular, HTML-Bereich und Dialog-Fenster schliessen -->

        </form>
      </body>
    </html>
    "]
  }
]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.4 - Gegenstand hinzufügen (Verarbeitung): Das Makro

Code: Select all

[h: "<!-- Daten aus Eingabeformular empfangen  -->"]

[h: daten = macro.args]

[h: "<!-- Eingabefenster schliessen  -->"]

[h: closeDialog("inventarNeu")]

[h: "<!-- Item-Daten in Variablen speichern  -->"]

[h: item.anzahl = getStrProp(daten, "iAnzahl")]
[h: item.name = getStrProp(daten, "iName")]

[h: "<!-- Daten aus Eingabeformular auf Fehler pruefen  -->"]

[h,if(item.name == ""): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Kein Name für den Gegenstand eingegeben. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl == ""): item.anzahl = 1; item.anzahl = item.anzahl]

[h: assert(isNumber(item.anzahl), "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl != round(item.anzahl)): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl < 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Du hast eine negative Zahl eingegeben. Bitte wiederhole den Vorgang.", 0)]

[h: "<!-- JSON-Object fuer Item erstellen  -->"]

[h: neu.item = json.set("{}", "Gegenstand", item.name, "Anzahl", item.anzahl)]

[h: "<!-- Item in Property eintragen und Liste sortieren -->"]

[h: Inventar = json.append(Inventar, neu.Item)]
[h: Inventar = json.sort(Inventar, "asc", "Gegenstand")]

[h: "<!-- Inventar aufrufen und aktualisieren  -->"]

[macro("inventar@Lib:makros"): ""]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.5 - Gegenstand hinzufügen (Verarbeitung): Die Erklärung

Nun fügen wir den neuen Gegenstand zum Inventar hinzu. Erstelle das neue Makro "inventarNeuProcess" in deinem Library-Token.

Zuerst empfangen wir die Daten aus dem Eingabeformular und schließen das Eingabefenster:

Code: Select all

[h: daten = macro.args]

[h: closeDialog("inventarNeu")]
Dann speichern wir die einzelnen Usereingaben in Variablen:

Code: Select all

[h: item.anzahl = getStrProp(daten, "iAnzahl")]
[h: item.name = getStrProp(daten, "iName")]
Die Usereingaben werden wieder auf Fehler überprüft:

Code: Select all

[h,if(item.name == ""): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Kein Name für den Gegenstand eingegeben. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl == ""): item.anzahl = 1; item.anzahl = item.anzahl]

[h: assert(isNumber(item.anzahl), "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl != round(item.anzahl)): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl < 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Du hast eine negative Zahl eingegeben. Bitte wiederhole den Vorgang.", 0)]
Jetzt muss ein neues JSON-Object für den neuen Gegenstand erstellt werden. Auf direktem Weg ist das schwierig, wir benutzen also die Funktion json.set(). Um mit dieser Funktion ein neues JSON-Object zu erstellen, müssen wir als ersten Parameter ein leeres JSON-Object als String angeben. Dann folgen die Felder die wir in diesem JSON-Object erstellen wollen. Die Werte für die Felder werden immer direkt nach dem Feld angegeben. Alle Einträge, bzw. Parameter, werden dabei durch ein Komma voneinander getrennt.

Code: Select all

[h: neu.item = json.set("{}", "Gegenstand", item.name, "Anzahl", item.anzahl)]
Jetzt tragen wir das JSON-Object in unser Inventar-Property, also das JSON-Array, ein. Dafür nutzen wir die Funktion json.append(), die den neuen Eintrag an die letzte Stelle in der Liste setzt. Als Parameter geben wir die Liste und den neuen Eintrag an.

Code: Select all

[h: Inventar = json.append(Inventar, neu.Item)]
Nun muss die Inventarliste, also das JSON-Array, noch sortiert werden. Da die einzelnen Einträge in der Liste aber aus JSON-Objects bestehen, müssen wir dabei auch das Feld innerhalb der Objects angeben, nach dem sortiert werden soll. Wir benutzen die Funktion json.sort(). Als ersten Parameter geben wir die Liste, also das JSON-Array an, das sortiert werden soll. Als zweiten Parameter geben wir das Schema an, nach dem sortiert werden soll. Wir wollen aufsteigend sortieren, geben also "asc" (ascending, auf Deutsch: aufsteigend) an. Als dritten Parameter geben wir das Feld innerhalb der JSON-Objects an, das zur Sortierung genutzt werden soll. Wir wollen natürlich nach dem Gegenstandsnamen sortieren, geben also das Feld "Gegenstand" an.

Code: Select all

[h: Inventar = json.sort(Inventar, "asc", "Gegenstand")]
Geschafft. Zum Schluss rufen wir das Inventarfenster zur Aktualisierung auf:

Code: Select all

[macro("inventar@Lib:makros"): ""]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.6 - Gegenstand editieren (Formular): Das Makro

Code: Select all

[h: "<!-- Nummer des zu editierenden Gegenstandes empfangen -->"]

[h: item.nummer = macro.args]

[h: "<!-- JSON-Objekt fuer Item aus Inventar-Property abrufen -->"]

[h: item = json.get(Inventar, item.Nummer)]

[h: "<!-- Item-Daten in Variablen speichern -->"]

[h: item.name = json.get(item, "Gegenstand")]
[h: item.anzahl = json.get(item, "Anzahl")]

[h: "<!-- Eingabefenster oeffnen und HTML-Aufbau notieren -->"]

[dialog("inventarEdit", "width=308; height=239; temporary=1; input=0; noframe=0"):
  {
    [r: "
    <html>
      <head>
        <title>
          Gegenstand editieren
        </title>
      </head>
      <body>
    "]

        [h: "<!-- Beginn des Eingabeformulars -->"]

        [h: processLink = macroLinkText("inventarEditProcess@Lib:makros")]
        [r: strformat("<form action='%s'>", processLink)]

          [h: "<!-- Beginn der aeusseren Tabelle -->"]

          [r: "
          <table style='border-spacing: 0px; border: 2px solid #008000; background-color: #ffffff; width: 280'>
            <tr>
              <td style='text-align: center'>

                <!-- Tabelle fuer Ueberschrift -->

                <table style='border-spacing: 0px; margin-top: 10px; margin-bottom: 10px; width: 240'>
                  <tr>
                    <td style='font-size: 14pt; font-weight: bold; color: #ffffff; text-align: center; background-color: #008000'>
                      Gegenstand editieren
                    </td>
                  </tr>
                </table>

          <!-- Weiterfuehrung der aeusseren Tabelle -->

              </td>
            </tr>
            <tr>
              <td style='text-align: center'>
          "]

                [h: "<!-- Tabelle fuer Eingabefelder -->"]

                [r: strformat("
                <table style='border-spacing: 0px'>
                  <tr>
                    <td>
                      Anzahl:
                    </td>
                    <td>
                      <input type='text' name='iAnzahl' size='2' maxlength='2' value='%s'>
                    </td> 
                  </tr>
                  <tr>
                    <td>
                      Gegenstand:
                    </td>
                    <td>
                      <input type='text' name='iName' size='15' maxlength='27' value='%s'>
                    </td> 
                  </tr>  
                </table>
                ", item.Anzahl, item.Name)]

          [r: "
          <!-- Abschluss der aeusseren Tabelle mit Senden-Button -->

              </td>
            </tr>
            <tr>
              <td style='text-align: center; padding: 10px'>
                <input type='submit' name='processButton' value='Gegenstand ändern'>
              </td>
            </tr>
          </table>
          "]

          [h: "<!-- Item-Nummer in verstecktem Feld mitsenden -->"]

          [r: strformat("
          <input type='hidden' name='iNummer' value='%s'>
          ", item.nummer)]

    [r: "
        <!-- Formular, HTML-Bereich und Dialog-Fenster schliessen -->

        </form>
      </body>
    </html>
    "]
  }
]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.7 - Gegenstand editieren (Formular): Die Erklärung

Gegenstände sollen vom User auch editiert, also der Name und die Anzahl geändert werden können. Einen entsprechenden Link, der auch die Index-Nummer des Gegenstandes weitersendet, gibt es ja schon bei den Gegenständen im Inventarfenster. Erstelle also das neue Makro "inventarEdit" im Library-Token, es handelt sich dabei erneut um ein HTML-Formular.

Zuerst empfangen wir die Index-Nummer des Gegenstandes:

Code: Select all

[h: item.nummer = macro.args]
Mit Hilfe der Nummer holen wir uns jetzt das JSON-Object für den Gegenstand aus der Inventarliste, also dem JSON-Array:

Code: Select all

[h: item = json.get(Inventar, item.Nummer)]
Anschließend speichern wir die Daten des Gegenstandes in Variablen:

Code: Select all

[h: item.name = json.get(item, "Gegenstand")]
[h: item.anzahl = json.get(item, "Anzahl")]
Jetzt erstellen wir das Eingabefenster und den ersten Teil des Eingabeformulars. Das hast du mittlerweile schon ein paar Mal gemacht, eine nähere Erklärung ist also überflüssig.

Code: Select all

[dialog("inventarEdit", "width=308; height=239; temporary=1; input=0; noframe=0"):
  {
    [r: "
    <html>
      <head>
        <title>
          Gegenstand editieren
        </title>
      </head>
      <body>
    "]

        [h: processLink = macroLinkText("inventarEditProcess@Lib:makros")]
        [r: strformat("<form action='%s'>", processLink)]

          [r: "
          <table style='border-spacing: 0px; border: 2px solid #008000; background-color: #ffffff; width: 280'>
            <tr>
              <td style='text-align: center'>
                <table style='border-spacing: 0px; margin-top: 10px; margin-bottom: 10px; width: 240'>
                  <tr>
                    <td style='font-size: 14pt; font-weight: bold; color: #ffffff; text-align: center; background-color: #008000'>
                      Gegenstand editieren
                    </td>
                  </tr>
                </table>
              </td>
            </tr>
            <tr>
              <td style='text-align: center'>
          "]
Dann die Tabelle mit den Eingabefeldern. Diese Eingabefelder werden natürlich mit den Gegenstandsdaten vorbelegt:

Code: Select all

[r: strformat("
  <table style='border-spacing: 0px'>
    <tr>
      <td>
        Anzahl:
      </td>
      <td>
        <input type='text' name='iAnzahl' size='2' maxlength='2' value='%s'>
      </td> 
    </tr>
    <tr>
      <td>
        Gegenstand:
      </td>
      <td>
        <input type='text' name='iName' size='15' maxlength='27' value='%s'>
      </td> 
    </tr>  
  </table>
", item.Anzahl, item.Name)]
Weiter geht's:

Code: Select all

[r: "
    </td>
  </tr>
  <tr>
    <td style='text-align: center; padding: 10px'>
      <input type='submit' name='processButton' value='Gegenstand ändern'>
    </td>
  </tr>
</table>
"]
Bevor wir nun das Formular und das Makro abschließen werden wir ein weiteres Eingabefeld einbauen, und zwar ein verstecktes das der User nicht sehen kann. Mit diesem Eingabefeld werden wir, zusammen mit den vom User eingegebenen Daten, die Index-Nummer des Gegenstandes an das verarbeitende Makro schicken.

Code: Select all

[r: strformat("
<input type='hidden' name='iNummer' value='%s'>
", item.nummer)]
Und das Ende des Makros:

Code: Select all

        </form>
      </body>
    </html>
    "]
  }
]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.8 - Gegenstand editieren (Verarbeitung): Das Makro

Code: Select all

[h: "<!-- Daten aus Eingabeformular empfangen  -->"]

[h: daten = macro.args]

[h: "<!-- Eingabefenster schliessen  -->"]

[h: closeDialog("inventarEdit")]

[h: "<!-- Item-Nummer in Variable speichern -->"]

[h: index.nummer = getStrProp(daten, "iNummer")]

[h: "<!-- Neue Item-Daten in Variablen speichern -->"]

[h: item.name = getStrProp(daten, "iName")]
[h: item.anzahl = getStrProp(daten, "iAnzahl")]

[h: "<!-- Daten aus Eingabeformular auf Fehler pruefen  -->"]

[h,if(item.name == ""): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Kein Name für den Gegenstand eingegeben. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl == ""): item.anzahl = 1; item.anzahl = item.anzahl]

[h: assert(isNumber(item.anzahl), "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl != round(item.anzahl)): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl < 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Du hast eine negative Zahl eingegeben. Bitte wiederhole den Vorgang.", 0)]

[h: "<!-- JSON-Object fuer neues Item erstellen  -->"]

[h: neu.item = json.set("{}", "Gegenstand", item.name, "Anzahl", item.anzahl)]

[h: "<!-- Altes Item aus Inventar-Property loeschen -->"]

[h: Inventar = json.remove(Inventar, index.nummer)]

[h: "<!-- Neues Item in Property eintragen und Liste sortieren -->"]

[h: Inventar = json.append(Inventar, neu.Item)]
[h: Inventar = json.sort(Inventar, "asc", "Gegenstand")]

[h: "<!-- Inventar aufrufen und aktualisieren  -->"]

[macro("inventar@Lib:makros"): ""]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.9 - Gegenstand editieren (Verarbeitung): Die Erklärung

Kommen wir zum verarbeitenden Makro. Erstelle das neue Makro "itemEditProcess" im Library-Token.

Empfangen wir die neuen Daten des Gegenstandes und schließen das Eingabefenster:

Code: Select all

[h: daten = macro.args]

[h: closeDialog("inventarEdit")]
Dann speichern wir die empfangene Index-Nummer und die anderen Daten in Variablen:

Code: Select all

[h: index.nummer = getStrProp(daten, "iNummer")]

[h: item.name = getStrProp(daten, "iName")]
[h: item.anzahl = getStrProp(daten, "iAnzahl")]
Und wie immer prüfen wir die Eingaben des Users:

Code: Select all

[h,if(item.name == ""): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Kein Name für den Gegenstand eingegeben. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl == ""): item.anzahl = 1; item.anzahl = item.anzahl]

[h: assert(isNumber(item.anzahl), "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl != round(item.anzahl)): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Die Eingabe ist keine ganze Zahl. Bitte wiederhole den Vorgang.", 0)]

[h,if(item.anzahl < 0): pruefwert = 0; pruefwert = 1]
[h: assert(pruefwert, "<span style='font-weight: bold'>Fehler!</span> Du hast eine negative Zahl eingegeben. Bitte wiederhole den Vorgang.", 0)]
Mit den geänderten Daten des Gegenstandes bauen wir nun ein neues JSON-Object. Dafür nutzen wir wieder die Funktion json.set().

Code: Select all

[h: neu.item = json.set("{}", "Gegenstand", item.name, "Anzahl", item.anzahl)]
Da wir nun ein brandneues JSON-Object mit den aktuellen Daten des geänderten Gegenstandes haben, brauchen wir das alte JSON-Object in der Inventarliste nicht mehr. Also löschen wir es doch einfach aus dem JSON-Array. Das geht mit der Funktion json.remove(), bei der wir als Parameter das Array und die Index-Nummer des zu löschenden Eintrags angeben.

Code: Select all

[h: Inventar = json.remove(Inventar, index.nummer)]
Bleibt nur noch eine Aufgabe übrig, nämlich das neue JSON-Object dem Array hinzuzufügen und die Liste zu sortieren. Dafür benutzen wir mal wieder die Funktionen json.append() und json.sort().

Code: Select all

[h: Inventar = json.append(Inventar, neu.Item)]
[h: Inventar = json.sort(Inventar, "asc", "Gegenstand")]
Zum Schluss rufen wir das Inventarfenster zur Aktualisierung auf:

Code: Select all

[macro("inventar@Lib:makros"): ""]

Thargun
Giant
Posts: 188
Joined: Sun Sep 14, 2014 4:27 am

Re: Macros for Dummies - A guide to MapTool-Macros (german)

Post by Thargun »

18.10.10 - Gegenstand löschen: Das Makro

Code: Select all

[h: "<!-- Index-Nummer des zu loeschenden Items empfangen -->"]

[h: index.nummer = macro.args]

[h: "<!-- Item aus Inventar-Property loeschen -->"]

[h: Inventar = json.remove(Inventar, index.nummer)]

[h: "<!-- Inventar aufrufen und aktualisieren -->"]

[macro("inventar@Lib:makros"): ""]

Post Reply

Return to “Documentation Requests/Discussion”