WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Addon help (https://www.wowinterface.com/forums/showthread.php?t=52753)

Caellian 09-19-15 06:06 AM

Addon help
 
So here's a tiny module i recently added in my UI. Basically what it does amongst other things is, whenever i target one of those new rares in Tanaan jungle, it lists a custom group and when the rare is dead, it disbands the raid.

It's working just fine exept that, every time it disbands the raid, it also throws an error and i don't understand why. I even added a 5 seconds delay thinking it was doing it too fast after PLAYER_REGEN_ENABLED but that didn't help.

Anyway, here's the code and the error below it:

Code:

caelUI.rares:SetScript("OnEvent", function(self, event, addon, arg)
        if event == "CHAT_MSG_MONSTER_YELL" and (arg == "Frogan" or arg == "Tyrant Velhari" or arg == "Shadow-Lord Iskar" or arg == "Siegemaster Mar\'tak") and not IsInRaid() then
                self:RegisterEvent("PLAYER_TARGET_CHANGED")
        end

        if event == "PLAYER_TARGET_CHANGED" then
                if UnitName("target") == "Terrorfist" or UnitName("target") == "Vengeance" or UnitName("target") == "Deathtalon" or UnitName("target") == "Doomroller" then

                        self:RegisterEvent("PLAYER_REGEN_ENABLED")
                        self:UnregisterEvent("PLAYER_TARGET_CHANGED")
--                        C_LFGList.CreateListing(Category ID, "groupName", itemLevel, "voiceChat", "comment", autoAccept)
                        C_LFGList.CreateListing(16, UnitName("target"), 685, " ", "Join quick !", true)

                        C_Timer.After(5, function()
                                if not IsInRaid() then
                                        print("Converting to raid")
                                        ConvertToRaid()
                                end
                        end)

                        C_Timer.After(120, function()
                                print("Delisting group")
                                C_LFGList.RemoveListing()
                        end)
                end
        end

        if event == "PLAYER_REGEN_ENABLED" then
                C_Timer.After(5, function()
                        if IsInRaid() then
                                SendChatMessage("Target is dead, disbanding raid.", "RAID")
                                for i = 1, GetNumGroupMembers() do
                                        local name, _, _, _, _, _, _, online = GetRaidRosterInfo(i)
                                        if online and name ~= caelUI.playerName then
                                                UninviteUnit(name)
                                        end
                                end
                        else
                                SendChatMessage("Target is dead, disbanding group.", "PARTY")
                                for i = MAX_PARTY_MEMBERS, 1, -1 do
                                        if GetPartyMember(i) then
                                                UninviteUnit(UnitName("party"..i))
                                        end
                                end
                        end
                        LeaveParty()
                        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
                end)
        end
end)


Code:

ID: 1
Error occured in: Unnamed
Message:
caelUI attempted to call a protected function (UninviteUnit()) which may require interaction.
Debug:
  [C]: UninviteUnit()
  ...erface\AddOns\caelUI\modules\announcements\rares.lua:77:
      ...erface\AddOns\caelUI\modules\announcements\rares.lua:71
locals:
nil


Banknorris 09-19-15 08:38 AM

This function is protected, and may only be called in response to hardware event.

Caellian 09-19-15 09:05 AM

Quote:

Originally Posted by Banknorris (Post 311068)
This function is protected, and may only be called in response to hardware event.

That i could gather from the error yeah, but it still works so i'm confused.

Also, while i'm at it, how could i improve the whole PLAYER_REGEN_ENABLED part, i'm playing mainly a hunter and if i feign death, i go out of combat so it triggers that part of the code when it shouldn't have.

Talyrius 09-19-15 11:07 AM

Quote:

Originally Posted by Caellian (Post 311069)
Also, while i'm at it, how could i improve the whole PLAYER_REGEN_ENABLED part, i'm playing mainly a hunter and if i feign death, i go out of combat so it triggers that part of the code when it shouldn't have.

Lua Code:
  1. local isFeignDeath = UnitAura("player", "Feign Death") ~= nil

Confirm that you're not feigning death or keep checking until you no longer are (C_Timer.NewTicker) before proceeding with your delayed function.

Caellian 09-19-15 11:12 AM

One more question, is it possible to check from within an addon if i have already looted the rare ? I was thinking to use that as a trigger to disband/leave group.

Nimhfree 09-19-15 12:04 PM

Looting a rare should be marked by Blizzard completing a specific quest for each rare. This type of quest is just a marker quest and does not show up in a quest list. However, when using Blizzard APIs to determine if a quest is complete it will work with these marker quests. Therefore, you would want for each rare to know the associated Blizzard marker quest and use the API with that value to see whether the person has looted that rare.

Caellian 09-19-15 12:14 PM

Yeah no, that's not what i meant, you're referring to IsQuestFlaggedCompleted, but that's not what i'm trying to know here.

I'm not trying to know if i have already looted "that" rare sometimes today. I'm trying to know if i looted the mob i was in combat with a few seconds ago so i can leave the group.

Talyrius 09-19-15 12:28 PM

Lua Code:
  1. local champions = {
  2.     [39287] = IsQuestFlaggedCompleted(39287), -- Deathtalon
  3.     [39288] = IsQuestFlaggedCompleted(39288), -- Terrorfist
  4.     [39289] = IsQuestFlaggedCompleted(39289), -- Doomroller
  5.     [39290] = IsQuestFlaggedCompleted(39290), -- Vengeance
  6. }
  7.  
  8. for id, completed in pairs(champions)
  9.     if IsQuestFlaggedCompleted(id) and not completed then
  10.         -- New quest completion
  11.         completed = true
  12.     end
  13. end

Caellian 09-19-15 12:29 PM

You didn't see my last post i guess :)

Talyrius 09-19-15 12:35 PM

I'm confused. If there is a new quest completion after combat ends then you have your answer…

Caellian 09-19-15 12:37 PM

I'm not looking for a quest completion, i'm trying to know if i looted something after killing it.

Let's just say something that would work with any mob, not just rares.

Edit: Besides, if i'm not mistaken, IsQuestFlaggedCompleted would tell me i killed it, not that i looted it :)

Lombra 09-19-15 04:38 PM

Aren't you going to want to wait with disbanding until everyone else has looted?

Caellian 09-19-15 04:40 PM

Quote:

Originally Posted by Lombra (Post 311085)
Aren't you going to want to wait with disbanding until everyone else has looted?

I gave up on the disbanding, instead i'm just leaving the group, but i still can't find a way to guarantee that i looted the mob before leaving.

Code:

local champions = {"Deathtalon", "Doomroller", "Terrorfist", "Vengeance"}

caelUI.rares:SetScript("OnEvent", function(self, event, addon, arg)

        if event == "CHAT_MSG_MONSTER_YELL" and (arg == "Frogan" or arg == "Shadow-Lord Iskar" or arg == "Siegemaster Mar\'tak" or arg == "Tyrant Velhari") and not IsInRaid() then
                self:RegisterEvent("PLAYER_TARGET_CHANGED")
        end

        if event == "PLAYER_TARGET_CHANGED" then
                for name = 1, #champions do
                        if UnitName("target") == champions[name] then

                                self:RegisterEvent("PLAYER_REGEN_ENABLED")

                                -- C_LFGList.CreateListing(Category ID, "groupName", itemLevel, "voiceChat", "comment", autoAccept)
                                C_LFGList.CreateListing(16, UnitName("target"), 0, "", "Join quick !", true)

                                C_Timer.After(5, function()
                                        ConvertToRaid()
                                end)

                                self:UnregisterEvent("PLAYER_TARGET_CHANGED")
                        end
                end
        end

        if event == "PLAYER_REGEN_ENABLED" then
                C_Timer.After(5, function()
                        C_LFGList.RemoveListing()
                        LeaveParty()
                end)

                self:UnregisterEvent("PLAYER_REGEN_ENABLED")
        end
end)


semlar 09-19-15 05:24 PM

Quote:

Originally Posted by Caellian (Post 311086)
i still can't find a way to guarantee that i looted the mob before leaving

You'll want to watch for the LOOT_OPENED event, iterate over the items from 1 to GetNumLootItems(), check GetLootSourceInfo(i) for the GUID of the source unit to figure out if you're looting from an npc ID on your list, then determine when you've actually looted what you're interested in via LOOT_SLOT_CLEARED or the actual "received item" bag events.

Caellian 09-20-15 12:33 AM

But i'm not interested in any specific loot, i just want to know if i looted it, not what was inside :)

So basically, you're saying something like this would suffice ? (untested, drycoded)

Code:

local champions = {"Deathtalon", 95053, "Doomroller", 95056, "Terrorfist", 95044, "Vengeance", 95054}

if event == "LOOT_OPENED" then
        for i = 1, GetNumLootItems() do
                local GUID = GetLootSourceInfo(i)

                for id = 1, #champions - 1, 2 do
                        if string.find(GUID, champions[id + 1]) then
                                C_Timer.After(5, function()
                                        C_LFGList.RemoveListing()
                                        LeaveParty()
                                end)
                        end
                end
        end

        self:UnregisterEvent("LOOT_OPENED")
end


Nimhfree 09-20-15 09:21 AM

In my addon Grail, I look for LOOT_CLOSED events in specific zones to handle looting chests (and it happens to work with looting monsters too). Grail then checks the quests that are completed to note which ones have just been done to know what is happening. This is how it can show you a list of all the treasures that you have not completed yet, for example. The same for rare monsters, etc. Therefore, you can definitely make use of this, but I am not sure I would do what you are doing here. Actually, if I were using Grail, I would do something like what is done in the Grail-When loadable addon, where I just register with Grail as an observer when a quest is complete, and if that quest is on one of the list of rares in which one has interest, do whatever you want (like leave the group). Grail would only tell you that you have completed the quests after you had done LOOT_CLOSED after killing a rare. Note that you might not actually loot the monster, or lack bag space, etc. so your check might want to be more extensive that what Grail does.

semlar 09-20-15 01:45 PM

Quote:

Originally Posted by Caellian (Post 311088)
So basically, you're saying something like this would suffice ? (untested, drycoded)

Since the GUID could potentially contain any of those numbers, rather than string.find it would be better to match the ID portion of the GUID specifically.

Something like this, or instead of using "tonumber" just convert the npc IDs in your table to strings.
Lua Code:
  1. if tonumber(string.match(GUID, '%-(%d+)%-[^-]+$')) == champions[id + 1] then

Caellian 09-21-15 12:48 AM

Quote:

Originally Posted by Nimhfree (Post 311093)
In my addon Grail, I look for LOOT_CLOSED

Don't ask me why, but it never worked with LOOT_CLOSED, that's why i use LOOT_OPENED


Quote:

Originally Posted by semlar (Post 311096)
Since the GUID could potentially contain any of those numbers, rather than string.find it would be better to match the ID portion of the GUID specifically.

Something like this, or instead of using "tonumber" just convert the npc IDs in your table to strings.
Lua Code:
  1. if tonumber(string.match(GUID, '%-(%d+)%-[^-]+$')) == champions[id + 1] then

Works perfectly. I usually stay far away from those patterns, in all those years, i never managed to understand them completely lol. Thanls :)


All times are GMT -6. The time now is 11:42 AM.

vBulletin © 2020, Jelsoft Enterprises Ltd
© 2004 - 2020 MMOUI