WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Issue with UnitBuff (https://www.wowinterface.com/forums/showthread.php?t=48502)

Caellian 11-13-13 06:13 PM

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


Resike 11-13-13 06:21 PM

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.

Caellian 11-13-13 06:32 PM

Quote:

Originally Posted by Resike (Post 286931)
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.

Nimhfree 11-13-13 07:16 PM

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

Phanx 11-13-13 11:28 PM

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.

Phanx 11-13-13 11:30 PM

Quote:

Originally Posted by Nimhfree (Post 286936)
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.

Caellian 11-14-13 02:29 AM

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


zork 11-14-13 02:57 AM

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)

Caellian 11-14-13 03:11 AM

Ok Zork, but isn't that a bit overkill, my food part was fine hehe :)

Any idea what's wrong in my version though ?

zork 11-14-13 03:13 AM

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.
Quote:

Usage: UnitBuff("unit", [index] or ["name", "rank"][, "filter"])

Caellian 11-14-13 03:20 AM

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"

zork 11-14-13 03:25 AM

What does
Lua Code:
  1. for i = 1, #flasks do
  2.             print(i)
  3.             print(flasks[i])
  4.         end
tell you?

Caellian 11-14-13 03:28 AM

Quote:

Originally Posted by zork (Post 286954)
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

zork 11-14-13 03:48 AM

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

Caellian 11-14-13 04:01 AM

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 ?

Oppugno 11-14-13 05:51 AM

No one has responded for awhile so I'll swoop in and steal the glory.

Lua.org - Multiple Results
Quote:

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.

Resike 11-14-13 06:36 AM

Quote:

Originally Posted by Caellian (Post 286932)
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

Resike 11-14-13 06:38 AM

Quote:

Originally Posted by Oppugno (Post 286958)
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

Dridzt 11-14-13 07:46 AM

You can grab the first return by enclosing your function call in parentheses.

(GetSpellInfo(spellID)) will discard everything but the first return.

Caellian 03-29-15 11:49 PM

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.


All times are GMT -6. The time now is 02:55 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI