Thread Tools Display Modes
02-09-10, 09:22 PM   #1
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Grr, I hate it when I miss stuff...

Getting an error that I don't know how to resolve:

lua Code:
  1. -- SET CITIES --
  2. function MageTaxi:SetFaction()
  3.     if UnitFactionGroup("player") == "Alliance" then
  4.         cityList = {
  5.             [1] = "Stormwind",
  6.             [2] = "Ironforge",
  7.             [3] = "Darnassus",
  8.             [4] = "Exodar",
  9.             [5] = "Theramore",
  10.             [6] = "Shattrath",
  11.             [7] = "Dalaran",
  12.         }
  13.     else
  14.         cityList = {
  15.             [1] = "Undercity",
  16.             [2] = "Orgrimmar",
  17.             [3] = "Thunder Bluff",
  18.             [4] = "Silvermoon",
  19.             [5] = "Stonard",
  20.             [6] = "Shattrath",
  21.             [7] = "Dalaran"
  22.         }
  23.     end;
  24.         dest = cityList[1]
  25. end
  26.  
  27. -- SET DESTINATION --
  28. local function setLoc(i)
  29.     for num= 1,#cityList do
  30.         _G["MageTaxi_City".. num]:SetChecked(false)  -- line 91
  31.     end
  32.     dest = cityList[i]
  33.     _G["MageTaxi_City".. i]:SetChecked(true)
  34. end
  35.  
  36. function MageTaxi_createGUI()
  37.     -- other code
  38.     for i = 1,#cityList do
  39.         cb = CreateFrame("CHECKBUTTON", "MageTaxi_City"..i, f, "UIRadioButtonTemplate")
  40.             if i == 1 then
  41.                 cb:SetPoint("TOPLEFT", f, "TOPLEFT", 40, -45)
  42.             else
  43.                 cb:SetPoint("TOP", "MageTaxi_City".. (i-1), "BOTTOM", 0, -10)
  44.             end
  45.             cb:SetScript("OnClick", setLoc(i)) -- line 149
  46.         end
  47. end

Code:
Message: Interface\AddOns\MageTaxi\magetaxi.lua:91: attempt to index field '?' (a nil value)
Time: 02/09/10 21:08:49
Count: 1
Stack: Interface\AddOns\MageTaxi\magetaxi.lua:91: in function <Interface\AddOns\MageTaxi\magetaxi.lua:89>
Interface\AddOns\MageTaxi\magetaxi.lua:149: in function `MageTaxi_createGUI'
[string "MageTaxi_createGUI()"]:1: in main chunk
[C]: in function `RunScript'

Locals: i = 1
(for index) = 2
(for limit) = 7
(for step) = 1
num = 2
(*temporary) = nil
(*temporary) = nil
(*temporary) = "2"
(*temporary) = "attempt to index field '?' (a nil value)"
As far as the checkbuttons, it's only creating one and stopping (leading to the error, figured that part out). I'm looking for WHY it's not building all the buttons.

Last edited by Sythalin : 02-09-10 at 09:24 PM.
  Reply With Quote
02-09-10, 09:38 PM   #2
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,917
If you haven't already I would convert the _G["MageTaxi_City".. num] part out to a variable and see what that says each time and if the object of that name exists both there and in CreateGUI.

Apart from that I cannot initially see anything wrong there. Especially with the error reporting values between 1 and 7 with it being stuck at 2. So the question is to find out why MageTax_City2 isn't being created, or thinks it hasn't been created.

Ah, I think I know the problem, at least based on the code there. I had the same problem in my own code recently. When you call a function at creation time that is also used later on after all items are created the chances are it is trying to access something that doesn't exist yet.

Try changing the setloc function to something like this. This way if _G["MageTaxi_City2"] doesn't exist when working on _G["MageTaxi_City1"] it won't kick up a fuss. Of course this assumes you haven't pre-created the objects themselves. But then again #citylist is already of size 7 but does that mean _G["MageTaxi_City2"] exists or that there are blank entries in citylist ?

Code:
local function setLoc(i)
  for num= 1,#cityList do
    if _G["MageTaxi_City".. num] then _G["MageTaxi_City".. num]:SetChecked(false) end
  end
  dest = cityList[i]
  _G["MageTaxi_City".. i]:SetChecked(true)
end
__________________
  Reply With Quote
02-09-10, 09:58 PM   #3
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
Edit: Oh I should've noticed that too,

Last edited by Akryn : 02-10-10 at 07:17 AM.
  Reply With Quote
02-10-10, 05:03 AM   #4
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Originally Posted by ChaosInc View Post
As far as the checkbuttons, it's only creating one and stopping (leading to the error, figured that part out). I'm looking for WHY it's not building all the buttons.
Code:
cb:SetScript("OnClick", setLoc(i))
Was that line meant to be:

