Gui-Hashtable-Tutorial

[contentad]


Gui-Hashtable-Tutorial

zum Anfang

1. Einleitung

Seit dem Patch 1.24 gibt es im Trigger-Editor einige neue Funktionen mit denen es viel leichter ist, einige Dinge umzusetzen. Dabei geht es vor allem um die neuen Hashtable-Funktionen zusammen mit der Funktion GetHandleID. Die Funktionsweise von beidem wird in diesem Tutorial an einem kurzen Beispiel erklärt. Grundlegende Gui-Kentnisse sollten vorhanden sein.

Achtung: Beim JassNewGen-Editor kann es passieren, dass die neuen Funktionen nicht verfügbar sind. Dies erkennt ihr zum Beispiel daran, dass es keinen Variablen-Typ „hashtable“ gibt. Ist dies bei euch der Fall versucht einfach euch nochmal die neuste Version herunterzuladen oder benutzt den normalen Editor.

zum Anfang

2. Hashtables

Was sind Hashtables überhaupt und wie kann man sie sich vorstellen? Der Zweite Teil des Wortes verrät schon, dass es sich um eine Art Tabelle handelt. Man kann in dieser Tabelle Werte speichern, indem man die Zelle durch Spalte und Zeile definiert (Bsp.: Zeile 13, Spalte 4). Statt Spalte und Zeile kann man das ganze auch als Kategorie-Nummer und Eintrags-Nummer betrachten (Bsp.: Eintrag Nummer 4 in Kategorie Nummer 13). Dies ist der wichtige Teil, den man verstehen sollte, der nächste Absatz ist nur eine kleine Zusatzinfo.
Der vordere Teil des Wortes („Hash“) gibt nur einen Hinweis auf die Funktionsweise der Tabelle. So braucht eine Tabelle nicht so viele Spalten und Zeilen wie ihr maximaler Eintrag, was jede Menge Speicherverbrauch bedeuten würde, sondern der Speicherverbrauch richtet sich eher nach der Zahl der Zellen, in denen etwas steht. Genauer will ich in diesem Tutorial aber nicht auf die Technik eingehen, da man diese nicht verstehen muss, um Hashtables zu benutzen.

Um einen Hashtable im GUI benutzen zu können, muss man sich zuerst einmal eine Variable vom Typ Hashtable erstellen (im Tutorial wird diese immer „ht“ heißen) und einen Trigger, der einen neuen Hashtable erstellt und in dieser Variable speichert:

 init

 Events

 Map initialization

 Conditions

 Actions

 ——– den Hashtable erstellen: ——–

 Hashtable – Create a hashtable

 Set ht = (Last created hashtable)

