Thread Tools Display Modes
07-22-08, 03:38 AM   #1
Sjak
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 13
I suck at this (first proper mod help)

Ok, I've spent the last day or so trying to make this work. I'm making a mod that will display some text when a buff is missing from the player (specifically an aura/blessing). However, using the "UIErrorsFrame" doesn't work because my message doesn't stay there - it fades and then doesn't come back. How would I make a message stay on the screen until the buff is found?

This is the main function for buff finding:

Code:
function CheckForAura(auraName, unit)
	auraName = auraName or "" 
	unit = unit or "player" 
	local i = 1
	local n = UnitBuff(unit, i) 
		while n do 
			if strfind(n, auraName) then 
			return true 
		end
	i = i + 1
	n = UnitBuff(auraName, i) 
	end
end
Thanks
  Reply With Quote
07-22-08, 03:53 AM   #2
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
Code:
local function UnitHasBuff(buff, unit)
	local i, n = 1 
	repeat
		n = UnitBuff(unit, i)
		i = i + 1
		if n == buff then
			return true
		end
	until not n
end
should work. Your code had an infinite loop in it as you didn't update n or i in the loop. I would also use buff texture instead of name so you don't have to localise.
  Reply With Quote
07-22-08, 04:05 AM   #3
Sjak
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 13
Ok thanks, but does that count partial matches? Ideally it would throw up a message every time the player didn't have a buff with "Aura" or "Blesssing of" in the name, otherwise it'll take a huge 'if' statement (right?)
  Reply With Quote
07-22-08, 04:42 AM   #4
VagrantEsha
Token Werewolf Fan
 
VagrantEsha's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 27
You'd probably be better off using the COMBAT_LOG_EVENT for what you're trying to do.

http://www.wowwiki.com/API_COMBAT_LOG_EVENT

Aura scanning is really overdoing things these days, and it's considered as a bit of a nuke solution unless it's absolutely needed for some reason. With that event, you'll pretty much be able to register it and do a spellName:find(myVar) on it.

One other thing I'll say is that if you're not encapsulating your mod in a table,, be sure to localise all your functions (put local before each function name, local function myFunc() instead of just function myFunc()). Slakah detailed this in his suggestion, but I thought I'd extrapolate.
  Reply With Quote
07-22-08, 05:35 AM   #5
Sjak
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 13
Ok, I don't think I've ever been as confused as I am now

Is there something wrong with what I have now? From what I understood about the combat log, arg2 is the event (spell_aura_removed in this case) and ar9 is the name but nothing happens. More confusing is that the onload event doesn't seem to do anything - no message is added to the chat unless it's outside the function but I wanted to know if it was actually working.

LUA
Code:
function Blaura_OnLoad()
	this:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	DEFAULT_CHAT_FRAME:AddMessage("Blaura has been loaded.")
end

function Blaura_OnEvent()
	if (event=="COMBAT_LOG_EVENT_UNFILTERED") then
		if (arg2=="SPELL_AURA_REMOVED") then
			if(arg9=="Seal of Righteousness") then
				UIErrorsFrame:AddMessage("Oh Noes");
			end
		end
	end
end
XML
Code:
<Frame name="Blaura_Frame">
  <Scripts>
     <OnLoad>
        Blaura_OnLoad()
     </OnLoad>
     <OnEvent>
        Blaura_OnEvent()
     </OnEvent>
  </Scripts>
</Frame>
(UI tag omitted)
So what have I done wrong :P?
  Reply With Quote
07-22-08, 11:32 AM   #6
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
First, use self instead of this. Second, since you're only registering for one event, you don't need to check to see which event fired. Third, you don't need that xml file, as you did everything in the lua. Lastly, arg3 is the event type.

edit: correction: you used the xml file to create your frame - completely missed that. But just create your frame in the lua file.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-22-08, 12:02 PM   #7
Icecoldcoke
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 132
Originally Posted by Seerah View Post
Lastly, arg3 is the event type.
Not really. arg1 is timestamp, arg2 is event type, and arg3 is sourceGUID.

What is wrong in your args is that arg9 is the spellID, and arg10 is the spellname

