You are not logged in.

Dear visitor, welcome to Runes of Magic EU. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

ArcticXWolf

Intermediate

  • "ArcticXWolf" started this thread

Posts: 1,050

Location: Ein kleines Kaff, das du nicht kennst.

  • Send private message

1

Tuesday, April 14th 2009, 10:25am

[Guide] Addonerstellung

Letztes Update: 30.06.09

Da ich hier kein deutsches Addonerstellungstutorial entdeckt habe, wollte ich dann Neulinge die Welt der RoM-Addonprogrammierung näherbringen.

VORAB: Dies soll jemandem nicht programmieren beibringen, das müsst ihr selber schon tun. Hier soll nur gezeigt werden, welches Grundgerüst ein Addon für RoM haben muss. Wer nicht programmieren kann, kann es hiernach wahrscheinlich auch nicht.

Also Schritt 0 ist sozusagen Lua lernen. (Siehe Links in Post 2)

Wer etwas hat, was umbedingt hier reinmuss, schreibt mir PM.

Bitte haltet den Thread sauber. Ergänzungen für den Guide per PN, Fragen zur Addonerstellung entweder per PN oder neuer Thread. Dankesagungen sind zwar schön, müllen aber den Thread zu. Wenn allerdings was im Tutorial unklar ist, kann das auch hier gepostet werden.

Los gehts:

Schritt 1 - Dateien erstellen

Zuallererst erstellt man einen Ordner mit dem Namen des Addons in /Interface/Addons/

Jedes Addon braucht verschiedene Dateien, die für verschiedene Dinge zuständig sind. Zuerst ist da die .toc-Datei.(Alle Dateien die wir erstellen heißen nach dem Addon(hier also Name.toc))
In dieser Datei steht, welche anderen Dateien eingebunden werden sollen. Was in den jeweiligen Dateien stehen muss, dazu komme ich in Schritt 2.

Die .xml-Datei ist fast das Wichtigste am Addon. In ihr werden die Frames, Buttons und fast alles andere des Addons deklariert und dann mit Scripten versehen. Allerdings braucht man diese nur für grafische Elemente und damit die Scripts zu bestimmten Zeiten laufen.

Optional ist die .lua-Datei. In ihr schreibt man den Code, der für die .xml-Datei zu groß ist. Theoretisch könnte man alles in die .xml-Datei schreiben, dadurch wird sie aber sehr unübersichtlich. In der .lua-Datei wird allerdings kein Frame usw. deklariert sondern nur programmiert.

Schritt 2 - Was kommt in die Dateien?

Die Dateien sind alle anders aufgebaut. Die drei Dateien(xml, toc, lua) werden als eine Textdatei erstellt, umbenannt und dann mit einem Editor (den von Windows oder notepad++) bearbeitet.

.toc-Datei: Hier kommen nur die Pfade der Dateien ab der .toc-Datei rein.
Meistens reicht hier nur die .xml-Datei einzubinden, den in dieser binden wir dann direkt die .lua ein. Wenn man die .lua jedoch schon hier einbindet, wird der Code, der nicht in einer "function" ist (Erklärung unten), beim Laden ausgeführt. So kann man, wenn man keine grafischen Elemente braucht( und auch keine Scripts zu andern Zeiten ausgeführt haben will), die xml-Datei überflüssig machen.:happydance:

Also ein Beispiel: (Das Addon heißt XXX)

XXX.toc

Source code

1
XXX.xml
Würde sich die .xml-Datei in einem Ordner namens Bla befinden, ständ dort dies:

Source code

1
Bla/XXX.xml
Zu beachten ist, dass man nicht wie bei Windows den Backslash \ benutzt, sondern den Slash /.

.xml-Datei: Hier wirds haarig. es gibt eine Menge an Möglichkeiten je nachdem, was dein Addon können muss. Hier erkläre ich den Grundaufbau.

Source code

1
<Ui xmlns="http://www.runewaker.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.runewaker.com/..\..\WorldXML\UI.xsd">
muss immer dort sein. Es macht nichts anderes, als dem Spiel zu sagen hier gehts los und es endet hier. Bei .xml-Dateien muss man alles wieder schließen. Das macht man in diesem Fall so

Source code

1
</Ui>
Dazwischen kommt dann ein

Source code

1
<Script file="XXX.lua"/>
Dies bindet die .lua-Datei ein, sofern wir eine brauchen.
Nun muss man immer ein Objekt deklarieren, an welches man dann die Scripte bindet. Jetzt wollen wir erstmal kein Fenster oä. erstellen, sondern nur unseren Code zu bestimmten Zeiten ausführen. Also schreiben wir

Source code

1
2
<Frame name="XXX" parent="UIParent" hidden="true">
</Frame>
Dies erstellt einen Frame, der den Namen XXX (der Name des Addons) trägt und seine Eigenschaften von "UIParent" (einem Frame von Spiel selber, welcher alle Frames beinhaltet). Das "hidden="true"" macht das Frame unsichtbar.

So nun kommen wir bald zum Scripten.
In dem

Source code

1
<Scripts></Scripts>
schreiben wir rein, welche Scripte wann ausgeführt werden.
Mit z.B. dem Code

