User:Cogswobble/Addon Tutorial/Slash Commands

From Warcraft Wiki
Jump to navigation Jump to search

So, we know what we want to do. But, how to get started?

Examining the API

Since both of my addons are very "inventory item"-centric, I should probably look at the available API functions and data types for dealing with inventory items, and see what is available for getting the data I'll need. Below is a list of functions grouped by area. The list was shamelessly stolen from the API page and cut down to a set of "interesting" functions for my addons (or my own education).

Bank Functions

BankButtonIDToInvSlotID(buttonID, isBag)   - Returns the ID number of a bank button or bag in terms of inventory slot ID.
GetNumBankSlots()   - Returns total purchased bank bag slots, and a flag indicating if it's full.

Container/Bag Functions

ContainerIDToInventoryID(bagID)
GetBagName(bagID)   - Get the name of one of the player's bags.
GetContainerItemInfo(bagID, slot)   - Get the info for an item in one of the player's bags.
GetContainerNumSlots(bagID)   - Returns the total number of slots in the bag specified by the index.
PROTECTED (Situational) UseContainerItem(bagID, slot[, onSelf])   - Uses an item located in bag# and slot#. (Warning: If a vendor window is open, using items in your pack may sell them!)   - 'onSelf' added in 1.12

Inventory Functions

ContainerIDToInventoryID(bagID)
GetInventoryItemCount("unit",invSlot)   - Determine the quantity of an item in an inventory slot.
GetInventoryItemQuality("unit",invSlot)   - Return the quality of an inventory item.
GetInventoryItemTexture("unit",invSlot)   - Return the texture for an inventory item.
GetInventorySlotInfo(invSlotName)   - Get the info for a named inventory slot (slot ID and texture)
PROTECTED UseInventoryItem(invSlot)   - Use an item in a specific inventory slot.

Item Functions

GetItemCount(itemId or "itemName" or "itemLink"[, includeBank])   - returns how many of specified item you have in your inventory
GetItemFamily(itemId or "itemName" or "itemLink")   - Returns the bag type that an item can go into, or for bags the type of items that it can contain. (New in Patch 2.4)
GetItemIcon(itemId or "itemString" or "itemName" or "itemLink")   - Returns the icon for the item. Works for any valid item even if it's not in the cache. (New in Patch 2.4)
GetItemInfo(itemId or "itemString" or "itemName" or "itemLink")   - Returns information about an item.
IsUsableItem(item)   - Returns usable, noMana.
IsConsumableItem(item)   -

Now What?

Now, I know what some of the above functions do. I have an idea what some of them do. And the rest...well, I have no idea. So, what I need to do now is play around with them and see what I can learn. There are a few ways to do this. First, you can use the slash command /script to execute a Lua function. This has the advantage of being really, really easy. The downside is that is just one function and we have a few that we want to play around with and see how they work together. Second, we can create an addon to perform certain operations as we press buttons, etc. So, this allows us to have complex behavior, but at the cost of building all the UI components and such. That is really overkill for a learning exercise. Third, we can create a new slash command. Arguments sent with the command can trigger complex behavior, but we don't have to waste the time creating UIs we are just going to throw out later.

We are going to go with the third option.

Creating a Slash Command

Setting Up the Addon Structure

Since I'm lazy, I'm going to name this addon MagicBox. Later, I can delete the files under it and reuse it for the real addon. So, that means creating a directory under <WoW install directory>\Interface\Addon named MagicBox.

MagicBox.toc

Next, I need to create a TOC file. You might want to do this last so you know what files to list in it, but I already know I'm going to have two files, MagicBox.lua and MagicBox.xml. The Lua file will contain the script for our desired behavior, and the XML file is needed to trigger the Lua script with a OnLoad event (more on this later).

Text of MagicBox.toc:

## Title: MagicBox
## Version: 0.1
## Author: Cogswobble of Malygos
## Interface: 30000

MagicBox.xml
MagicBox.lua