Code:
7/21 19:39:05.942  SPELL_CAST_SUCCESS,0x00000000012533F8,"Icecoldcoke",0x511,0x0000000000000000,nil,0x80000000,33736,"Water Shield",0x8

Last edited by Icecoldcoke : 07-22-08 at 12:06 PM.
  Reply With Quote
07-22-08, 12:48 PM   #8
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
Don't use this and the global argN's blizzard will be removing them in wotlk.

Last edited by Slakah : 07-23-08 at 05:33 AM. Reason: I suck at grammar.
  Reply With Quote
07-22-08, 02:18 PM   #9
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by Icecoldcoke View Post
Not really. arg1 is timestamp, arg2 is event type, and arg3 is sourceGUID.

What is wrong in your args is that arg9 is the spellID, and arg10 is the spellname

Code:
7/21 19:39:05.942  SPELL_CAST_SUCCESS,0x00000000012533F8,"Icecoldcoke",0x511,0x0000000000000000,nil,0x80000000,33736,"Water Shield",0x8
Ah, duh. I do
Code:
function() MyMod:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventType, etc)
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-23-08, 04:37 AM   #10
VagrantEsha
Token Werewolf Fan
 
VagrantEsha's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 27
Actually Seerah, in his example it should be this (due to him using a Blizzard frame object via XML, as opposed to Ace3/Dongle), but he's going about things in the wrong way. To the OP, you should never use an XML file to do what you're doing, so to help I've rewritten what you had there in such a way that you'll not need the XML file...

Code:
local addon = CreateFrame("Button", "MyAddonName", UIParent)

addon:RegisterEvent"COMBAT_LOG_EVENT_UNFILTERED"
-- Don't use a loaded message, players never want to see them.
addon:SetScript("OnEvent", addon.log_handler)

-- You don't need to do an event check, because you're only loading one event.
function addon.log_handler(_, _, _, state, _, _, _, _, _, _, _, spell)
	if state == "SPELL_AURA_REMOVED" and spell == "Seal of Righteousness" then
		UIErrorsFrame:AddMessage("onoz, i r become unsealed! OMG FIX PLX!")
	end
end
With this, you only need two files: the toc and the lua.

