WoW:Changing a button's action slot ID: Difference between revisions

m
Move page script moved page Changing a button's action slot ID to WoW:Changing a button's action slot ID without leaving a redirect
m (Move page script moved page Changing a button's action slot ID to WoW:Changing a button's action slot ID without leaving a redirect)
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Sometimes you would like to control the action a button will start when it is clicked. Maybe you want to add extra buttons, maybe you just want to control the behavior of existing ones. I will tell you in a moment how to do that, but first you should know something about how the default UI handles it's buttons.
Sometimes you would like to control the action a button will start when it is clicked. Maybe you want to add extra buttons, maybe you just want to control the behavior of existing ones. I will tell you in a moment how to do that, but first you should know something about how the default UI handles its buttons.
 
'''IMPORTANT: Recommendations involving changing ActionButton_GetPagedID do not work after WoW 2.0'''


==Button Handling in the Default UI==
==Button Handling in the Default UI==
World of Warcraft supplies the player with 6 action bars, each having 12 buttons. Some classes like warriors, rogues and druids have a few more bars due to their stances. Ever noticed the lower left bar changes its actions when you go in stealth or in battle stance? When changing stances, there are no buttons hidden or shown. Whatever stance you are in, the buttons remain tight at their position. What's actually changing are the action slot IDs of the buttons. You can read a bit more about this here: [[ActionSlot]] API Type. Two buttons having the same action ID means they are twins. If you drag an action onto one of them, the other one will adopt this action, too. This is because the potions, spells, abilities, macros, etc. on your buttons are not bound to the button itself, but to its action ID.
World of Warcraft supplies the player with 6 action bars, each having 12 buttons. Some classes, like warriors, rogues and druids have a few more bars due to their stances. have you ever noticed that the lower left bar changes its actions when you go in stealth or in battle stance? When changing stances, there are no buttons hidden or shown. Whatever stance you are in, the buttons remain tight at their position. What's actually changing are the action slot IDs of the buttons. You can read a bit more about this here: [[ActionSlot]] API Type. Two buttons having the same action ID means they are twins. If you drag an action onto one of them, the other one will adopt this action, too. This is because the potions, spells, abilities, macros, etc. on your buttons are not bound to the button itself, but to its action ID.


So, how does a button know its action ID? Let's look at Blizzard's ActionButton.lua, which you can obtain by downloading the Blizzard Interface Customization Tools here: http://www.blizzard.com/support/wow/?id=aww01669p (after installing this, you can find ActionButton.lua in "/Blizzard Interface Data/FrameXML"). The functions in this file handle the behaviour of (guess what?) buttons. But not of any buttons. The methods there are used by the action buttons on your bars.
So, how does a button know its action ID? Let's look at Blizzard's ActionButton.lua, which you can obtain by downloading the Blizzard Interface Customization Tools here: http://www.blizzard.com/support/wow/?id=aww01669p (after installing this, you can find ActionButton.lua in "/Blizzard Interface Data/FrameXML"). The functions in this file handle the behaviour of (guess what?) buttons. But not of any buttons. The methods there are used by the action buttons on your bars.
Line 8: Line 10:
In the ActionButton.lua file, every time a function (i.e. [[API_UseAction]]) needs to know the action ID of a specific button, it calls  
In the ActionButton.lua file, every time a function (i.e. [[API_UseAction]]) needs to know the action ID of a specific button, it calls  
   id = ActionButton_GetPagedID(button)
   id = ActionButton_GetPagedID(button)
I wouldn't recommend looking at the code of this method, because your brain may explode (unless you are good at reading uncommented and foreign code in Lua), but I will summarize the method for you. Every button has an ID, specified in the corresponding XML File:
I wouldn't recommend looking at the code of this method, because your brain may explode (unless you are good at reading uncommented and foreign code in Lua), but I will summarize the method for you. Every Blizzard UI button has an ID, specified in the corresponding XML File:
  <Button name="SomeName" ...someOtherValues... id="2">
  <Button name="SomeName" ...someOtherValues... id="2">
  ...some Code
  ...some Code
  </Button>
  </Button>
This ID can be obtained by calling button:GetID(). Unfortunately, this ID ranges from only 1-12, so the GetPagedID method can't just return this ID, or otherwise, we would have only twelve different actions at our disposal (the other 60 something buttons would be twins, triplets, and so on of the first 12, remember?). Don't ask me why Blizzard did this. To distinguish more than twelve buttons, getPagedID has to add an offset, according to the bar the button is on, to the action ID. That's not very convenient if we want to create our own buttons (i.e. to use these idle action IDs 109-120), as our buttons won't have an action bar. We couldn't call GetPagedID(button) to retrieve our button's ID.
This ID can be obtained by calling button:GetID(). Unfortunately, this ID ranges from only 1-12, and is then offset based on the type of button or action page page, so it's not very convenient if you want to create your own button.
 
Luckily, the blizzard code recognizes that AddOns need to create their own buttons so it provides special behaviour if you set the id of your Button to 0, using the "action" attribute of the button.


==Controlling a Button's Action Slot ID==
==Controlling a Button's Action Slot ID==
So, what can we do about this? Right, we can hook the ActionButton_GetPagedID function and replace it with one of our functions:
To make your own action button with a specific slot you simply have to set your button's ID to 0 (which is the default if you dont specify, but I recommend you set it anyway), and set the button's "action" attribute. You can do this in the XML, or in lua code afterwards.
  oldGetPagedID = ActionButton_GetPagedID
 
  ActionButton_GetPagedID = newGetPagedID
XML:
To create our own button, we can define it in an XML file and let it inherit its traits from Blizzard's ActionBarButtonTemplate:
 
   <CheckButton name="customButton" inherits="ActionBarButtonTemplate">
   <CheckButton name="customButton" inherits="ActionBarButtonTemplate" id="0">
     ... sizing, positioning, etc.
    <Attributes>
      <Attribute name="action" value="101"/>
     </Attributes>
   </CheckButton>
   </CheckButton>
Note that we don't have to define an ID in the XML tag. If you're wondering why I used CheckButton and not Button here, "CheckButton" is the frame type of all the default action buttons. This is because of channeled spells, auto-attack actions, etc., where the yellow border around the icon stays while the action is active. With a simple "Button", you can't do that, because upon using the action, this border just flashes once and the button returns to its former appearance. A CheckButton will stay like this, until he is told "OK, the action's done, you can relax and be normal again".
 
Now you should give your custom buttons some flag to indicate that they are yours, and the desired action slot ID. You can do this anywhere in your code, as long as it is before the first call to ActionButton_GetPagedID. I would recommend doing it in the OnLoad script handler:
LUA:
   <OnLoad>
   customButton:SetAttribute("action", 101);
    button.isCustomButton = 1
    button.customID = 103
    ActionButton_OnLoad()
  </OnLoad>
this is to determine whether the function newGetPagedID should return the customID or the return value of the oldGetPagedID function. The call to ActionButton_OnLoad() is there because defining a new OnLoad tag will overwrite the inherited one. If you don't put this call there, your button will behave strangely.
All we have to do now is define the function newGetPagedID:
  function newGetPagedID(button)
    if(button.isCustomButton) then
      return button.customID
    end
    return oldGetPagedID(button)
  end
Now we piggybacked the default UI's functions for managing buttons! Our custom button is treated just like a standard one, except that we can control its action slot ID.


[[Category: HOWTOs|Changing a Buttons Action Slot ID]]
[[Category: HOWTOs|Changing a Buttons Action Slot ID]]
Anonymous user