Thread Tools Display Modes
11-13-13, 06:13 PM   #1
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Issue with UnitBuff

Right so, this is a tiny addon i've had for a while to auto answer ready checks depnding on the situation.

Everything works exept the flask part, flask is always nil and i don't understand what i did wrong.

Code:
local _, caelUI = ...

caelUI.readycheck = caelUI.createModule("ReadyCheck")

local GetSpellName = function(spellId)
	return GetSpellInfo(spellId)
end

local flasks = {
	-- Cataclysm
	GetSpellName(80719),		-- Flask of Steelskin
	GetSpellName(80720),		-- Flask of the Draconic Mind
	GetSpellName(80721),		-- Flask of the Winds
	GetSpellName(80723),		-- Flask of Titanic Strength
	GetSpellName(94162),		-- Flask of Flowing Water

	-- Pandaria
	GetSpellName(105694),	-- Flask of the Earth
	GetSpellName(105691),	-- Flask of the Warm Sun
	GetSpellName(105696),	-- Flask of Winter's Bite
	GetSpellName(105693),	-- Flask of Falling Leaves
	GetSpellInfo(105689),	-- Flask of Spring Blossoms
}

ReadyCheckListenerFrame:SetScript("OnShow", nil)

local isGuildGroup

caelUI.readycheck:SetScript("OnEvent", function(self, event)
	if event == "PLAYER_ENTERING_WORLD" then
		hooksecurefunc(GuildInstanceDifficulty, "Show", function()
			isGuildGroup = true
		end)

		hooksecurefunc(GuildInstanceDifficulty, "Hide", function()
			isGuildGroup = false
		end)
	elseif event == "READY_CHECK" then
		PlaySoundFile([[Sound\Interface\ReadyCheck.wav]], "Master")

		local food = UnitBuff("player", GetSpellName(104280))

		for k, v in pairs(flasks) do
			local flask =  UnitBuff("player", k)
		end

		if (not isGuildGroup and food) or (isGuildGroup and flask and food) then
			ReadyCheckFrame:Hide()
			ConfirmReadyCheck(1)
		end
	end
end)

for _, event in next, {
	"PLAYER_ENTERING_WORLD",
	"READY_CHECK",
} do
	caelUI.readycheck:RegisterEvent(event)
end
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
11-13-13, 06:21 PM   #2
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
GetSpellInfo returns multiple stuff, i guess you need the name of the spell.

name = GetSpellInfo(spellId or spellName or spellLink)

http://www.wowwiki.com/API_GetSpellInfo

Also i'm not sure GetSpellName is a valid API atm, and it's only for spellbook items so its useless for you. I think you need to use GetSpellInfo for food too.

Last edited by Resike : 11-13-13 at 06:27 PM.
  Reply With Quote
11-13-13, 06:32 PM   #3
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Resike View Post
GetSpellInfo returns multiple stuff, i guess you need the name of the spell.

name = GetSpellInfo(spellId or spellName or spellLink)

http://www.wowwiki.com/API_GetSpellInfo

Also i'm not sure GetSpellName is a valid API atm, and it's only for spellbook items so its useless for you. I think you need to use GetSpellInfo for food too.
Hmm ? GetSpellName is a function i create, and GetSpellInfo without parameters returns the name.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
11-13-13, 07:16 PM   #4
Nimhfree
A Frostmaul Preserver
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 267
Instead of worrying about the spell names, since you already have the spell IDs for the ones in which you have interest, why don't you just use UnitAura in a loop like:

flasks = {} -- fill this with each one
local i = 1
local foundFLask = nil
while (true) do
local name,_,_,_,_,_,_,_,_,_,spellId = UnitAura("player", i)
if name then
spellId = tonumber(spellId)
if tContains(flasks, spellId) then foundFlask = spellId end -- or use name if you want
i = i + 1
else
break
end
end
  Reply With Quote
11-13-13, 11:28 PM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
You have a scoping problem.

Code:
for k, v in pairs(flasks) do
	local flask =  UnitBuff("player", k)
	-- "flask" is local to this scope.
end

-- "flask" does not exist in this scope.
if (not isGuildGroup and food) or (isGuildGroup and flask and food) then
	ReadyCheckFrame:Hide()
	ConfirmReadyCheck(1)
end
Also, you may want to change your GetSpellName function to return an empty string, or UNKNOWN, or some other "dummy" value for spell IDs that don't return a real name. Otherwise, if Blizzard changes a spell ID, you will end up with holes in your otherwise sequentially-indexed table.

