oUF Code schnipsel

wertzû

Welt-Boss
Mitglied seit
12.01.2008
Beiträge
2.803
Reaktionspunkte
20
Kommentare
76
Hallo
Ich liste hier paar nützliche Funktionen bzw Tipps zu oUF auf. Warum ist ganz einfach:
oUF(otravi Unitframes, geschrieben von Haste) ist eigentlich das beste Unitframe AddOn.
Jedoch schreibt man die Unitframes in LUA (Der WoW Internen Programmiersprache), das schreckt viele davon ab.
Ich will euch eigentlich nur zeigen das es gar nicht so schwer ist (Vorkenntnisse von Lua braucht man jedoch, zwar nur wenig aber man braucht es).

Ich werde immer wieder Sachen hinzufügen. Ich bitte euch wenn ihr auch nen tollen Script habt ihn zu posten und zu erläutern was er bewirkt.


Link Auflistung
oUF_Wiki
Events
Frame_API
WoW_API



Schneller Strings erstellen
Was tut es? Schneller CreateFontString ausführen, Schrift(Schriftart, Schriftgrösse, SchriftHintergrund) und Ausrichtung des Textes bestimmen

Code:
SetFontString = function(parent, fontName, fontHeight, fontStyle)
	local fs = parent:CreateFontString(nil, "OVERLAY")
	fs:SetFont( fontName, fontHeight, fontStyle)
	fs:SetJustifyH("LEFT")
	return fs
end

Aussführung:
Code:
NameDesTextFrames = SetFontString(Frame, Schriftgrösse, Schriftstyle)
Beispiel
Code:
self.Health.Text = SetFontString(self.Health, "Fonts\\ARIALN.ttf", 12, "OUTLINE")
Zahlen kürzen
Bewirkt das 1200 zu 1.2k wird

Code:
local ShortValue = function(value)
	if value >= 1e6 then
		return ("%.1fm"):format(value / 1e6):gsub("%.?0+([km]){:content:}quot;, "%1")
	elseif value >= 1e3 or value <= -1e3 then
		return ("%.1fk"):format(value / 1e3):gsub("%.?0+([km]){:content:}quot;, "%1")
	else
		return value
	end
end
local ShortValueNegative = function(v)
	if v <= 999 then return v end
	if v >= 1000000 then
		local value = string.format("%.1fm", v/1000000)
		return value
	elseif v >= 1000 then
		local value = string.format("%.1fk", v/1000)
		return value
	end
end

Ausführung

Code:
ShortValue(PositiveZahl)
ShortValueNegative(NegativeZahl)
Auren funktionalität steigern
Hier wird einfach gekürzt und gerundet. Beispiel: Aus 2 Minuten und 20 Sekunden wird 2 Minuten.

Code:
local FormatTime = function(s)
	local day, hour, minute = 86400, 3600, 60
	if s >= day then
		return format("%dd", ceil(s / hour))
	elseif s >= hour then
		return format("%dh", ceil(s / hour))
	elseif s >= minute then
		return format("%dm", ceil(s / minute))
	elseif s >= minute / 12 then
		return floor(s)
	end
	return format("%.1f", s)
end

Eigenes OmniCC für Auren wird erstellt
Code:
local CreateAuraTimer = function(self, elapsed)
	if self.timeLeft then
		self.elapsed = (self.elapsed or 0) + elapsed
		if self.elapsed >= 0.1 then
			if not self.first then
				self.timeLeft = self.timeLeft - self.elapsed
			else
				self.timeLeft = self.timeLeft - GetTime()
				self.first = false
			end
			if self.timeLeft > 0 then
				local time = FormatTime(self.timeLeft)
				self.remaining:SetText(time)
				if self.timeLeft <= 5 then
					self.remaining:SetTextColor(0.99, 0.31, 0.31)
				else
					self.remaining:SetTextColor(1, 1, 1)
				end
			else
				self.remaining:Hide()
				self:SetScript("OnUpdate", nil)
			end
			self.elapsed = 0
		end
	end
end
In diesem teil werden die Auras "geskinnt". Ein 3 Pixelborder wird durch SetBackdrop erzeugt. Statt OmniCC wird ein eigener Text verwendet damit man nicht einen zu grossen Text auf den Auren hat. Auch Counts (also Zählungen, wie bei Blühendes Leben) werden erstellt.
Code:
function PostCreateAura(element, button)
    button:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8", 
        edgeFile = "Interface\\Buttons\\WHITE8x8", 
        tile = false,
        tileSize = 0,
        edgeSize = 1, 
        insets = {
        left = -1,
        right = -1,
        top = -1,
        bottom = -1
        }
    });
    button:SetBackdropBorderColor(0.2, 0.2, 0.2);
    button:SetBackdropColor(0, 0, 0)
	
	button.remaining = SetFontString(button, font, 11, "THINOUTLINE")
	button.remaining:SetPoint("CENTER", 0, 0)
	
	button.cd.noOCC = true 				-- hide OmniCC CDs
	button.cd.noCooldownCount = true    -- hide CDC CDs
	
	button.cd:SetReverse()
	button.icon:SetPoint("TOPLEFT", 2, -2)
	button.icon:SetPoint("BOTTOMRIGHT", -2, 2)
	button.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
	button.icon:SetDrawLayer('ARTWORK')
	
	button.count:SetPoint("BOTTOMRIGHT", 3, 1.5)
	button.count:SetJustifyH("RIGHT")
	button.count:SetFont(font, 9, "THICKOUTLINE")
	button.count:SetTextColor(0.84, 0.75, 0.65)

	button.overlayFrame = CreateFrame("frame", nil, button, nil)
	button.cd:SetFrameLevel(button:GetFrameLevel() + 1)
	button.cd:ClearAllPoints()
	button.cd:SetPoint("TOPLEFT", button, "TOPLEFT", 2, -2)
	button.cd:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
    
	button.overlayFrame:SetFrameLevel(button.cd:GetFrameLevel() + 1)   	
	button.overlay:SetParent(button.overlayFrame)
	button.count:SetParent(button.overlayFrame)
	button.remaining:SetParent(button.overlayFrame)