Code:
cb:SetScript("OnClick", function() setLoc(i) end)
As it is now you are trying to set the "OnClick" script for each button to the return value of setLoc, but in calling setLoc you are attempting to reference frames that haven't been created yet.

Edit:

Instead of creating a separate function for each frame's "OnClick" handler why not just do:

Code:
local function setLoc(self)
	for i = 1, #cityList do
		_G["MageTaxi_City" .. i]:SetChecked(false)
	end
	dest = cityList[self.id]
	self:SetChecked(true)
end
 
function MageTaxi_createGUI()
	-- other code
	for i = 1, #cityList do
		cb = CreateFrame("CHECKBUTTON", "MageTaxi_City" .. i, f, "UIRadioButtonTemplate")
		if i == 1 then
			cb:SetPoint("TOPLEFT", f, "TOPLEFT", 40, -45)
		else
			cb:SetPoint("TOP", "MageTaxi_City" .. (i - 1), "BOTTOM", 0, -10)
		end
		cb.id = i
		cb:SetScript("OnClick", setLoc) -- line 149
	end
end

Last edited by Vrul : 02-10-10 at 05:13 AM.
  Reply With Quote
02-10-10, 05:46 AM   #5
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
The error is in the SetScript on line 149. SetScript accepts 2 parameters, the script and the function that should be called.

Code:
cb:SetScript("OnClick", setLoc(i))
This will generate an error This will happen if the onclick handler is called:

Code:
setLoc(i)(...)
Errors. This IS correct:

Code:
cb:SetScript("OnClick", function(i) setLoc(i) end)
Which will be called like this(function:2FJ39 is the link to the local function created by function(i) setLoc(i) end):

Code:
function:2FJ39(...)
And the most neat way is this:

Code:
cb:SetScript("OnClick", setLoc)
Which will get called like this:

Code:
setLoc(...)
Which is what we want.

Final thing, you are concatenating the i variable in your setLoc function, don't you mean this?

Code:
i = i:GetName()
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.

Last edited by nightcracker : 02-10-10 at 05:48 AM.
  Reply With Quote
02-10-10, 10:59 AM   #6
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Originally Posted by Vrul View Post
[code]
Edit:

Instead of creating a separate function for each frame's "OnClick" handler why not just do:

Code:
local function setLoc(self)
	for i = 1, #cityList do
		_G["MageTaxi_City" .. i]:SetChecked(false)
	end
	dest = cityList[self.id]
	self:SetChecked(true)
end
 
function MageTaxi_createGUI()
	-- other code
	for i = 1, #cityList do
		cb = CreateFrame("CHECKBUTTON", "MageTaxi_City" .. i, f, "UIRadioButtonTemplate")
		if i == 1 then
			cb:SetPoint("TOPLEFT", f, "TOPLEFT", 40, -45)
		else
			cb:SetPoint("TOP", "MageTaxi_City" .. (i - 1), "BOTTOM", 0, -10)
		end
		cb.id = i
		cb:SetScript("OnClick", setLoc) -- line 149
	end
end
Isn't just passing i doing the same thing, or am I not following this logic correctly?

Final thing, you are concatenating the i variable in your setLoc function, don't you mean this?
Code:
i = i:GetName()
Why would I want the name of a number?

And the most neat way is this:

Code:
cb:SetScript("OnClick", setLoc)
Which will get called like this:

Code:
setLoc(...)
Which is what we want.
... is still somewhat confusing to me. I understand that it's all arguments that are passed, but cb:SetScript("OnClick", setLoc) isn't passing anything, so how would I get the i value?

Still learning as I go along.
  Reply With Quote
02-10-10, 11:36 AM   #7
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by ChaosInc View Post
Isn't just passing i doing the same thing, or am I not following this logic correctly?


Why would I want the name of a number?



... is still somewhat confusing to me. I understand that it's all arguments that are passed, but cb:SetScript("OnClick", setLoc) isn't passing anything, so how would I get the i value?

Still learning as I go along.
NOW I see what you want to do.... Here it comes:

Code:
function MageTaxi:SetFaction()
    if UnitFactionGroup("player") == "Alliance" then
        cityList = {
            [1] = "Stormwind",
            [2] = "Ironforge",
            [3] = "Darnassus",
            [4] = "Exodar",
            [5] = "Theramore",
            [6] = "Shattrath",
            [7] = "Dalaran",
        }
    else
        cityList = {
            [1] = "Undercity",
            [2] = "Orgrimmar",
            [3] = "Thunder Bluff",
            [4] = "Silvermoon",
            [5] = "Stonard",
            [6] = "Shattrath",
            [7] = "Dalaran"
        }
    end;
        dest = cityList[1]