Your interface version number may be different, as this changes with each UI update. You'll know when this happens, all of the addons will show up as out of date. To find the latest interface version number, see Getting the current interface number.

MagicBox.xml

Now we need a simple XML file that will allow us to trap the OnLoad event and send it to our Lua script. The frame we generate doesn't need to be fancy. In fact, we don't even want to have it displayed. Text of MagicBox.xml:

<Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.blizzard.com/wow/ui/">
  <Script file="MagicBox.lua" />
  <Frame name="MagicBox" parent="UIParent" toplevel="true" hidden="true">
    <Scripts>
      <OnLoad>
        MagicBox_OnLoad();
      </OnLoad>
    </Scripts>
  </Frame>
</Ui>

The Script element identifies our Lua file. And the OnLoad element identifies MagicBox_OnLoad() as the function to call when the frame is loaded.

MagicBox.lua

Now it's time to write our Lua script. We need a function, MagicBox_OnLoad(), which will be called when the frame is loaded. This function needs to setup the slash command (we are going to use /magicbox, and for example purposes, /mb) and declare the handler function for when this slash command is used, MagicBox_SlashCommandHandler( msg ). Because Lua uses a one-pass parser, functions must be defined before being used. Therefore, MagicBox_SlashCommandHandler( msg ) must be defined before MagicBox_OnLoad() which will use it. Text for MagicBox.lua:

function MagicBox_SlashCommandHandler( msg )
  DEFAULT_CHAT_FRAME:AddMessage( "Command: " .. msg ); -- Output the message to the default chat window
end

function MagicBox_OnLoad()
  SlashCmdList["MAGICBOX"] = MagicBox_SlashCommandHandler; -- Add our slash command handler to the list of slash commands
  SLASH_MAGICBOX1 = "/magicbox"; -- Associate /magicbox with the slash command list entry for MAGICBOX
  SLASH_MAGICBOX2 = "/mb"; -- Associate /mb with the slash command list entry for MAGICBOX
end

This code really begs some explaination. The MagicBox_SlashCommandHandler function is pretty straightforward, the arguement msg will be output to the chat window. We'll modify this later to actually do some work. The MagicBox_OnLoad function is a little more mystical. The SlashCmdList is an array of handlers for different slash commands. The index string for our handler is "MAGICBOX". The following lines associate our slash commands with this index by creating the variables SLASH_MAGICBOX1 and SLASH_MAGICBOX2. Notice the use of the index string in the variables' names? That completes the association from the slash command string "/magicbox" to MagicBox_SlashCommandHandler.

Note, the MAGICBOX used as the index string is unrelated to the name of the addon or this function name. To make this point, here is the file again, except we implement the slash commands /beavis and /butthead:

function MagicBox_SlashCommandHandler( msg )
  DEFAULT_CHAT_FRAME:AddMessage( "Command: " .. msg ); -- Output the message to the default chat window
end

function MagicBox_OnLoad()
  SlashCmdList["TRICK"] = MagicBox_SlashCommandHandler; -- Add our slash command handler to the list of slash commands
  SLASH_TRICK1 = "/beavis"; -- Associate /beavis with the slash command list entry for TRICK
  SLASH_TRICK2 = "/butthead"; -- Associate /butthead with the slash command list entry for TRICK
end

This is very important to note, as this syntax is neither obvious or intuitive. A much better mechanism would have been something more like:

function MagicBox_OnLoad()
  AssociateSlashCommandToHandler( "/magicbox", MagicBox_SlashCommandHandler );
  AssociateSlashCommandToHandler( "/mb", MagicBox_SlashCommandHandler );
end

However, Blizzard stuck us with this kludgy code instead.

Test MagicBox

After saving your files, it's time to take it for a spin. Login and ensure that the addon is set to load with your character. Enter WoW with that character and type: /magicbox Test. You should see in your chat window: Command: Test. If not, or if you get an error, go back, fix your files and try again. Congratulations, you have just written an addon!