Also also, since you are using an indexed table, you should use for i = 1, #flasks do local k = flasks[ i ] instead of for k, v in pairs(flasks) to avoid the slow call to pairs.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 11-13-13 at 11:32 PM.
  Reply With Quote
11-13-13, 11:30 PM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Nimhfree View Post
if tContains(flasks, spellId) then ...
Never, ever, ever, ever, never use tContains. It's a complete waste of a function call. If you're going to need to check "is this value in this table?" you should just set up your table correctly in the first place, so you can do a simple table lookup instead:

Code:
if flasks[spellId] then ...
Also, in this case the number of important buffs (flask buffs) is smaller than the number of buffs that will likely be on a player at any given time, and it's simply more efficient to iterate over the smaller list, so what Caellian is doing is fine.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 11-13-13 at 11:34 PM.
  Reply With Quote
11-14-13, 02:29 AM   #7
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Not sure i understand what you meant with the function GetSpellName but here's what i did, if that's correct.

Code:
local _, caelUI = ...

caelUI.readycheck = caelUI.createModule("ReadyCheck")

local GetSpellName = function(id)
	return GetSpellInfo(id)
end

local flasks = {
	-- Cataclysm
	GetSpellName(80719),		-- Flask of Steelskin
	GetSpellName(80720),		-- Flask of the Draconic Mind
	GetSpellName(80721),		-- Flask of the Winds
	GetSpellName(80723),		-- Flask of Titanic Strength
	GetSpellName(94162),		-- Flask of Flowing Water

	-- Pandaria
	GetSpellName(105694),	-- Flask of the Earth
	GetSpellName(105691),	-- Flask of the Warm Sun
	GetSpellName(105696),	-- Flask of Winter's Bite
	GetSpellName(105693),	-- Flask of Falling Leaves
	GetSpellName(105689),	-- Flask of Spring Blossoms

	GetSpellName(127230),	-- For testing purpose: Vision of Insanity
}

ReadyCheckListenerFrame:SetScript("OnShow", nil)

local isGuildGroup

caelUI.readycheck:SetScript("OnEvent", function(self, event)
	if event == "PLAYER_ENTERING_WORLD" then
		hooksecurefunc(GuildInstanceDifficulty, "Show", function()
			isGuildGroup = true
		end)

		hooksecurefunc(GuildInstanceDifficulty, "Hide", function()
			isGuildGroup = false
		end)
	elseif event == "READY_CHECK" then
		PlaySoundFile([[Sound\Interface\ReadyCheck.wav]], "Master")

		local food = UnitBuff("player", GetSpellName(104280))

		local flask

		for i = 1, #flasks do
			flask = UnitBuff("player", flasks[i])
		end

		if (not isGuildGroup and food) or (isGuildGroup and flask and food) then
			ReadyCheckFrame:Hide()
			ConfirmReadyCheck(1)
		end
	end
end)

for _, event in next, {
	"PLAYER_ENTERING_WORLD",
	"READY_CHECK",
} do
	caelUI.readycheck:RegisterEvent(event)
end
But now i get:

Code:
Error occured in: Global
Message:
..\AddOns\caelUI\modules\misc\readyCheck.lua line 52:
   Usage: UnitBuff("unit", [index] or ["name", "rank"][, "filter"])