Um etwas im Hashtable zu speichern, benutzt man (je nach dem was man speichern will) eine der Save-Funktionen. Will man einen String zum Beispiel in Zeile 561, Spalte 1304 (bzw Kategorie #561, Nummer #1304) speichern benutzt man die Funktion „Save String“ folgendermaßen:

 Hashtable – Save "Das ist ein Test." as 1304 of 561 in ht

Das Laden funktioniert fast genau so über entsprechende Load-Funktionen:

 Set message = (Load 1304 of 561 from ht)

Viel mehr gibt es zu Hashtables eigentlich nicht zu sagen, denn sie sind relativ einfach aufgebaut. Trotzdem kann es etwas dauern, bis man ein Gefühl für sie bekommt. Deshalb noch ein kleines Beispiel:

 Actions

 Hashtable – Save A as 5 of 3 in ht

 Hashtable – Save B as 1 of 7 in ht

 Hashtable – Save C as 8 of 3 in ht

 Hashtable – Save E as 1 of 7 in ht

 Hashtable – Save D as 4 of 3 in ht

Nach diesen Aktionen würde unser Hastable etwa so aussehen:

1
2
3
4
5
6
7
8
9
1
2
3
D A C
4
5
6
7
E
8
9

zum Anfang

3. Get Handle ID

Die zweite wichtige Funktion ist die GetHandleID Funktion. Um zu verstehen, was diese Funktion macht, muss man wissen, dass bei Warcraft jedes Objekt (oder Handle; also Einheiten, Items, Trigger, Timer, Spezialeffekte, usw.) eine interne Nummer hat. Diese Nummer repräsentiert praktisch, an welcher Position im Speicher sich das Objekt befindet, aber das ist für uns nicht so wichtig. Wichtig ist, dass wir diese Nummer mit der Get Handle ID Funktion bekommen können und diese dann als Zeilennummer oder Spaltennummer für unsere Hashtables benutzen können. Den Sinn davon wird man gleich in einem kleinen Beispiel sehen.
Zu beachten ist hier noch, dass Objekte, nach dem sie nicht mehr existieren, ihre Nummer verlieren und neu erstellte Objekte diese Nummer dann bekommen können.

Hinweis: Die Funktion „Get Handle ID“ erscheint im GUI als „key(….)“ also beispielsweise so:

 Set i = (Key (Triggering unit))

In der Funktionsliste heißt sie aber „Hashtable – Get Handle ID“.

zum Anfang

4. Ein Beispiel

Um den Nutzen des ganzen etwas klarer zu machen, wollen wir uns ein Beispiel anschauen. Wirklich interessant wird es aber erst bei großen Beispielen, die ihr euch aber nach dem Tutorial selbst ausdenken und selbst umsetzen könnt ;)
Für das Beispiel dieses Tutorial wollen wir einen kleinen Kill-Zähler basteln. Dieser soll für jede Einheit auf der Map zählen, wie viele Einheiten sie bereits getötet hat.

Dazu erstellen wir uns zuerst wie oben erwähnt eine Hashtable Variable „ht“. Zusätzlich erstellen wir uns noch die integer-Variablen „kills“ und „_KILLS“ und die string-Variable „message“, da wir diese Variablen auch noch benutzen werden.

Zum Mapstart müssen wir natürlich den Hashtable erstellen. Um später im Code die Lesbarkeit zu verbessern, benutzen wir noch die Variable „_KILLS“ und setzen diese in der Initialisierung auf 1.

 hashtable init

 Events

 Map initialization

 Conditions

 Actions

 ——– den Hashtable erstellen: ——–

 Hashtable – Create a hashtable

 Set ht = (Last created hashtable)

 ——– Hashtable – Nummern: ——–

 Set _KILLS = 1

Wir werden dann später die Variable _KILLS verwenden, um unsere Spalte zu adressieren. Es ist sehr viel übersichtlicher zu sagen, man nimmt die _KILLS-Spalte, als zu sagen, man nimmt die Spalte 1. Im Endeffekt ist aber natürlich beides das gleiche, mit der zweiten Variante läuft man jedoch spätestens bei der fünften Spalte in Gefahr, eine Nummer zu vertauschen oder doppelt zu belegen.

Nun wollen wir den Trigger erstellen, der die Kills hochzählt. Wir werden die Kills einer Einheit wie gesagt in der _KILLS-Spalte speichern. Als Zeile benutzen wir immer die Handle-ID der Einheit. Zusammen mit einem kleinen schwebenden Text sieht der Trigger dann so aus:

 onKill

 Events

 Unit – A unit Dies

 Conditions

 Actions

 ——– Die aktuellen Kills laden und um 1 erhöhen: ——–

 Set kills = (Load _KILLS of (Key (Killing unit)) from ht)

 Set kills = (kills + 1)

 ——– Kills speichern ——–

 Hashtable – Save kills as _KILLS of (Key (Killing unit)) in ht

 ——– Die Kills ausgeben: ——–

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 If – Conditions

 kills Equal to 1

 Then – Actions

 Set message = Das war mein erster Kill!

 Else – Actions

 Set message = (Das war mein + ((String(kills)) + . Kill!))

 Floating Text – Create floating text that reads message above (Killing unit) with Z offset 0.00, using font size 8.00, color (50.00%, 50.00%, 100.00%), and 0.00% transparency

 Floating Text – Show (Last created floating text) for (All players)

 Floating Text – Change (Last created floating text): Disable permanence

 Floating Text – Set the velocity of (Last created floating text) to 40.00 towards 90.00 degrees

 Floating Text – Change the lifespan of (Last created floating text) to 6.00 seconds

 Floating Text – Change the fading age of (Last created floating text) to 4.00 seconds

 ——– Die kills der getöteten Einheit zurücksetzen. ——–

 Hashtable – Save 0 as _KILLS of (Key (Dying unit)) in ht