If you're serious about modding, I'd recommend you grab the new Programming in World of Warcraft book, and even more importantly, read the online print of Programming in Lua (you can buy a hard copy of that too though, if you'd like). They'll be invaluable to you over the years if you really do set foot down this path, I can pretty much promise you that. Well, unless clad's lost his touch, but somehow I doubt that.

(Edit: D'oh! I forgot to put the AddMessage on UIErrorsFrame, for some reason I was thinking of it as a function, rather than a frame. The hell, brain?)

Last edited by VagrantEsha : 07-23-08 at 04:45 AM.
  Reply With Quote
07-23-08, 05:35 AM   #11
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
Make it a local function, noone will want access to that event handler.
  Reply With Quote
07-23-08, 07:26 AM   #12
VagrantEsha
Token Werewolf Fan
 
VagrantEsha's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 27
It is local.

Note: local addon

The table is local, therefore everything held within the table is also local, by inheritance.

Edit:

I'll explain that, just in case...

Basically, I just did function addon.log_handler (local) as opposed to local function log_handler (also local). Since the table was there though, I figured I might aswell make use of it because it makes the code look more cohesive and it's generally cleaner.

An example of this is if you were to do create a local table and put a print function inside of that. So let's say you had local bob = {} and function bob.print() DEFAULT_CHAT_FRAME:AddMessage("Hello World!") end, because bob is local, bob.print is local. You'd only be able to call bob.print within the namespace of the mod, it wouldn't be in the global namespace. Try calling bob.print() in-game to see for yourself.

Putting things in one local table is just how I do things. If there's no need for me to create a local table (in this case, the button frame for registering events) then generally I just create a bunch of local funcs, but if the table's there... I use it. It looks nice.

Last edited by VagrantEsha : 07-23-08 at 07:43 AM.
  Reply With Quote
07-23-08, 07:55 AM   #13
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
Yeh I get locals and globals I just personally try and use tables as sparingly as possible, I'm still fairly new to coding and thus I use terms in the wrong places :P.

Last edited by Slakah : 07-23-08 at 07:59 AM.
  Reply With Quote
07-23-08, 12:49 PM   #14
Sjak
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 13
Originally Posted by VagrantEsha View Post
Code:
local addon = CreateFrame("Button", "MyAddonName", UIParent)

addon:RegisterEvent"COMBAT_LOG_EVENT_UNFILTERED"
-- Don't use a loaded message, players never want to see them.
addon:SetScript("OnEvent", addon.log_handler)

-- You don't need to do an event check, because you're only loading one event.
function addon.log_handler(_, _, _, state, _, _, _, _, _, _, _, spell)
	if state == "SPELL_AURA_REMOVED" and spell == "Seal of Righteousness" then
		UIErrorsFrame:AddMessage("onoz, i r become unsealed! OMG FIX PLX!")
	end
end
(Edit: D'oh! I forgot to put the AddMessage on UIErrorsFrame, for some reason I was thinking of it as a function, rather than a frame. The hell, brain?)
lol, I figured out my problem anyway - I forgot to add the .xml file to the toc

Thanks for your help, I should have it tested/uploaded by tonight.

Oh, the loading text was only there so I could see if it was working, I would have removed it before release

EDIT: The code you gave me didn't seem to work? I fixed the stuff I had before (with xml included). Is there some reason why xml files should be avoided? It works perfectly now, the only problem is that it's a huge
'if x then
y
elseif z then
a
elseif ....'

Last edited by Sjak : 07-23-08 at 01:12 PM.
  Reply With Quote
07-23-08, 01:21 PM   #15
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
Its partially due to people using the globals "this" and argN's instead of passing arguments to the function, and the functions have to be placed in the global environment for the lua to have access to it. Whereas using when only using lua you can keep the whole thing local, and frames can be created dynamically.
  Reply With Quote
07-23-08, 01:23 PM   #16
Sjak
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 13
Originally Posted by Slakah View Post
Its partially due to people using the globals "this" and argN's instead of passing arguments to the function, and the functions have to be placed in the global environment for the lua to have access to it. Whereas using when only using lua you can keep the whole thing local, and frames can be created dynamically.
So it's mainly because global functions can be overwritten/overwrite others?
  Reply With Quote
07-23-08, 03:21 PM   #17
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
This, yes (it's called "polluting the global namespace") and also because globals are generally slower than locals.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-23-08, 03:54 PM   #18
VagrantEsha
Token Werewolf Fan
 
VagrantEsha's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 27
I can't imagine why my example wouldn't work, as it's basically just a supremely stripped down version of Spelling (you might want to take a look at that). I can't see anything I've missed, to be honest. I might've screwed up the variable numbering (one too many underscores?), or there might be a typo somewhere there, but that's all I can think of. I'll look into it the next time I'm in game (I'll make a temporary mod out of my example).

Since I'm off to bed though, I'll leave this one open to the crowd. Anyone, anyone, Beuller?

And yes indeed, Seerah. Cramming junk into the global namespace is generally a bad practice, even Programming in Lua tells us so. The only people who really do it anymore are Blizzard (sorry Blizz, but it's the truth!) or people who're new to mod coding. Everyone picks up on this eventually though and their mods are all the better for it.

It seems like even Blizzard is learning with some elements though, like finally eliminating args. Now iif only they'd go back to all of their Blizzard_ mods and rewrite those to not use so many global variables, functions, and tables. I think it's those setting a bad example that's giving people the wrong idea.

Edit: Almost forgot to mention...

Originally Posted by Slakah View Post
Yeh I get locals and globals I just personally try and use tables as sparingly as possible, I'm still fairly new to coding and thus I use terms in the wrong places :P.
Me too, I don't like crowding things up with tables, that's generally a bad practice too. That's why I like reusing tables as much as possible. Garbage collection is great, but if you have tables upon tables with tables in them, then the memory use of the mod is going to climb exponentially. Whenever RegisterEvent is involved though, there has to be a table somewhere to accomodate for the frame. Ace creates its own frame (and frames are basically tables with special values), XML based frames are the same, and CreateFrame() is also basically the same.

So, like I said, if the table has to be created... then one might aswell use it. If one doesn't need a table, then a whole slew of locals is better.

Last edited by VagrantEsha : 07-23-08 at 03:58 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » I suck at this (first proper mod help)

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off