Thread Tools Display Modes
12-27-09, 07:58 PM   #1
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
local is local in a global?

I get reports for my addon that make me believe I have done
something wrong. I have used a global function so that I can call
it from moduls. In the code I have some local vars (mods,events,reqistered).
My question is when using them in the global function could this cause the
trouble ?

Everything works fine on my system but not on others. So I guess
the problem occurs together with other addons overwriting my stuff.

Code:
local addon = LibStub("LibzzAddOnInit"):Init(...)

local mods = {}
local events = {}
local registered = {}

function zzMiscHelper_Register(name,event,func,desc)
  mods[#mods + 1] = name
  events[name] = { [event] = func}
  if(not registered[event]) then
    registered[event] = true
    addon:RegisterEvent(event, "eventHandler")
  end
  addon:AddConfigEntry("toggle",name,desc,_,1)
  return addon
end

function addon:eventHandler(event,...)
  for k,v in pairs(mods) do
    if(type(events[v][event]) == 'function' and addon.db.profile[v]) then
      events[v][event](...)
    end
  end
end
The addon is http://www.wowinterface.com/download...iscHelper.html
  Reply With Quote
12-27-09, 09:17 PM   #2
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
The only question is if addon.db and addon.db.profile are actually defined as tables before your event code is running. Lua throws an error if you try to index a nil value.

EDIT:
I downloaded the addon code to take a look at it. With all the libs there, I'm still not completely sure what's going on. I don't really see addon.db.profile[modname] being set anywhere even though addon.db.profile is being defined as a valid table by LibzzAddOnInit calling on AceDB. I'd dig deeper, but my time is limited at the moment.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 12-27-09 at 10:19 PM.
  Reply With Quote
12-27-09, 09:24 PM   #3
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by SDPhantom View Post
The only question is if addon.db and addon.db.profile are actually defined as tables before your event code is running. Lua throws an error if you try to index a nil value.
Yes, this is done "externaly". In the first line my zzLib sets up the needed
stuff for the addon. The addon works fine here on my system. So its nothing
"technical". It probably more a mistake in my understanding.
  Reply With Quote
12-27-09, 10:33 PM   #4
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
From how the code looks... if it's running fine on your system, then all the events are firing fine and being captured, the only thing left would be the config and whether or not it's actually being set.

Have you tried clearing out the saved data and trying to debug it from that direction?
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
12-28-09, 07:08 AM   #5
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by SDPhantom View Post
From how the code looks... if it's running fine on your system, then all the events are firing fine and being captured, the only thing left would be the config and whether or not it's actually being set.

Have you tried clearing out the saved data and trying to debug it from that direction?
Reading and writing the saved vars works fine. One user reported that he
saw written in the settings as a menupoint where you can enable/disable
my modules the option "Fishingpole" which is why I think I have a
golbal/local problem in the maincode since in no place one of my addons uses this. But now that you mention it perhaps the problem is in my preferencesbuilding code.

Code:
zz_MiscHelperCharDB = {
	["profileKeys"] = {
		["Rilgana - Tirion"] = "Rilgana - Tirion",
	},
	["profiles"] = {
		["Rilgana - Tirion"] = {
			["showMMIcon"] = false,
			["bopconfirm"] = true,
			["startupMessage"] = false,
			["autogroup"] = true,
			["lootconfirm"] = true,
			["ldbicon"] = {
				["minimapPos"] = 335.7730919739564,
				["hide"] = true,
			},
			["deconfirm"] = true,
			["greedorbs"] = true,
			["noduel"] = true,
			["autoport"] = true,
			["autogreed"] = true,
		},
	},
}
  Reply With Quote
12-28-09, 03:41 PM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
Was it just that rare/epic loot module that was reported as not working or all of them?
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
12-28-09, 05:47 PM   #7
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Epic was reported to show the disenchant/bop requester still.
Epic loot is not autogreeded atm but the requesters after selecting
greed/need/de should be answered.

And where the wrong named configentry ("Fishingpole") came from I have no clue.
  Reply With Quote
12-28-09, 06:25 PM   #8
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
ok.. I ran some tests on my own, the BoP code works on blues so far, although I had to click twice on them before they looted, confirmation box stayed hidden though.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
12-28-09, 06:39 PM   #9
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by SDPhantom View Post
ok.. I ran some tests on my own, the BoP code works on blues so far, although I had to click twice on them before they looted, confirmation box stayed hidden though.
Thank you 1000x for looking at it I'm going through it again and again
and I start to believe the trigger for this is in another addon that I dont have.
With 28 downloads it was marked 7x as a fav ... so I guess it works ok
for systems with only a few addons like mine.
  Reply With Quote
12-28-09, 07:06 PM   #10
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
I don't have much on mine either, just a few outside of what I wrote myself.
I did have my own Anti-Duel code, only takes up 6 lines.

lua Code:
  1. UIParent:HookScript("OnEvent",function(self,event,...)
  2.     if event=="DUEL_REQUESTED" then
  3.         CancelDuel();
  4.         StaticPopup_Hide("DUEL_REQUESTED");
  5.     end
  6. end);

Since UIParent processes most of the StaticPopup requests including this one, I just hooked its event script instead of wasting memory creating a frame object. Simple and lightweight. If you want to duel someone, you can still send out requests.



This addon of yours does give me the idea of an addon that simply auto-answers a list of StaticPopup messages strictly by hooking the function called to show them. Need to be careful though since some popups do run protected code. I know confirming the replacement of an enchant is one of them.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
12-28-09, 07:17 PM   #11
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Hehe, I want the code to be as generic as it can be.
This way I can use the code for every event I want to react on.
I'm still in the beginning phase of understanding what can be done
in lua. Hooks have scared me away since they (can) change the way
something is done. So there is a bigger potential to break stuff.
And there is nothing worse than breaking stuff you dont understand
  Reply With Quote
12-28-09, 07:27 PM   #12
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
Ever since Blizzard added in the concept of Taint, they added in a few functions to safely hook other functions and frame events. Although not as powerful as the old way of hooking these, it still lets you run your code in response of some other code running. Think of hooking as an extra event or more control of when you want your code run. Just wait until you get into metatables.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
12-28-09, 07:53 PM   #13
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by SDPhantom View Post
Ever since Blizzard added in the concept of Taint
Brrr, dont mention taint I spent weeks to have my bags-addon not cause
taints over and over and still I think this is the most stupid protection
I've ever seen when you try to find where a taint started. I looked into metatables when I tried to understand what ace-db does ... my plan was to have the zzLib ace-free ... after trying to understand what is done there the plan changed
  Reply With Quote
12-28-09, 08:14 PM   #14
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
Here's what I came up with. It isn't tested, but theoretically, it should work. Just make a call to AutoAnswer_Register() and send it the ID used to show the StaticPopup along with either an index of which button to click or the text shown on the button. To unregister, just make another call to AutoAnswer_Register() with the ID and nil as the answer.
lua Code:
  1. local PopupAnswers={};
  2.  
  3. hooksecurefunc("StaticPopup_Show",function(id,a1,a2,dat)
  4.     local answer=PopupAnswers[id];
  5.     if answer then
  6.         local button=nil;
  7.  
  8.         local answerid=tonumber(answer)
  9.         if answerid then
  10.             button=_G[StaticPopup_FindVisible(id,dat):GetName().."Button"..answerid];
  11.         elseif type(answer)=="string" then
  12.             local info=StaticPopupDialogs[id];
  13.             if info then
  14.                 for i=1,3 do
  15.                     local ptr=info["button"..i]
  16.                     if ptr and ptr:lower()==answer:lower() then
  17.                         button=_G[StaticPopup_FindVisible(id,dat):GetName().."Button"..i];
  18.                         break;
  19.                     end
  20.                 end
  21.             end
  22.         end
  23.  
  24.         if button and button:IsShown() then button:Click(); end
  25.     end
  26. end);
  27.  
  28. function AutoAnswer_Register(id,answer)
  29.     if type(id)~="string" then error("bad argument #1 to 'AutoAnswer_Register' (string expected, got "..type(id)..")",2);return; end
  30.  
  31.     local found=nil;
  32.     for i,j in pairs(StaticPopupDialogs) do
  33.         if i:lower()==id:lower() then found=i;break; end
  34.     end
  35.  
  36.     if found then PopupAnswers[found]=answer; end
  37. end
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
12-28-09, 08:40 PM   #15
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Looks good

My fav line is

Code:
if button and button:IsShown() then button:Click(); end
Didnt know that you can simulate a button click. Thats more elegant
than hiding and redo what is done on accept/reject
  Reply With Quote
12-28-09, 08:57 PM   #16
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
It's certainly better than the old way.
Code:
local func=button:GetScript("OnClick");
if func then func(button,"LeftButton"); end
This just ran the code associated with the OnClick handler, which is what happens when you click a button.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
01-06-10, 06:19 AM   #17
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by SDPhantom View Post
It's certainly better than the old way.
It's the better code. But too fast If I hook it and autoaccept then
data and data2 are not yet set. This is required for the ConfirmLootRoll-Dialog.
So I have to stick to my old code because data and data2 (id and rolltype)
are passed by the event,too.
In UIParent.lua the requester is opened and if hooked the args are unset.
Code:
	if ( event == "CONFIRM_LOOT_ROLL" ) then
		local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
		local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
		if ( dialog ) then
			dialog.text:SetFormattedText(LOOT_NO_DROP, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
			StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
			dialog.data = arg1;
			dialog.data2 = arg2;
		end
		return;
	end
  Reply With Quote
01-07-10, 02:07 PM   #18
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
I've improved on the code a bit since my last post. I made my own AutoRoll addon and I'm in the middle of testing it. It doesn't use the code I posted, instead, I wrote a function that's hooked into UIParent's OnEvent handler.

Here's the modified section that handles the StaticPopup.
lua Code:
  1. UIParent:HookScript("OnEvent",function(self,event,...)
  2.     if event=="CONFIRM_LOOT_ROLL" or event=="CONFIRM_DISENCHANT_ROLL" then
  3.         if StaticPopup_FindVisible("CONFIRM_LOOT_ROLL",...) then
  4.             ConfirmLootRoll(...);
  5.             StaticPopup_Hide("CONFIRM_LOOT_ROLL",...);
  6.         end
  7.     elseif event=="LOOT_BIND_CONFIRM" then
  8.         if StaticPopup_FindVisible("LOOT_BIND",...) then
  9.             ConfirmLootSlot(...);
  10.             StaticPopup_Hide("LOOT_BIND",...);
  11.         end
  12.     end
  13. end);
The '...' holds all the args passed in by the event, this needs to be defined in the function parameters too.


Note that these pieces of code are exactly the same: ('...' can hold an unlimited number of returns, this is an example of a function that only wants 3)
Code:
function func(...)
	local arg1,arg2,arg3=...;
--	Do something here
end
Code:
function func(arg1,...)
	local arg2,arg3=...;
--	Do something here
end
Code:
function func(arg1,arg2,arg3)
--	Do something here
end
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
01-08-10, 05:08 AM   #19
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by SDPhantom View Post
lua Code:
  1. UIParent:HookScript("OnEvent",function(self,event,...)
  2.     if event=="DUEL_REQUESTED" then
  3.         CancelDuel();
  4.         StaticPopup_Hide("DUEL_REQUESTED");
  5.     end
  6. end);
I think this can be done even better:
lua Code:
  1. UIParent:HookScript("OnEvent",function(_,e) e=="DUEL_REQUESTED" and CancelDuel() and StaticPopup_Hide("DUEL_REQUESTED") end)
The most important part is to not take parameters you don't need in your function. Instead of function(self, event, ...) use function(_,event). If you do take the parameters in your function they get stored in the memory(which is not bad at all), but then comes the garbage collector wasting CPU on what really IS garbage.

OT: I like the object-oriënted approach, keep it going!
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
01-08-10, 06:00 AM   #20
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by nightcracker View Post
I think this can be done even better:
...
The most important part is to not take parameters you don't need in your function. Instead of function(self, event, ...) use function(_,event).
Yes, this is done in the last step in development. But here in the forum when you talk about it with others it is easier when self (and other names) are written so you know what _ is supposed to be
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » local is local in a global?

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