Die letze Zeile des Triggers ist nötig, da es passieren kann, dass eine neu erstellte Einheit die Nummer einer alten, verstorbenen Einheit bekommt (siehe Handle-ID-Kapitel). Würden wir den Wert nicht auf 0 setzen, so würde die neue Einheit auch die Kills der alten Einheit erben.

Zur ßbung könnt ihr nun noch einen Trigger bauen, der die Kills einer Einheit ausgibt, wenn man sie anklickt. Oder ihr ladet euch einfach die Beispielmap herunter und probiert das Beispiel dort aus.

zum Anfang

5. Schlusswort

Dies war zugegebenermaßen eine recht kurze Einführung, aber ich denke wenn ihr euch noch ein bisschen mit der Materie beschäftigt, könnt ihr einige interessante Dinge damit anstellen ;)
Es eignet sich hervorragend, wenn man irgendwelche Daten mit Warcraft-Objekten verknüpfen will (wie in unserem Beispiel die Kills der Einheit mit der Einheit).
Wer dieses neue Feature aber richtig professionell und effektiv nutzen möchte, der sollte vielleicht anfangen sich in (v)Jass einzuarbeiten.

Vielen Dank für das Lesen dieses Tutorials, wenn ihr noch Fragen habt, benutzt bitte das Trigger-Forum.

zum Anfang

peq
  • 11.08.2009 um 04:38
ESL Warcraft International Premiership Saison IV beendet Gui-Hashtable-Tutorial

Gui-Hashtable-Tutorial


Gui-Hashtable-Tutorial

zum Anfang

1. Einleitung

Seit dem Patch 1.24 gibt es im Trigger-Editor einige neue Funktionen mit denen es viel leichter ist, einige Dinge umzusetzen. Dabei geht es vor allem um die neuen Hashtable-Funktionen zusammen mit der Funktion GetHandleID. Die Funktionsweise von beidem wird in diesem Tutorial an einem kurzen Beispiel erklärt. Grundlegende Gui-Kentnisse sollten vorhanden sein.

Achtung: Beim JassNewGen-Editor kann es passieren, dass die neuen Funktionen nicht verfügbar sind. Dies erkennt ihr zum Beispiel daran, dass es keinen Variablen-Typ „hashtable“ gibt. Ist dies bei euch der Fall versucht einfach euch nochmal die neuste Version herunterzuladen oder benutzt den normalen Editor.

zum Anfang

2. Hashtables

Was sind Hashtables überhaupt und wie kann man sie sich vorstellen? Der Zweite Teil des Wortes verrät schon, dass es sich um eine Art Tabelle handelt. Man kann in dieser Tabelle Werte speichern, indem man die Zelle durch Spalte und Zeile definiert (Bsp.: Zeile 13, Spalte 4). Statt Spalte und Zeile kann man das ganze auch als Kategorie-Nummer und Eintrags-Nummer betrachten (Bsp.: Eintrag Nummer 4 in Kategorie Nummer 13). Dies ist der wichtige Teil, den man verstehen sollte, der nächste Absatz ist nur eine kleine Zusatzinfo.
Der vordere Teil des Wortes („Hash“) gibt nur einen Hinweis auf die Funktionsweise der Tabelle. So braucht eine Tabelle nicht so viele Spalten und Zeilen wie ihr maximaler Eintrag, was jede Menge Speicherverbrauch bedeuten würde, sondern der Speicherverbrauch richtet sich eher nach der Zahl der Zellen, in denen etwas steht. Genauer will ich in diesem Tutorial aber nicht auf die Technik eingehen, da man diese nicht verstehen muss, um Hashtables zu benutzen.

