Quantcast Addon help - WoWInterface
Thread Tools Display Modes
09-19-15, 06:06 AM   #1
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
09-19-15, 08:38 AM   #2
Banknorris
A Chromatic Dragonspawn
 
Banknorris's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2014
Posts: 153
This function is protected, and may only be called in response to hardware event.
__________________
"In this world nothing can be said to be certain, except that fractional reserve banking is a Ponzi scheme and that you won't believe it." - Mandrill
  Reply With Quote
09-19-15, 09:05 AM   #3
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Banknorris View Post
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.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 09-19-15 at 09:20 AM.
  Reply With Quote
09-19-15, 11:07 AM   #4
Talyrius
An Onyxian Warder
 
Talyrius's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 361
Originally Posted by Caellian View Post
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.
  Reply With Quote
09-19-15, 11:12 AM   #5
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
09-19-15, 12:04 PM   #6
Nimhfree
A Frostmaul Preserver
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 264
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.
  Reply With Quote
09-19-15, 12:14 PM   #7
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
09-19-15, 12:28 PM   #8
Talyrius
An Onyxian Warder
 
Talyrius's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 361
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

Last edited by Talyrius : 09-19-15 at 01:30 PM.
  Reply With Quote
09-19-15, 12:29 PM   #9
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
You didn't see my last post i guess
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
09-19-15, 12:35 PM   #10
Talyrius
An Onyxian Warder
 
Talyrius's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 361
I'm confused. If there is a new quest completion after combat ends then you have your answer…
  Reply With Quote
09-19-15, 12:37 PM   #11
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 09-19-15 at 03:09 PM.
  Reply With Quote
09-19-15, 04:38 PM   #12
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Aren't you going to want to wait with disbanding until everyone else has looted?
__________________
Grab your sword and fight the Horde!
  Reply With Quote
09-19-15, 04:40 PM   #13
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Lombra View Post
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)
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
09-19-15, 05:24 PM   #14
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,059
Originally Posted by Caellian View Post
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.
  Reply With Quote
09-20-15, 12:33 AM   #15
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 09-20-15 at 03:47 AM.
  Reply With Quote
09-20-15, 09:21 AM   #16
Nimhfree
A Frostmaul Preserver
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 264
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.
  Reply With Quote
09-20-15, 01:45 PM   #17
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,059
Originally Posted by Caellian View Post
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
  Reply With Quote
09-21-15, 12:48 AM   #18
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Nimhfree View Post
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


Originally Posted by semlar View Post
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
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }

Last edited by Caellian : 09-21-15 at 01:06 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Addon 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