WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Grr, I hate it when I miss stuff... (https://www.wowinterface.com/forums/showthread.php?t=30566)

Sythalin 02-09-10 09:22 PM

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.

Xrystal 02-09-10 09:38 PM

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


Akryn 02-09-10 09:58 PM

Edit: Oh I should've noticed that too, :D

Vrul 02-10-10 05:03 AM

Quote:

Originally Posted by ChaosInc (Post 177972)
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


nightcracker 02-10-10 05:46 AM

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()

Sythalin 02-10-10 10:59 AM

Quote:

Originally Posted by Vrul (Post 177996)
[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?

Quote:

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? :confused:

Quote:

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

nightcracker 02-10-10 11:36 AM

Quote:

Originally Posted by ChaosInc (Post 178036)
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? :confused:



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

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


Sythalin 02-10-10 12:11 PM

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?

nightcracker 02-10-10 12:19 PM

Quote:

Originally Posted by ChaosInc (Post 178046)
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 :)

Sythalin 02-10-10 04:31 PM

Quote:

Originally Posted by nightcracker (Post 178048)
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 :D

ArrchDK 02-10-10 07:16 PM

Quote:

Originally Posted by ChaosInc (Post 178086)
Worked like a charm. Now mind explaining it to me? LOL :D

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 =/

Akryn 02-10-10 07:35 PM

Quote:

Originally Posted by ArrchDK (Post 178109)
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. :p

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.

Vrul 02-10-10 09:56 PM

Quote:

Originally Posted by ChaosInc (Post 178036)
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.

nightcracker 02-11-10 12:22 AM

Quote:

Originally Posted by Akryn (Post 178111)
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.

Xrystal 02-11-10 12:51 AM

Quote:

Originally Posted by nightcracker (Post 178132)
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 :D

Torhal 02-11-10 01:21 AM

Bah. You missed "greedyness" in your dictionary check. :P

Xrystal 02-11-10 01:22 AM

Quote:

Originally Posted by Torhal (Post 178136)
Bah. You missed "greedyness" in your dictionary check. :P

d'oh, didn't read that far rofl.

nightcracker 02-11-10 01:58 AM

: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

Sythalin 02-11-10 03:15 AM

Great, glad the thread has become a spelling bee. :rolleyes:

Xrystal 02-11-10 05:47 PM

Quote:

Originally Posted by nightcracker (Post 178139)
: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 :D English has been known to be the worst language to learn :D

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

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


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

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