Debug:
   [C]: ?
   [C]: UnitBuff()
   caelUI\modules\misc\readyCheck.lua:52:
      caelUI\modules\misc\readyCheck.lua:35
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
11-14-13, 02:57 AM   #8
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Lua Code:
  1. local _, caelUI = ...
  2.  
  3. caelUI.readycheck = caelUI.createModule("ReadyCheck")
  4.  
  5. local foods = {
  6.   [104280] = { name = nil, rank = nil, }, -- food
  7. }
  8.  
  9. local flasks = {
  10.   [80719] = { name = nil, rank = nil, }, -- Flask of Steelskin
  11.   [80720] = { name = nil, rank = nil, }, -- Flask of the Draconic Mind
  12.   [80721] = { name = nil, rank = nil, }, -- Flask of the Winds
  13.   [80723] = { name = nil, rank = nil, }, -- Flask of Titanic Strength
  14.   [94162] = { name = nil, rank = nil, }, -- Flask of Flowing Water
  15.  
  16.   -- Pandaria
  17.   [105694] = { name = nil, rank = nil, }, -- Flask of the Earth
  18.   [105691] = { name = nil, rank = nil, }, -- Flask of the Warm Sun
  19.   [105696] = { name = nil, rank = nil, }, -- Flask of Winter's Bite
  20.   [105693] = { name = nil, rank = nil, }, -- Flask of Falling Leaves
  21.   [105689] = { name = nil, rank = nil, }, -- Flask of Spring Blossoms
  22.  
  23.   [127230] = { name = nil, rank = nil, }, -- For testing purpose: Vision of Insanity
  24. }
  25.  
  26. --get food data
  27. for key, data in ipairs(foods) do
  28.   local name, rank, icon = GetSpellInfo(key)
  29.   if name then
  30.     data.name = name
  31.     data.rank = rank
  32.   end
  33. end
  34.  
  35. --get flask data
  36. for key, data in ipairs(flasks) do
  37.   local name, rank, icon = GetSpellInfo(key)
  38.   if name then
  39.     data.name = name
  40.     data.rank = rank
  41.   end
  42. end
  43.  
  44. --guild check
  45. local isGuildGroup = false
  46. local GuildInstanceDifficulty = GuildInstanceDifficulty
  47. hooksecurefunc(GuildInstanceDifficulty, "Show", function() isGuildGroup = true end)
  48. hooksecurefunc(GuildInstanceDifficulty, "Hide", function() isGuildGroup = false end)
  49.  
  50. --readycheck listen
  51. ReadyCheckListenerFrame:SetScript("OnShow", nil)
  52.  
  53. local function OnEvent(...)
  54.   PlaySoundFile([[Sound\Interface\ReadyCheck.wav]], "Master")
  55.   local food, flask
  56.   --check food
  57.   for key, data in ipairs(foods) do
  58.     if data.name then
  59.       if UnitAura("player", data.name, data.rank, "HELPFUL") then
  60.         food = true
  61.         break
  62.       end
  63.     end
  64.   end
  65.   --check flask  
  66.   for key, data in ipairs(flasks) do
  67.     if data.name then
  68.       if UnitAura("player", data.name, data.rank, "HELPFUL") then
  69.         flask = true
  70.         break
  71.       end
  72.     end
  73.   end
  74.   --dodat
  75.   if (not isGuildGroup and food) or (isGuildGroup and flask and food) then
  76.     ConfirmReadyCheck(1)
  77.     ReadyCheckFrame:Hide()
  78.   end
  79. end
  80.  
  81. caelUI.readycheck:RegisterEvent("READY_CHECK")
  82. caelUI.readycheck:SetScript("OnEvent", OnEvent)
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 11-14-13 at 03:05 AM.
  Reply With Quote
11-14-13, 03:11 AM   #9
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Ok Zork, but isn't that a bit overkill, my food part was fine hehe

Any idea what's wrong in my version though ?
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
11-14-13, 03:13 AM   #10
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
No I don't think that it is overkill. If you need to add other food buffs in feature you can easily add them. Maybe you called UnitBuff with a nil string or if you have a name you still need the rank as described in the usage.
Usage: UnitBuff("unit", [index] or ["name", "rank"][, "filter"])
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 11-14-13 at 03:15 AM.
  Reply With Quote
11-14-13, 03:20 AM   #11
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Well yeah, that's exactly what i've been trying to fix

Code:
		for i = 1, #flasks do
			flask = UnitBuff("player", flasks[i])
			print(flask)
		end

prints out "nil"
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
11-14-13, 03:25 AM   #12
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
What does
Lua Code:
  1. for i = 1, #flasks do
  2.             print(i)
  3.             print(flasks[i])
  4.         end
tell you?
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
11-14-13, 03:28 AM   #13
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by zork View Post
What does
Lua Code:
  1. for i = 1, #flasks do
  2.             print(i)
  3.             print(flasks[i])
  4.         end
tell you?
Code:
1
Visions of Insanity
2
 
3
INTERFACE\ICONS\spell_shadow_mindflay
4
0
5
false

...
That's with only the vision of insanity in the table
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
11-14-13, 03:48 AM   #14
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
That is hilarious.
Those are the return values of: http://wowprogramming.com/docs/api/GetSpellInfo
Basically...name, rank, icon, etc...

So your GetSpellName function does what you told it to do. It returns all values of GetSpellInfo and adds them to the table. >_<

Change it to:
Lua Code:
  1. local GetSpellName = function(id)
  2.   local name = GetSpellInfo(id)
  3.   return name or "NOT_FOUND"
  4. end
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 11-14-13 at 03:50 AM.
  Reply With Quote
11-14-13, 04:01 AM   #15
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Seems to be working now, i need to test some more, because i'm in a raid right now.

But anyway, what's going on ?