end

local function setLoc(i)
    for num= 1,#cityList do
        _G["MageTaxi_City".. num]:SetChecked(false)  -- line 91
    end
    dest = cityList[i]
    _G["MageTaxi_City".. i]:SetChecked(true)
end
 
function MageTaxi_createGUI()
    for i = 1,#cityList do
        cb = CreateFrame("CHECKBUTTON", "MageTaxi_City"..i, f, "UIRadioButtonTemplate")
		if i == 1 then
			cb:SetPoint("TOPLEFT", f, "TOPLEFT", 40, -45)
		else
			cb:SetPoint("TOP", "MageTaxi_City".. (i-1), "BOTTOM", 0, -10)
		end
		cb:SetScript("OnClick", function() setLoc(i) end) -- line 149
    end
end
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-10-10, 12:11 PM   #8
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Thanks, I realized the fix last night already, but good to see it verified (and it works btw).

One thing though that I've run into that maybe someone can help me with. I have ZERO understanding of string manipulation and it has me painted into a corner atm.

Code:
cityList = {
	[3] = "ThunderBluff",
}

b = CreateFrame("BUTTON", "MageTaxi_Port"..i, f, "SecureActionButtonTemplate")
	b:SetPoint("RIGHT", "MageTaxi_City"..i, "LEFT", 0, 0)
	b:SetHeight(18)
	b:SetWidth(18)
	b.texture = b:CreateTexture("MageTaxi_Spell"..i)
	b.texture:SetAllPoints(b)
	b.texture:SetTexture("Interface\\Icons\\Spell_Arcane_Portal".. cityList[i])
	b:SetAttribute("type", "spell")
	b:SetAttribute("spell", "Portal: ".. cityList[i])
fs = b:CreateFontString("MageTaxi_Text"..i)
	fs:SetFontObject("GameFontGreenSmall")
	fs:SetJustifyH("LEFT")
	s:SetText(cityList[i])
	fs:SetPoint("LEFT", "MageTaxi_City"..i, "RIGHT", 0,0)
Only things that really matter are the orange spots. The issue is with Thunder Bluff. The icon name puts it as "ThunderBluff" (no space), but I still want it to appear as "Thunder Bluff" in the font string. Is there a way to do this without having to assign a temp var for difference?
  Reply With Quote
02-10-10, 12:19 PM   #9
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by ChaosInc View Post
Thanks, I realized the fix last night already, but good to see it verified (and it works btw).

One thing though that I've run into that maybe someone can help me with. I have ZERO understanding of string manipulation and it has me painted into a corner atm.

Code:
cityList = {
	[3] = "ThunderBluff",
}

b = CreateFrame("BUTTON", "MageTaxi_Port"..i, f, "SecureActionButtonTemplate")
	b:SetPoint("RIGHT", "MageTaxi_City"..i, "LEFT", 0, 0)
	b:SetHeight(18)
	b:SetWidth(18)
	b.texture = b:CreateTexture("MageTaxi_Spell"..i)
	b.texture:SetAllPoints(b)
	b.texture:SetTexture("Interface\\Icons\\Spell_Arcane_Portal".. cityList[i])
	b:SetAttribute("type", "spell")
	b:SetAttribute("spell", "Portal: ".. cityList[i])
fs = b:CreateFontString("MageTaxi_Text"..i)
	fs:SetFontObject("GameFontGreenSmall")
	fs:SetJustifyH("LEFT")
	s:SetText(cityList[i])
	fs:SetPoint("LEFT", "MageTaxi_City"..i, "RIGHT", 0,0)
Only things that really matter are the orange spots. The issue is with Thunder Bluff. The icon name puts it as "ThunderBluff" (no space), but I still want it to appear as "Thunder Bluff" in the font string. Is there a way to do this without having to assign a temp var for difference?
lua Code:
  1. s:SetText(gsub(cityList[i], "([a-z]+)([A-Z][a-z]+)", "%1 %2"))

I really like that I've done my regex homework so I can solve problems like this
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.

Last edited by nightcracker : 02-10-10 at 12:22 PM.
  Reply With Quote
02-10-10, 04:31 PM   #10
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Originally Posted by nightcracker View Post
lua Code:
  1. s:SetText(gsub(cityList[i], "([a-z]+)([A-Z][a-z]+)", "%1 %2"))

I really like that I've done my regex homework so I can solve problems like this
Worked like a charm. Now mind explaining it to me? LOL
  Reply With Quote
02-10-10, 07:16 PM   #11
ArrchDK
A Fallenroot Satyr
 
ArrchDK's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 25
Originally Posted by ChaosInc View Post
Worked like a charm. Now mind explaining it to me? LOL
Info on gsub