Source code

1
<OnLoad>XXX_OnLoad();</OnLoad>
wird die function XXX_OnLoad() ausgeführt, sobald das Addon geladen wird.
Die Auflistung der verschiedenen Befehle für <scripts> ist im nächsten Post. (Falls noch jemand welche findet, bitte PM).


Nun zur .lua-Datei.
Wir gehen davon aus, das wir oben das mit dem OnLoad jetzt gemacht haben. Also schreiben wir

Source code

1
function XXX_OnLoad()
Dies öffnet die Funktion.
Geschlossen wird sie mit

Source code

1
end
Dazwischen kommt unser Code. Ich schreibe meistens hier einen Befehl rein, der eine Nachricht wie "Addon geladen" im Chat ausgibt. Die Funktion zum schreiben in den Chat lautet:

Source code

1
DEFAULT_CHAT_FRAME:AddMessage(string);
Das string ersetzen wir mit dem Text, den wir schreiben wollen. Dieser muss allerdings in Anführungszeichen stehen. In unserem Beispiel schreibe ich z.B.

Source code

1
DEFAULT_CHAT_FRAME:AddMessage("Addon |cff00ff00 XXX geladen.");
Wie man sieht, kann man auch hier die Farben benutzen. Das "|c" sagt dem Spiel, jetzt kommt Farbe, und danach kommen (in HEXADEZIMAL) 4mal 2 Stellen. Diese stehen 1. für die Transparenz (00 = durchsichtig), 2. für Rot, 3.Grün, 4. Blau.

Nun haben wir unser erstes Addon fertig. Der Code der Dateien sieht nun so aus:

XXX.toc:

Source code

1
XXX.xml
XXX.xml

Source code

1
2
3
4
5
6
7
8
<Ui xmlns="http://www.runewaker.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.runewaker.com/..\..\WorldXML\UI.xsd">
    <Script file="XXX.lua"/>
    <Frame name="XXX" parent="UIParent" hidden="true">
        <Scripts>
            <OnLoad>XXX_OnLoad();</OnLoad>
        </Scripts>
    </Frame>
</Ui>
XXX.lua

Source code

1
2
3
function XXX_OnLoad()
    DEFAULT_CHAT_FRAME:AddMessage("Addon |cff00ff00 XXX geladen.");
end
Wenn alle mithelfen, bekommen wir zu vielen Funktionen dann auch Erklärungen.

Ich hoffe man konnte mich verstehen, denn dies war erst mein 2. Tutorial.

mfG
ArcticXWolf

PS: Das Tutorial darf nicht kopiert oder woanders veröffentlicht werden, ausgenommen es wurde von mir erlaubt. (C) ArcticXWolf, JNR
Inaktiv..
FAQ | Addon-FAQ | Forenregeln | Suchen

ArcticXWolf

Intermediate

  • "ArcticXWolf" started this thread

Posts: 1,050

Location: Ein kleines Kaff, das du nicht kennst.

  • Send private message

2

Tuesday, April 14th 2009, 10:26am

Befehle für <scripts>:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Befehl = Wann ausgeführt;
 
[B][U]ACHTUNG:[/U][/B] Die meisten Events funktionieren nur, wenn das Frame nicht hidden ist.
 
OnLoad = beim Laden, bei ungefähr 3 Viertel des Ladebalkens.
OnSizeChanged = Wenn die Größe das Frames, Buttons etc. geändert wird.
OnEvent = Wenn bestimmte Events ausgeführt werden. (siehe unten)
OnUpdate = bei jeder Aktualisierung des Bildschirms, also fast immer.
OnShow = Sobald der Frame, Button etc. gezeigt wird.
OnHide = Sobald der Frame, Button etc. versteckt wird.
OnEnter = Sobald die Maus über dem Frame, Button etc ist und dieser sichtbar ist.
OnLeave = Sobald die Maus den Frame, Button etc. verlässt.
OnMouseDown = Wenn man die Maustaste über dem Frame, Button etc. runterdrückt.
OnMouseUp = Wenn die Maustaste losgelassen wird.
OnMouseWheel = Wenn das Mausrad über dem Frame, Button etc. betätigt wird.
OnDragStart = Sobald man anfängt den Frame (z.B. Fenster) zu verschieben.
OnDragStop = Sobald man aufhört den Frame zu verschieben.
OnReceiveDrag = Unbekannt.
OnClick = Sobald man auf den Frame, Button etc. klickt.
OnDoubleClick = Sobald man auf den Fram, Button etc. doppelklickt.
OnValueChanged = Unbekannt.
OnUpdateModel = Unbekannt.
OnAnimFinished = Unbekannt.
OnEnterPressed = Wenn Enter gedrückt wird.
OnEscapePressed = Wenn Escape gedrückt wird.
OnSpacePressed = Wenn Leertaste gedrückt wird.
OnTabPressed = Wenn Tab gedrückt wird.
OnTextChanged = Wenn der Text des Frames, Buttons etc. geändert wird.
OnTextSet = Wenn man den Text des Frames, Buttons etc. setzt (SetText()).
OnCursorChanged = Unbekannt.
OnInputLanguageChanged = Unbekannt.
OnEditFocusGained = Unbekannt
OnEditFocusLost = Unbekannt
OnHorizontalScroll = Unbekannt
OnVerticalScroll = Unbekannt
OnScrollRangeChanged = Unbekannt
OnChar = Unbekannt
OnKeyDown = Wenn eine Taste runtergedrückt wird.
OnKeyUp = Wenn eine Taste losgelassen wird.
OnColorSelect = Wenn eine Farbe ausgewählt wurde (?).
OnHyperlinkEnter = Wenn man die Maus über einen Link hält (?).
OnHyperlinkLeave = Wenn die Maus den Link verlässt (?).
OnHyperlinkClick = Wenn man auf den Link klickt (?).
OnMessageScrollChanged = Unbekannt
OnMovieFinished = Unbekannt
OnMovieShowSubtitle = Unbekannt
OnMovieHideSubtitle = Unbekannt
OnTooltipSetDefaultAnchor = Unbekannt
OnTooltipCleared = Unbekannt
OnTooltipAddMoney = Unbekannt
Bitte helft mir indem ihr Dinge, die noch unbekannt sind oder nicht gelistete Dinge mir per PN sendet.