While it should only return the name it returns all the values, is that it ?
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 11-14-13 at 04:09 AM.
  Reply With Quote
11-14-13, 05:51 AM   #16
Oppugno
A Fallenroot Satyr
Join Date: Sep 2012
Posts: 22
No one has responded for awhile so I'll swoop in and steal the glory.

Lua.org - Multiple Results
Lua always adjusts the number of results from a function to the circumstances of the call. When we call a function as a statement, Lua discards all of its results. When we use a call as an expression, Lua keeps only the first result. We get all results only when the call is the last (or the only) expression in a list of expressions. These lists appear in four constructions in Lua: multiple assignment, arguments to function calls, table constructors, and return statements.
The relevant part in this particular case is that return statements can return multiple values. If you've done something like:
Code:
local name, realm = UnitName('target') -- Two values returned from a single function call.
then you've used this functionality before.
  Reply With Quote
11-14-13, 06:36 AM   #17
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Caellian View Post
Hmm ? GetSpellName is a function i create, and GetSpellInfo without parameters returns the name.
My bad i tought it's:

http://wowprogramming.com/docs/api/GetSpellName
  Reply With Quote
11-14-13, 06:38 AM   #18
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Oppugno View Post
No one has responded for awhile so I'll swoop in and steal the glory.

Lua.org - Multiple Results

The relevant part in this particular case is that return statements can return multiple values. If you've done something like:
Code:
local name, realm = UnitName('target') -- Two values returned from a single function call.
then you've used this functionality before.
Well thats what i was trying to tell in my first comment too. :P
  Reply With Quote
11-14-13, 07:46 AM   #19
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
You can grab the first return by enclosing your function call in parentheses.

(GetSpellInfo(spellID)) will discard everything but the first return.
  Reply With Quote
03-29-15, 11:49 PM   #20
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Gravedigger

Yey for grave digging an old issue because it came back...

Code:
local GetSpellName = function(id)
	local spellName = GetSpellInfo(id)

	return spellName or "NOT_FOUND"
end

local flasks = {
	-- Cataclysm
	GetSpellName(80719),		-- Flask of Steelskin
	GetSpellName(80720),		-- Flask of the Draconic Mind
	GetSpellName(80721),		-- Flask of the Winds
	GetSpellName(80723),		-- Flask of Titanic Strength
	GetSpellName(94162),		-- Flask of Flowing Water

	-- Pandaria
	GetSpellName(105694),	-- Flask of the Earth
	GetSpellName(105691),	-- Flask of the Warm Sun
	GetSpellName(105696),	-- Flask of Winter's Bite
	GetSpellName(105693),	-- Flask of Falling Leaves
	GetSpellName(105689),	-- Flask of Spring Blossoms

	-- Draenor
	GetSpellName(156070),	-- Draenic Intellect Flask
	GetSpellName(156071),	-- Draenic Strength Flask
	GetSpellName(156073),	-- Draenic Agility Flask
	GetSpellName(156077),	-- Draenic Stamina Flask

	GetSpellName(156064),	-- Greater Draenic Agility Flask
	GetSpellName(156079),	-- Greater Draenic Intellect Flask
	GetSpellName(156080),	-- Greater Draenic Strength Flask
	GetSpellName(156084),	-- Greater Draenic Stamina Flask

	GetSpellName(176151),	-- For testing purpose: Whispers of Insanity
}

ReadyCheckListenerFrame:SetScript("OnShow", nil)

local isGuildGroup = false

caelUI.readycheck:SetScript("OnEvent", function(self, event)
	if event == "PLAYER_ENTERING_WORLD" then
		hooksecurefunc(GuildInstanceDifficulty, "Show", function()
			isGuildGroup = true
		end)

		hooksecurefunc(GuildInstanceDifficulty, "Hide", function()
			isGuildGroup = false
		end)
	elseif event == "READY_CHECK" then
		PlaySoundFile([[Sound\Interface\ReadyCheck.wav]], "Master")

		local food = UnitBuff("player", GetSpellName(104280))

		local flask

		for i = 1, #flasks do
			flask = UnitBuff("player", flasks[i])
		end

		print(flask)

		if (not isGuildGroup and food) or (isGuildGroup and flask and food) then
			ReadyCheckFrame:Hide()
			ConfirmReadyCheck(1)
		end
	end
end)
So this time, here's what it does:

1. If i use the whispers of insanity, it works perfectly.
2. if i only leave one flask in the table, it works perfectly.
3. if i leave it like it is, flask returns nil.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Issue with UnitBuff


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