end
Dieser teil des Codes macht das wenn du eine Krankheit auf den Gegner wirkst, dass das Panel um der Debuff braun gefärbt wird. (Blau für Magie, Violet für Fluch und Rot für nicht Spezifiziert). Ausserdem bewirkt es das der Debuff ausgegraut wird wenn jemand anderen als du einen draufhaut.
Code:
function PostUpdateAura(icons, unit, icon, index, offset, filter, isDebuff, duration, timeLeft)
	local _, _, _, _, dtype, duration, expirationTime, unitCaster, _ = UnitAura(unit, index, icon.filter)
    
	if(icon.debuff) then
		if(not UnitIsFriend("player", unit) and icon.owner ~= "player" and icon.owner ~= "vehicle") then
			icon:SetBackdropBorderColor(0.2, 0.2, 0.2) -- Border Color
			icon.icon:SetDesaturated(true)
		else
			local color = DebuffTypeColor[dtype] or DebuffTypeColor.none
			icon:SetBackdropBorderColor(color.r * 0.6, color.g * 0.6, color.b * 0.6)
			icon.icon:SetDesaturated(false)
		end
	end

	if duration and duration > 0 then
        icon.remaining:Show()
	else
		icon.remaining:Hide()
	end
 
	icon.duration = duration
	icon.timeLeft = expirationTime
	icon.first = true
	icon:SetScript("OnUpdate", CreateAuraTimer)
end
Jedoch muss man die Funktion bei den Auren bestimmen (Je nach Frame müsst ihr ein anderes wählen)
Code:
self.Auras.PostUpdateIcon = PostUpdateAura
self.Auras.PostCreateIcon = PostCreateAura

self.Debuffs.PostCreateIcon = PostCreateAura
self.Debuffs.PostUpdateIcon = PostUpdateAura

self.Buffs.PostUpdateIcon = PostUpdateAura
self.Buffs.PostCreateIcon = PostCreateAura
Text ausgabe (Beispiele mit Lebensanzeige)
Mit dem wird die Funktion bestimmt
Code:
local HealthPostUpdate = function(health, unit, min, max)
	self.Health.Percent:SetText("|cffaf243a"..(min/max*100).."|r")
end;

damit wird Sie ausgeführt
Code:
self.Health.Percent = self.Health:CreateFontString(nil, "OVERLAY")
self.Health.Percent:SetPoint("CENTER", self.Health, "CENTER", 0, 0);
self.Health.Percent:SetFont("Fonts\\ARIALN.ttf", 12, nil)
self.Health.Percent:SetJustifyH("LEFT")
self.Health.PostUpdate = HealthPostUpdate