------------------------------------------------------------

Slash-Befehle

Wenn man eigene Chat-Befehle haben möchte fügt man das am Ende der .lua ein (XXX ist der Addonname; xbefehl ist der Befehl (also gibt man ein /xbefehl)):

Source code

1
2
3
SLASH_XBEFEHL1 = "/xbefehl";
... Hier kann man noch weitere Befehle definieren(die dasselbe machen), mit SLASH_XBEFEHL2, 3, 4 etc...
SlashCmdList['XBEFEHL'] = xbefehl_start;
Nun muss man nurnoch eine function erstellen (im Beispiel mit dem Namen xbefehl_start), die ausgeführt wird, wenn man /xbefehl eingibt.



------------------------------------------------------------

Variablen speichern
Als erstes brauchen wir eine globale Table in der unsere zu speichernden Einstellungen stehen sollen.

Source code

1
MyAddOnName_mySettings = {};

Darin werden dann im AddOn selbst die jeweiligen Variablen gespeichert:

Source code

1
MyAddOnName_mySettings['1Setting'] = "BlaBla";

Und wie speichert man die Tabelle nun ab und läd sie wieder?
[INDENT]Dies geschieht indem man die Tabelle für das Speichern registriert.
[/INDENT]

Source code

1
SaveVariables("MyAddOnName_mySettings");

Wichtig sind hierbei zwei Dinge:

  • die umschliessenden "" also nicht SaveVariables(MyAddOnName_mySettings) sondern eben SaveVariables("MyAddOnName_mySettings");
  • der Zeitpunkt der Registrierung: Das Ganze sollte passieren bevor das Event VARIABLES_LOADED getriggert wird. Ein guter Platz ist daher die OnLoad Funktion des Addons
Und was hab ich nun davon?
[INDENT]Nun wird die Tabelle jedesmal kurz vor dem Event VARIABLES_LOADED mit den gespeicherten Werten bestückt und kurz nach dem Event SAVE_VARIABLES, wird der Inhalt der Tabelle wieder gespeichert.
[/INDENT]Wann werden die Events VARIABLES_LOADED und SAVE_VARIABLES ausgelöst?
[INDENT]
  • VARIABLES_LOADED: beim Laden der UI, also nach dem Einloggen,Umloggen, ReloadUI() usw.
  • SAVE_VARIABLES: kurz bevor der Char sich ausloggt

[/INDENT]Beim allerersten Laden des Addons existieren ja noch keine gespeicherten Werte, also ist MyAddOnName_mySettings leer. Daher ist es sinnvoll Defaultwerte zu definieren.


Source code

1
2
3
4
5
6
7
8
9
10
11
  local myDefaultSettings = {
    ['1Setting'] = true,
    ['2Setting'] = 1,
    ['3Setting'] = "Bla",
  };
  
  for k,v in pairs(myDefaultSettings) do
    if (MyAddOnName_mySettings[k] == nil) then
      MyAddOnName_mySettings[k] = v;
    end
  end

Und wann/wo soll das nun wieder passieren?
[INDENT][LEFT]Am besten in OnEvent bei Eintreten des VARIABLES_LOADED Events[/LEFT]


[LEFT]z.B.[/LEFT]

[LEFT]

Source code

1
function MeinAddonName_OnEvent(this, event,...) if ( event == "VARIABLES_LOADED" ) then local myDefaultSettings = {...--siehe oben end;end;
[/LEFT]
[/INDENT]Thx an morphone.


------------------------------------------------------------

Wichtige Seiten/Links:

Für RoM-API (also RoM-Funktionen, Events usw.):

http://rom.elrac.de/wiki/index.php/Addons_und_Scripting
http://www.theromwiki.com/index.php/Main_Page

Für Lua-Programmierung:

http://lua.gts-stolberg.de/
http://www.lua.org/source/5.1/
Inaktiv..
FAQ | Addon-FAQ | Forenregeln | Suchen