From ESOUI Wiki
Greetings, and welcome to the annotated version of ISummonThee!
This is an annotated and dissected version of ISummonThee, version 0.2, for tutarial reasons.
You can download the sourcepre [my dropbox].
If you are completely new to AddOn-development and want a guided tour, you should check out [tutorial] first. This is for learning by example.
What does it do?
This AddOn analyzes the groupchat and reacts upon certain trigger phrases: "I summon thee (optional:name/@name)" calls everyone running this add-on to the speaker "Know thy master" makes everyone running this add-on pass the crown to the speaker
It contains the following things (all of them in ISummonThee.lua):
- Registering a Slash Command:
- To see how to register a SlashCommand, find SLASH_COMMANDS['/togglesummon']
- To see how to react to a SlashCommand, find local function toggleActive()
- A toggle
- To see how to turn an AddOn off/on, check the SlashComand and read local function toggleActive()
- Registering an event
- To see how the AddOn is registered within ESO, check the very last line of code
- To see how to tell the AddOn to listen to chat, check
EVENT_MANAGER:RegisterForEvent("ISummonThee_Initialized", EVENT_CHAT_MESSAGE_CHANNEL, onChatMessage)
It does not contain the following things:
- A menu / saved variables
- Several files
## Title: ISummonThee
The AddOn name. It must be identical to the name of the folder and the file.
## Author: manavortex
Who wrote this AddOn. Open the AddOn menu in your ESO client, you'll see.
## Version: 0.2
Your AddOn's version. If you upload your work on esoui, incrementing the version number will cause minion to list it as outdated. My standard practice here is to increment the first digit with every major update/release, the second digit with every overhaul/maintenance cycle, and add a letter for every bugfix (if I upload the same version but fixed the debug output that I forgot to comment out, I'd upload 0.2a )
## APIVersion: 100017 100018
Which version of ESO this is up to date for. 100017 is Shadow of the Hist, 100018 is Homestead. Yes, I've tested this on PTS!
The manifest file gets scanned for files to load. If you remove this line, your AddOn will show up in the list, but not do anything.
Lua is a procedural programming language, and as such things get evaluated in the order you write them. That means that local functions that are not registered to an object of any kind, such as
local function toggleActive() ... end
will be known to every other local function written beneath it.
I need this to be different, how do I do this?
Make your functions AddOn-functions. By registering a function like this:
function ISummonThee.toggleActive() ... end
you will be able to call it regardless of writing order. That is so because the very last line in the code is the line that actually registers the AddOn! You can first set up the structure before actually doing anything with it.
Local / Global / What?
The difference between those two is crucial. Everything that is not explicitly declared local will be available in ESO's global namespace.
function zo_strformat; return; end
in your code and gleefully watch everything going to hell.
To avoid that, and to not clutter up the global namespace needlessly, you should make any functions that you don't need to call from UI elements or across lua files local functions.
This can also be a security concern. Global functions can be called by anyone - other AddOns, or even the users via Chat!
Note that a local function will not be available across different files.
local function callMe() if condition1 then if not condition 1a then return end doSomething() end if condition2 then if not condition 2a then return end doSomethingElse() end end
A function is a logical block of code that contains a certain action. You can call functions from within functions.
You can identify them by the parenthesises() - anything with (maybe some arguments) is a function call. When you pass a function to another function as argument, you omit the parenthesises, as you otherwise pass the function value!
return ends the function call, skipping the execution of code behind it. Unless you add an argument (list) behind the "return", the value will be nil.
The above function is my preferred way to write termination conditions. Other ways to do the same thing are (list not exhaustive):
local function CallMe() if condition1 and condition1a then doSomething() end if condition 2 and condition 2a then doSomethingElse() end end
local function CallMe() if condition1 and condition1a then doSomething() else if condition 2 and condition 2a then doSomethingElse() end end
local function CallMe() if condition1 and condition1a then return doSomething() end if not condition 2 and condition 2a then return end end
You can assign function calls to variables
local accountName = GetUnitDisplayName('player') if accountName == "@manavortex" then grantWorldDomination() end
or use them inline:
if GetUnitDisplayName('player') == "@manavortex" then grantWorldDomination() end
How you handle this is mostly a matter of personal preference. You can see many different styles if you read through the AddOns you have installed.
Wait, but why?
Assigning function values to variables serves three main purposes:
Chaining up function calls until the end of the world is called spaghetti code. Trying to read someone else's (that includes past you) spaghetti code is annoying and difficult.
It's far easier to write
local myvar = function1(function2(function3(function4(function5(function6)))))) d(myvar) if myvar then ... end
d(function1(function2(function3(function4(function5(function6))))))) if function1(function2(function3(function4(function5(function6)))))) then ... end
You might want to debug your variables occasionally, to check why in the name of all that's good and holy your code isn't working.
- Saving API calls
What causes lag and makes add-ons impair performance is the number of API calls. You want to try to keep those as low as possible.
- Calling code is more expensive than accessing a variable.
- Accessing a global variable is (slightly) more expensive than accessing a local variable.
Please keep in mind that clearly naming your local variables and function calls will make it easier for other developers to understand your code.