Um einen Hashtable im GUI benutzen zu können, muss man sich zuerst einmal eine Variable vom Typ Hashtable erstellen (im Tutorial wird diese immer „ht“ heißen) und einen Trigger, der einen neuen Hashtable erstellt und in dieser Variable speichert:

 init

 Events

 Map initialization

 Conditions

 Actions

 ——– den Hashtable erstellen: ——–

 Hashtable – Create a hashtable

 Set ht = (Last created hashtable)

Um etwas im Hashtable zu speichern, benutzt man (je nach dem was man speichern will) eine der Save-Funktionen. Will man einen String zum Beispiel in Zeile 561, Spalte 1304 (bzw Kategorie #561, Nummer #1304) speichern benutzt man die Funktion „Save String“ folgendermaßen:

 Hashtable – Save "Das ist ein Test." as 1304 of 561 in ht

Das Laden funktioniert fast genau so über entsprechende Load-Funktionen:

 Set message = (Load 1304 of 561 from ht)

Viel mehr gibt es zu Hashtables eigentlich nicht zu sagen, denn sie sind relativ einfach aufgebaut. Trotzdem kann es etwas dauern, bis man ein Gefühl für sie bekommt. Deshalb noch ein kleines Beispiel:

 Actions

 Hashtable – Save A as 5 of 3 in ht

 Hashtable – Save B as 1 of 7 in ht

 Hashtable – Save C as 8 of 3 in ht

 Hashtable – Save E as 1 of 7 in ht

 Hashtable – Save D as 4 of 3 in ht

Nach diesen Aktionen würde unser Hastable etwa so aussehen:

1
2
3
4
5
6
7
8
9
1
2
3
D A C
4
5
6
7
E
8
9

zum Anfang

3. Get Handle ID

Die zweite wichtige Funktion ist die GetHandleID Funktion. Um zu verstehen, was diese Funktion macht, muss man wissen, dass bei Warcraft jedes Objekt (oder Handle; also Einheiten, Items, Trigger, Timer, Spezialeffekte, usw.) eine interne Nummer hat. Diese Nummer repräsentiert praktisch, an welcher Position im Speicher sich das Objekt befindet, aber das ist für uns nicht so wichtig. Wichtig ist, dass wir diese Nummer mit der Get Handle ID Funktion bekommen können und diese dann als Zeilennummer oder Spaltennummer für unsere Hashtables benutzen können. Den Sinn davon wird man gleich in einem kleinen Beispiel sehen.
Zu beachten ist hier noch, dass Objekte, nach dem sie nicht mehr existieren, ihre Nummer verlieren und neu erstellte Objekte diese Nummer dann bekommen können.

Hinweis: Die Funktion „Get Handle ID“ erscheint im GUI als „key(….)“ also beispielsweise so:

 Set i = (Key (Triggering unit))

In der Funktionsliste heißt sie aber „Hashtable – Get Handle ID“.

zum Anfang

4. Ein Beispiel

Um den Nutzen des ganzen etwas klarer zu machen, wollen wir uns ein Beispiel anschauen. Wirklich interessant wird es aber erst bei großen Beispielen, die ihr euch aber nach dem Tutorial selbst ausdenken und selbst umsetzen könnt ;)
Für das Beispiel dieses Tutorial wollen wir einen kleinen Kill-Zähler basteln. Dieser soll für jede Einheit auf der Map zählen, wie viele Einheiten sie bereits getötet hat.

Dazu erstellen wir uns zuerst wie oben erwähnt eine Hashtable Variable „ht“. Zusätzlich erstellen wir uns noch die integer-Variablen „kills“ und „_KILLS“ und die string-Variable „message“, da wir diese Variablen auch noch benutzen werden.

