You don’t have to know much about LUA to start hacking around in it. If you have any experience in another programming language, its easy to get in and muck around with things. I have played with several languages. C++, Java, C#, VB6, VB.Net, JScript, VBScript, JavaScript, Batch files, Autohotkey, Html, XML, Flash4, ASP, ASPX, PHP, SQL and Assembly. I’m not listing this to impress anyone or to say I’m an expert at all of those. But I am good at working with code and making it do what I want it to do even when I am not familiar with it. Jumping into LUA was easy for me but I did have a few things slow me down. Here are some things that I discovered about LUA while working on it that was different to me from other languages. I figured most of this out by looking at other LUA code and with the help of google.
One of the first things I figured out was that .. is the concatination opperator. It’s common in many languages to use + or & to combine strings together.
print("Items Skipped: "..totalSkipped)
The print command I just used was a little trick I saw another mod use to generate output. I saw many many people use DEFAULT_CHAT_FRAME:AddMessage and some of my early LUA code does the same. I expect there are reasons to use one over the other. But using print statements to help in debugging is great.
Most languages have a NULL or NOTHING type value for objects that have no value or are not initialized. In LUA its nil. I found it hard to fight the habit to type null when I needed to type nil. Checking for nil was something else I had to figure out. If an object is nil and you try to use it, you generate an error. I wanted to use != or “is not nil” or neq like other languages. I found ~= to be the not equal syntax. Sometimes its the simplest things that slow you down.
if enchantLink ~= nil then print(enchantLink) end
Functions use a simple syntax like I expect but they can return more than one value. You can use the underscore to ignore values you don’t care about. Sometime you only one one or two of the return values. You can place them all in variables, but using the underscore saves on typing.
skillName, _, _, _, altVerb = GetTradeSkillInfo(index)
The most powerfull thing I found was the ability to call public functions in other mods. I think functions are public by default so most mods are wide open for interaction.
local itemId = Skillet:GetItemIDFromLink(itemLink) _, _, _, _, altVerb = GetTradeSkillInfo(index) if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then -- Ask LSW for the correct scroll itemId = LSW.scrollData[itemId]["scrollID"] end
In the example I just gave, I take an item link and use a public function of Skillet to pull out the item ID. That is an easy function to write but it was so quick to just ask skillet. GetTradeSkillInfo is a built in api call that gets info about a trade skill. I use it here to get the skill type. I then check an array in LSW to see if they have it in the scroll conversion list and make sure the type is an enchant. I then replace the item id I have with the translated one that LSW has if needed. This was all the code I needed to add to KTQ for enchant scroll support.
With this stuff in mind, go take a look at other mods. Start with simple mods and just look around. Some are packed with thousands of lines of complicated code, others have nice clean functions. One time I was doing something that interacted with the mailbox. I downloaded every bulk mailing mod on curse to figure it out. I was hunting for one small feature and I found it easier in some crapy low rated mod than in the full featured highly popular mod. Fewer features means less code to look at. People also do stuff in different ways.
One last thing to remember is that wowwiki has a good section on warcraft API calls. I use that site a lot to figure things out. You don’t have to start learning LUA by writing a full mod. Making little changes to other mods is how I got started.