Natürlich kann man das noch aufbauen. Z.B. ein String für aktuelles Leben einbauen.

Funktion würde dann so aussehen.
Code:
local HealthPostUpdate = function(health, unit, min, max)
	self.Health.Percent:SetText("|cffaf243a"..(min/max*100).."|r")
	self.Health.Value:SetText("|cffaf243a"..min.."|r")
end;


dann halt wie oben ein Frame mit dem Namen self.Health.Value bestimmen
Code:
self.Health.Value = self.Health:CreateFontString(nil, "OVERLAY")
self.Health.Value:SetPoint("CENTER", self.Health, "CENTER", 0, 0);
self.Health.Value:SetFont("Fonts\\ARIALN.ttf", 12, nil)
self.Health.Valuet:SetJustifyH("LEFT")


Code:
self.Health.PostUpdate = HealthPostUpdate
muss man nur einmal angeben.

Codeschnipsel aus meinem UI
Code:
local HealthPostUpdate = function(health, unit, min, max)
	self.Health.Percent:SetText("|cffaf243a"..(min/max*100).."|r")
	self.Health.Value:SetText("|cffaf243a"..min.." / ".."max"|r")
end;

self.Health.Value gibt folgenden Wert aus (AKTUELLESLEBEN / MAXIMALESLEBEN). In der farbe af243a (was einem Dunkelrot entspricht).
Self.Health.Percent gibt folgenden Wert aus (ANZAHLPROZENT Des Lebens (ohne %)). In der farbe af243a (was einem Dunkelrot entspricht).

PS: Das gleiche gilt für die Power werte. Ihr müsst einfach Health durch Power ersetzen
Panel um aktuelles Target tun.
Was tut es? Es zaubert ein Blaues Panel um das Unit das du anvisiert hast. Eignet sich am besten für: Party, Raid, ArenaFrames, BossFrames


es sieht so aus


Code:
self.Border = CreateFrame("Frame", nil, self);
self.Border:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    title = false,
    tileSize = 0,
    edgeSize = 1,
    insets = {
        left = -1,
        right = -1,
        top = -1,
        bottom = -1
    }
})
self.Border:SetPoint("TOPLEFT",-2,2);
self.Border:SetPoint("BOTTOMRIGHT",2,-2);
self.Border:SetFrameStrata(self:GetFrameStrata());
self.Border:SetFrameLevel(self:GetFrameLevel()-1);
self.Border:SetBackdropBorderColor(0.31, 0.45, 0.63);
self.Border:SetBackdropColor(0,0,0,1);
self.Border:Hide();

self:RegisterEvent("PLAYER_TARGET_CHANGED", function(self)
    if ( UnitIsUnit("target", self.unit) ) then
        self.Border:Show();
    else
        self.Border:Hide();
    end
end);
Tags erstellen (Afk-Tag Beispiel)
Ach verdammt, wie ich sie hasste (obwohl sie ganz einfach sind)

Erstmal zum Beispiel
Code:
oUF.TagEvents['afk'] = 'PLAYER_FLAGS_CHANGED'
oUF.Tags['afk'] = function(unit)
	if UnitIsAFK(unit) then
		return CHAT_FLAG_AFK
	end
end

So was tut es? Erste Zeile Bestimmt Event, dass das Tag braucht, in dem Beispiel wann der Status des Spielers ändert. Bei der zweiten Zeile wird die Funktion bestimmt (Name, im Beispiel afk, muss in beiden Zeilen gleich sein).
Dann wird eine if Abfrage gestartet ob das Unit afk ist. Wenn Ja dann gibt es AFK aus (Das Return ist ganz wichtig, ohne das wird nicht ausgegeben).

Damit der Tag ausgeführt wird muss ein Frame erstellt werden(Und Fontstring muss bestimmt werden).
Danach fügt man einfach
Code:
self:Tag(NameDesFrames, '[afk]')
ein.

Man kann auch mehrere Tags in einem einfügen. Aus [afk] kann z.B. [afk][dnd][...] werden. Jedoch müssen diese Tags erst erstellt werden. In oUF gibt es auch schon bestehende Tags. Die werde ich noch auflisten.

Icons