Zum Mapstart müssen wir natürlich den Hashtable erstellen. Um später im Code die Lesbarkeit zu verbessern, benutzen wir noch die Variable „_KILLS“ und setzen diese in der Initialisierung auf 1.

 hashtable init

 Events

 Map initialization

 Conditions

 Actions

 ——– den Hashtable erstellen: ——–

 Hashtable – Create a hashtable

 Set ht = (Last created hashtable)

 ——– Hashtable – Nummern: ——–

 Set _KILLS = 1

Wir werden dann später die Variable _KILLS verwenden, um unsere Spalte zu adressieren. Es ist sehr viel übersichtlicher zu sagen, man nimmt die _KILLS-Spalte, als zu sagen, man nimmt die Spalte 1. Im Endeffekt ist aber natürlich beides das gleiche, mit der zweiten Variante läuft man jedoch spätestens bei der fünften Spalte in Gefahr, eine Nummer zu vertauschen oder doppelt zu belegen.

Nun wollen wir den Trigger erstellen, der die Kills hochzählt. Wir werden die Kills einer Einheit wie gesagt in der _KILLS-Spalte speichern. Als Zeile benutzen wir immer die Handle-ID der Einheit. Zusammen mit einem kleinen schwebenden Text sieht der Trigger dann so aus:

 onKill

 Events

 Unit – A unit Dies

 Conditions

 Actions

 ——– Die aktuellen Kills laden und um 1 erhöhen: ——–

 Set kills = (Load _KILLS of (Key (Killing unit)) from ht)

 Set kills = (kills + 1)

 ——– Kills speichern ——–

 Hashtable – Save kills as _KILLS of (Key (Killing unit)) in ht

 ——– Die Kills ausgeben: ——–

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 If – Conditions

 kills Equal to 1

 Then – Actions

 Set message = Das war mein erster Kill!

 Else – Actions

 Set message = (Das war mein + ((String(kills)) + . Kill!))

 Floating Text – Create floating text that reads message above (Killing unit) with Z offset 0.00, using font size 8.00, color (50.00%, 50.00%, 100.00%), and 0.00% transparency

 Floating Text – Show (Last created floating text) for (All players)

 Floating Text – Change (Last created floating text): Disable permanence

 Floating Text – Set the velocity of (Last created floating text) to 40.00 towards 90.00 degrees

 Floating Text – Change the lifespan of (Last created floating text) to 6.00 seconds

 Floating Text – Change the fading age of (Last created floating text) to 4.00 seconds

 ——– Die kills der getöteten Einheit zurücksetzen. ——–

 Hashtable – Save 0 as _KILLS of (Key (Dying unit)) in ht

Die letze Zeile des Triggers ist nötig, da es passieren kann, dass eine neu erstellte Einheit die Nummer einer alten, verstorbenen Einheit bekommt (siehe Handle-ID-Kapitel). Würden wir den Wert nicht auf 0 setzen, so würde die neue Einheit auch die Kills der alten Einheit erben.

Zur Übung könnt ihr nun noch einen Trigger bauen, der die Kills einer Einheit ausgibt, wenn man sie anklickt. Oder ihr ladet euch einfach die Beispielmap herunter und probiert das Beispiel dort aus.

zum Anfang

5. Schlusswort

Dies war zugegebenermaßen eine recht kurze Einführung, aber ich denke wenn ihr euch noch ein bisschen mit der Materie beschäftigt, könnt ihr einige interessante Dinge damit anstellen ;)
Es eignet sich hervorragend, wenn man irgendwelche Daten mit Warcraft-Objekten verknüpfen will (wie in unserem Beispiel die Kills der Einheit mit der Einheit).
Wer dieses neue Feature aber richtig professionell und effektiv nutzen möchte, der sollte vielleicht anfangen sich in (v)Jass einzuarbeiten.

Vielen Dank für das Lesen dieses Tutorials, wenn ihr noch Fragen habt, benutzt bitte das Trigger-Forum.

zum Anfang

peq
  • 11.08.2009 um 02:38
Gui-Hashtable-Tutorial Kein WTV mehr bei ESL TV-ßbertragungen