The second argument ("([a-z]+)([A-Z][a-z]+)") looks for a lower case letter ([a-z]) followed by an uppercase letter ([A-Z]) followed by a lower case letter ([a-z]). So in the case of ThunderBluff, it would find "rBl" as the pattern. Something like LookingForGroup would find "gFo" and "rGr". It then substitutes it with the third argument ("%1 %2"). In this case, it is substituting the first letter (%1) and the second letter (%2), combined would be (%1%2) with (%1 %2); essentially adding a space inbetween them. So "rBl" becomes "r Bl" in the string, making "ThunderBluff" change to "Thunder Bluff"

I hope that's easier to understand than it is to explain =/
  Reply With Quote
02-10-10, 07:35 PM   #12
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
Originally Posted by ArrchDK View Post
Info on gsub

The second argument ("([a-z]+)([A-Z][a-z]+)") looks for a lower case letter ([a-z]) followed by an uppercase letter ([A-Z]) followed by a lower case letter ([a-z]). So in the case of ThunderBluff, it would find "rBl" as the pattern. Something like LookingForGroup would find "gFo" and "rGr". It then substitutes it with the third argument ("%1 %2"). In this case, it is substituting the first letter (%1) and the second letter (%2), combined would be (%1%2) with (%1 %2); essentially adding a space inbetween them. So "rBl" becomes "r Bl" in the string, making "ThunderBluff" change to "Thunder Bluff"

I hope that's easier to understand than it is to explain =/
That's a better explanation than I could have given.

To be completely accurate, it's searching for a string of lowercase letters of length >=1 both before and after the single capital letter; but it's true that you don't really need that. Removing the + signs would make it behave exactly as described.

As it is, "ThunderBluff" yields one match: "hunderBluff", which in turn matches the subpatterns as "(hunder)(Bluff)" and therefore %1 == "hunder" and %2 == "Bluff", resulting in gsub replacing all instances of "hunderBluff" with "hunder Bluff", with a final result of "Thunder Bluff" since there's only one instance of that.

In any case, I think: "(%l)(%u)" would work just as well; but it doesn't really matter much.

Last edited by Akryn : 02-10-10 at 07:49 PM.
  Reply With Quote
02-10-10, 09:56 PM   #13
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Originally Posted by ChaosInc View Post
Isn't just passing i doing the same thing, or am I not following this logic correctly?
Passing i requires the function setLoc and an additional separate function for each city button. Saving i into the frame allows you to just have the one function shared by all the buttons. It is just an efficiency thing, why create 8 functions to accomplish the same thing you can do with just 1.
  Reply With Quote
02-11-10, 12:22 AM   #14
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by Akryn View Post
To be completely accurate, it's searching for a string of lowercase letters of length >=1 both before and after the single capital letter; but it's true that you don't really need that. Removing the + signs would make it behave exactly as described.
It's efficienter with the +, because else it's constantly look-aheading while the greedyness of [a-z]+ is getting exactly to the point we want.
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-11-10, 12:51 AM   #15
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,917
Originally Posted by nightcracker View Post
It's efficienter with the +, because else it's constantly look-aheading while the greedyness of [a-z]+ is getting exactly to the point we want.
Checks dictionary, hmm efficienter isn't in there :P Sorry, couldn't resist
__________________
  Reply With Quote
02-11-10, 01:21 AM   #16
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
Bah. You missed "greedyness" in your dictionary check. :P
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
02-11-10, 01:22 AM   #17
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,917
Originally Posted by Torhal View Post
Bah. You missed "greedyness" in your dictionary check. :P
d'oh, didn't read that far rofl.
__________________
  Reply With Quote
02-11-10, 01:58 AM   #18
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
:P I'm sorry for my malformed english, only a 15 year old dutch kiddo who just learns english by browsing forums like this one. "efficienter" is the comparative of efficient(which IS a dutch word) in dutch. So I was confused. And greedyness is well..... greedyness! :P
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
02-11-10, 03:15 AM   #19
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Great, glad the thread has become a spelling bee.
  Reply With Quote
02-11-10, 05:47 PM   #20
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,917
Originally Posted by nightcracker View Post
:P I'm sorry for my malformed english, only a 15 year old dutch kiddo who just learns english by browsing forums like this one. "efficienter" is the comparative of efficient(which IS a dutch word) in dutch. So I was confused. And greedyness is well..... greedyness! :P
ah then this English gal forgives you English has been known to be the worst language to learn

And sorry Chaos, didn't mean to derail your thread somewhat

So, hows your coding going ? ( trying to steer back on topic - rofl ).
__________________
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Grr, I hate it when I miss stuff...

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