Combat Icon
Gibt nicht viel zusagen, ist alles selbst erklärend
Code:
    local self.Combat = self.Health:CreateTexture(nil, "OVERLAY")
    self.Combat:SetHeight(19)
    self.Combat:SetWidth(19)
    self.Combat:SetPoint("CENTER",0,1)
    self.Combat:SetVertexColor(0.69, 0.31, 0.31)
Leader Icon
auch hier selbsterklärend
Code:
    local self.Leader = self.Health:CreateTexture(nil, "OVERLAY")
    self.Leader:SetHeight(14);
    self.Leader:SetWidth(14);
    self.Leader:SetPoint("TOPLEFT", 2, 8);
Masterloot Icon
Auch hier selbsterklärend
Code:
    local self.MasterLooter = self.Health:CreateTexture(nil, "OVERLAY")
    self.MasterLooter:SetHeight(14);
    self.MasterLooter:SetWidth(14);
    self.MasterLooter:SetPoint("TOP",self,0,5);
Raid Icons
Auch hier selbsterklärend
Code:
	local self.RaidIcon = self.Health:CreateTexture(nil, "OVERLAY")
	self.RaidIcon:SetHeight(20)
	self.RaidIcon:SetWidth(20)
	self.RaidIcon:SetPoint("TOP", 0, 8)
LFD Icons
Auch hier selbsterklärend
Code:
    local self.LFDRole = self.Health:CreateTexture(nil, "OVERLAY")
    self.LFDRole:SetHeight(19)
    self.LFDRole:SetWidth(19)
    self.LFDRole:SetPoint("TOPLEFT",4,1)
Phasing Icons
Auch hier selbsterklärend
Code:
    local self.PhaseIcon = self.Health:CreateTexture(nil, "OVERLAY")
    self.PhaseIcon:SetHeight(19)
    self.PhaseIcont:SetWidth(19)
    self.PhaseIcon:SetPoint("TOPLEFT",4,1)
Quest Icons
Auch hier selbsterklärend
Code:
    local self.QuestIcon = self.Health:CreateTexture(nil, "OVERLAY")
    self.QuestIcon:SetHeight(19)
    self.QuestIcon:SetWidth(19)
    self.QuestIcon:SetPoint("TOPLEFT",4,1)
PvP Icons
Auch hier selbsterklärend
Code:
    local self.PvP = self.Health:CreateTexture(nil, "OVERLAY")
    self.PvP:SetHeight(19)
    self.PvP:SetWidth(19)
    self.PvP:SetPoint("TOPLEFT",4,1)

Castbar

Castbartext (was zauber ich)

Eigentlich ganz einfach, das einzige was man wissen muss ist wie das Frame heissen muss.
Code:
self.Castbar.Text = self.Castbar:CreateFontString(nil, "OVERLAY")
self.Castbar.Text:SetFont("Fonts\\ARIALN.ttf", 12, nil)
self.Castbar.Text:SetPoint("LEFT", self.Castbar.Textr, "LEFT", 4, 0);

Castbartime (wie lange zauber ich schon)
Auch einfach, wie oben braucht man nur den Namen.
Code:
self.Castbar.Time = self.Castbar:CreateFontString(nil, "OVERLAY")
self.Castbar.Time:SetFont("Fonts\\ARIALN.ttf", 12, nil)
self.Castbar.Time:SetPoint("RIGHT", sel.Castbar, "RIGHT", -4, 0);
Safezone (Latenzanzeige auf dem Zauberbalken)
Ist eigentlich ganz einfach, man braucht auch hier nur den Namen, ABER
Es wird deshalb eine Textur zugewiesen da oUF SetTexture benutzt, jedoch will man ein Rot zuweisen ist das schwerer als sonst (Farbe weicht ab).
Code:
local self.Castbar.SafeZone = self.Castbar:CreateTexture(nil, "OVERLAY")
self.Castbar.SafeZone:SetTexture(NAME_DER_TEXTUR)
self.Castbar.SafeZone:SetVertexColor(139/255, 0, 0, 1)

 
Zuletzt bearbeitet von einem Moderator:
Gute Auflistung einzelner Funktionen.
Ich als Programmierer finde es leicht zu verstehen, hoffentlich sehen das die Leute die sich nicht so gut auskennen auch so.

Ich verwende leider kein oUF und keine anderen Unit frames, aber für die die oUF verwenden oder es vielleicht vor haben finde ich es hier gut sich zu Informieren.

Hast du vielleicht irgentwo eine Einführung in LUA oder auch einen Link zu den einzelnen Funktionen von oUF?
Wär sicher nützlich meiner Meinung nach.

edit sagt: Oo ich schrieb nicht leicht zu verstehen.. nein, ich verstehs;)
Gute Arbeit bisher, der Guide wächst =)
 
Zuletzt bearbeitet von einem Moderator:
Gerade keinen zur Hand. Den alten Lua guide den ich hatte gibt es nicht mehr. Zu oUF speziell... hmpf. Gerade keinen im Sinn. Ich suche wenn ich Zeit hab einen und poste ihn hier rein.
 
Ich finds recht gut, versuche mir möglichst viel übers programieren bei zu bringen, was leider fehlt mir dazu seit einiger Zeit und zur Zeit die Freizeit dazu es zuhause zutun (opfere für so was auch gerne mal den Rest von meiner Freizeit). Leider haben wir in der Schule erst Java durchgekaut und ein kleinen Teil von HTML würde aber durch aus gerne merh lernen und da hilft so was gut weiter.^^
Edit: Aber bei allen sollte man mit Grundkenntnis anfangen, was ich so auf den ersten Blick hir auch wohl tun muss.
 
Zuletzt bearbeitet von einem Moderator:
Das meiste was man braucht ist eh die Frame kenntnisse. Rest macht man nur 1 mal und nutzt dann Copy&Paste.
 
Das "local" ist doch unnötig bei diesem hier zb. :
Code:
local self.RaidIcon = self.Health:CreateTexture(nil, "OVERLAY")
        self.RaidIcon:SetHeight(20)
        self.RaidIcon:SetWidth(20)
        self.RaidIcon:SetPoint("TOP", 0, 8)
(also ich sehe oft bei den self.blahblah kein "local" davor)

Und was sehr nützlich ist das oUF Wiki von haste!
https://github.com/haste/oUF/wiki
 
Ja es ist nicht nötig, erspart aber Ärger wenn es konflikte mit anderen AddOns gibt. (Syntax sieht damit auch schöner aus)
e: Stimmt, war ja noch das Wiki, naja auch nicht ganz vollendet
 
Zuletzt bearbeitet von einem Moderator:
Hey thx =) hat mir stellenweiße echt weitergeholfen
 
Jo, das "local" sollte bei self.xxx weg. :-)
Macht absolut 0 Sinn.
Code:
local frame = CreateFrame("Frame", "FrameNameABC");

frame.texture = frame:CreateTexture("$parentTexture", "OVERLAY");
FrameNameABC ist die Tabelle frame und FrameNameABCTexture ist in der Tabelle frame als Tabelle texture.

Man kann frame.texture von aussen nicht überschreiben, da es in der Tabelle frame ist und frame ist lokalisiert, daher ist "local" davor unsinnig.
 
Zuletzt bearbeitet von einem Moderator:
Ah ok, lass es trozdem drin, einfach weil ich local so gern mag
 
Dann solltest local dich mal an meckern, damit du es nicht mehr mags... :-P

Macht die Datei nur grösser, was wiederum heisst, dass das laden länger dauert^^
 
hehe Naja um das laden mach ich mir erst sorgen wenn es länger als 5 sekunden geht (dann gibts immer nen lua error :'( )
Du Shanty, sag mal
Wann Veröffentlichst du deine AB's/AB-Styler oder Buff AddOn? (Oder das mit dem AB leuchten wenn du dran weiter gearbeitet hast, bei mir spinnt das immer noch bisschen rum)
 
Zuletzt bearbeitet von einem Moderator:
Wenn ich mal weiter bauen kann. :-) Mein Account ist schon wieder seit knapp 4 Wochen eingefroren, kein Geld... :-/
 
Oh mist :'( dacht schon du hast keine lust mehr.
 
Wie sieht denn dieses Unitframe Addon aus?
Will mir nix zusammenbasteln wenn ich dann sowieso sage das gefällt mir nicht xD

Screen pls
 
Screenshot ist bisschen schlecht bei einem Framework... ^^ Du kannst mit oUF _ALLES_ machen, was du dir vorstellen kannst... ^^
 
oUF kann alles, deshalb sollte man es auch benutzen
 
Zurück