WoW:SecureActionButtonTemplate: Difference between revisions

From AddOn Studio
Jump to navigation Jump to search
m (catfix)
m (Move page script moved page SecureActionButtonTemplate to SecureActionButtonTemplate without leaving a redirect)
 
(6 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{Stub/API}}
{{uitech}}
{{tocright}}
The '''SecureActionButtonTemplate''' was introduced in [[Patch 2.0]] to allow addons to perform protected actions -- casting spells, executing macros, etc -- by specifying button behavior via its attributes.


Secure Frames are Blizzard's new mechanism as of WoW 2.0 to allow for the creation of custom interfaces which may target units, cast spells, use items, and the like while ensuring that such actions are done in a way that Blizzard approves of.
== Creating a SecureActionButton ==
To create a SecureActionButton, simply create a button that inherits from the SecureActionButtonTemplate; to make the button instance useful, specify interesting attributes. This can be done in both XML, Lua and a mix of the two:


This is documentation for current beta functionality, and is subject to change.
'''Using XML''':
 
<Button name="myButton" inherits="SecureActionButtonTemplate" parent="UIParent">
== Creating Secure Frames ==
  <Attributes>
All secure frames must inherit from one of the secure frame templates. These templates, found in FrameXML/SecureTemplates.xml include (but are not limited to):
    <Attribute name="type" value="action" />
 
    <Attribute name="action" value="1" type="number" />
* SecureActionButtonTemplate - A button template for click-cast style action buttons
   </Attributes>
* SecureUnitButtonTemplate - A variant of SecureActionButtonTemplate used for unit buttons
 
<Button name="myButton" inherits="SecureActionButtonTemplate">
   ...
  </Button>
  </Button>
'''Using Lua''': (Warning: the following code does nothing)
local btn = CreateFrame("Button", "myButton", UIParent, "SecureActionButtonTemplate");
btn:SetAttribute("type", "action");
btn:SetAttribute("action", 1);


 
== Modified attributes ==
<Button name="myButton" inherits="SecureUnitButtonTemplate">
{| class="darktable"
  ...
! Attribute !! Used on...
</Button>
|-
| type || Any clicks.
* Any secure frame that does not have a [[UnitId]] will fail to perform any action that requires one for the action.  
|-
myButton:SetAttribute("unit", [[UnitId]])
| *type1 || Any left click.
 
|-
== Frame Attribute Types ==
| type1 || Unmodified left click.
After creating a frame, you will want to endow it with various attributes that determine how it reacts to user input.
|-
 
| shift-type2 || Shift+right click. (But not Alt+Shift+right click)
* You will want to set an action type for the button. This determines what action the button takes when acted upon.  
|-
myButton:SetAttribute("type", <typeString>)
| shift-type* || Shift+any button click.
 
|-
Where typeString is one of the following base strings, which may then be modified as described below.  
| alt-ctrl-shift-type* || Alt+Control+Shift+any button click.
----
|-
===actionbar===
| <s>ctrl-alt-shift-type*</s> || Invalid, as modifiers are in the wrong order.
A button of this type changes your current action bar.<br />
'''Attributes:'''
 
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| action
| May be "increment", "decrement", or an integer which specifies the page to switch to.
|}
|}


frame:SetAttribute("type1", "actionbar") -- Sets this frame's left click type to "actionbar"
Some attribute may change value based on whether a particular combination of modifier keys is held down and/or a particular button is being clicked. Those attributes are typically called modified attributes, and are resolved by the SecureButton_GetModifiedAttribute function.
frame:SetAttribute("action1", "increment") -- Causes this frame to increment the action bar index when left clicked
-----


===action===
The "modified attribute" name takes the form of: modifier-name-button. The modifier is one of "alt-", "ctrl-", "shift-", or a combination of them in ''that'' order, and the button is a normally number from 1 through 5 or hyphen followed by an arbitrary string. Both the prefix and the suffix can be "*" to signify no regard to the modifier/button; "*attribute*" is thus equivalent to "attribute". Some examples are shown in the table to the right; both the modifier and the button must match the click details in order for the attribute value to be used.
Executes an action. Calls UseAction(action, unit, button)


<br />
A limited precedence order is defined by the Frame:[[API Frame GetAttribute|GetAttribute]] method.
'''Attributes:'''


{| border="1" style="border-collapse: collapse;" cellpadding="4"
==Button remapping==
|-----
SecureActionButtons are also able to change the button being clicked in response to whether your target can be assisted ([help]) or attacked ([harm]) by you; the two relevant attributes are "helpbutton" and "harmbutton". The value of those attributes, should they match, will be used as the button to resolve the "type" and other required arguments.
| action
| (integer) The action slot to execute
|-----
| unit
| (unitid) The unit to perform that action on. Defaults to player's target.
|}


frame:SetAttribute("type1", "action")
For example, suppose we wanted to create a button that would alter behavior based on whether you can attack your target. Setting the following attributes has the desired effect:
frame:SetAttribute("action1", 3) -- Causes this frame to use the action in your #3 action bar slot when left clicked
{| class="darktable"
frame:SetAttribute("shift-action1", 4) -- Causes this frame to use the action in your #4 action bar slot when shift-left clicked
!Attribute !! Value !! Purpose
-----
|-
 
| "unit" || "target" || Make all actions target the player's target.
===pet===
|-
Executes a pet action. Calls CastPetAction(self:GetAttribute("action"), self:GetAttribute("unit"))
| "*harmbutton1" || "nuke1" || Remap any left clicks to "nuke1" clicks when target is hostile.
<br />
|-
'''Attributes:'''
| "*harmbutton2" || "nuke2" || Remap any right clicks to "nuke2" clicks when target is hostile.
 
|-
{| border="1" style="border-collapse: collapse;" cellpadding="4"
| "helpbutton1" || "heal1" || Remap unmodified left clicks to "heal1" clicks when target is friendly.
|-----
|-
| action
| "type" || "spell" || Make all clicks cast a spell.
| (integer) The pet action slot to execute
|-
|-----
| "spell-nuke1" || "Mind Flay" || Cast Mind Flay on "hostile" left click.
| unit
|-
| (unitid) The unit to perform that action on. Defaults to player's target.
| "spell-nuke2" || "Shadow Word: Death" || Cast Shadow Word: Death on "hostile" right click.
|-
| "alt-spell-nuke2" || "Mind Blast" || Cast Mind Blast on "hostile" alt-right click.
|-
| "spell-heal1" || "Flash Heal" || Cast Flash Heal on "friendly" left click.
|}
|}


frame:SetAttribute("type1", "pet")
If the button is remapped by the "harmbutton" or "helpbutton" attributes, the value of the "unit" attribute is reevaluated with the new button suffix: it is therefore to make a button that would check the hostility of one unit, and perform a reactive action on an entirely different unit.
frame:SetAttribute("action1", 3) -- Causes this frame to use the action in your pet's #3 bar slot when left clicked
frame:SetAttribute("shift-action1", 4) -- Causes this frame to use the action in your pet's #4 action bar slot when shift-left clicked
-----


===spell===
== Action Types ==
Casts a spell.
The action the SecureActionButtonTemplate-inheriting frame actually performs is dependent on the value of its ''modified'' type attribute, and possibly additional attributes specific to a type.
<br />
'''Attributes:'''


{| border="1" style="border-collapse: collapse;" cellpadding="4"
The table below lists all valid type values and the attributes they use to perform their actions. All relevant attributes can be modified as previously described; and, to the extent possible, all types respect the "unit" attribute for targeting. Generally, variable names are used to refer to the value of the modified attribute sharing their name.
|-----
| spell
| (string) The name of the spell to cast. For example, "Flash Heal".
|-----
| unit
| (unitid) The unit to cast the spell on. Defaults to player's target.
|}


frame:SetAttribute("type1", "spell")
{| class="darktable"
frame:SetAttribute("spell1", "Flash Heal")
|+SecureActionButtonTemplate "type" attributes
frame:SetAttribute("shift-spell1", "Greater Heal")
|-
-----
! style="width: 8em" | Type
! style="width: 8em" | Used attributes
! Behavior
|-
| valign="top" | "actionbar"
| valign="top" | "action"
| Switches the current action bar depending on the value of the "action" attribute:


===item===
* A number: switches to a the bar specified by the number.
Uses an item in your inventory (equipped items) or your bags.
* "increment" or "decrement": move one bar up/down.
<br />
* "a, b", where a, and b are numeric, switches between bars a and b.
'''Attributes:'''
|-
| valign="top" | "action"
| valign="top" | "unit", "action"<br />["actionpage"]
| Performs an action specified by the "action" attribute (a number).<br />
If the button:GetID() > 0, paging behavior is supported; see the ActionButton_CalculateAction FrameXML function.
|-
| valign="top" | "pet"
| valign="top" | "unit", "action"
| Calls {{api|CastPetAction}}(action, unit);
|-
| valign="top" | "spell"
| valign="top" | "unit", "spell"
| Calls {{api|CastSpellByName}}(spell, unit);
|-
| valign="top" | "item"
| valign="top" | "unit"<br />"item" OR<br />["bag", "slot"]
| Equips or uses the specified item, as resolved by {{api|SecureCmdItemParse}}.
* "item" attribute value may be a macro conditioned string, item name, or "bag slot" string (i.e. "1 3").
* If "item" is nil, the "bag" and "slot" attributes are used; those are deprecated -- use a "bag slot" item string.
|-
| valign="top" | "macro"
| valign="top" | "macro" OR<br />"macrotext"
| valign="top" | If "macro" attribute is specified, calls {{api|RunMacro}}(macro, button); otherwise, {{api|RunMacroText}}(macrotext, button);
|-
| valign="top" | "cancelaura"
| valign="top" | "unit"<br />"index" OR<br />"spell"[, "rank"]
| Calls either {{api|CancelUnitBuff}}(unit, index) or CancelUnitBuff(unit, spell, rank). The first version
'''Note''': the value of the "index" attribute must resolve to nil/false for the "spell", "rank" attributes to be considered.
|-
| valign="top" | "stop" || &nbsp; || Calls {{api|SpellStopTargeting}}().
|-
| valign="top" | "target"
| valign="top" | "unit"
| Changes target, targets a unit for a spell, or trades unit an item on the cursor.<br />
If "unit" attribute value is "none", your target is cleared.
|-
| valign="top" | "focus"
| valign="top" | "unit"
| Calls {{api|FocusUnit}}(unit).
|-
| valign="top" | "assist"
| valign="top" | "unit"
| Calls {{api|AssistUnit}}(unit).
|-
| valign="top" | "mainassist"
| valign="top" | "action", "unit"
| Performs a main assist status on the unit based on the value of the "action" attribute:


{| border="1" style="border-collapse: collapse;" cellpadding="4"
* nil or "set": the unit is assigned main assist status. ({{api|SetPartyAssignment}})
|-----
* "clear": the unit is stripped main assist status. ({{api|ClearPartyAssignment}})
| slot
* "toggle": the main assist status of the unit is inverted.
| Integer specifying the slot the item to be used is in. If "bag" is set, then this will be a bag slot. If "bag" is not set, then it is an Inventory slot.
|-
|-----
| valign="top" | "maintank"
| bag
| valign="top" | "action", "unit"
| Integer specifying the bag the item to be used is in. Requires that "slot" be set.
| As "mainassist", but for main tank status.
|-----
|-
| item
| valign="top" | "click"
| String specifying the item name or [[itemString]]. May be used instead of a bag/slot combo. Will not be used if "slot" is set.
| valign="top" | "clickbutton"
|-----
| Calls clickbutton:Click(button)
| unit
| (string unitid) Unit to use that item on. Defaults to player's target.
|}
 
This causes the button to use the item in Slot #1 in your backpack when left clicked:
 
frame:SetAttribute("type1", "item")
frame:SetAttribute("bag1", "1")
frame:SetAttribute("slot1", "1")
 
This causes the button to use your Hearthstone when left clicked:
 
frame:SetAttribute("type1", "item")
frame:SetAttribute("item1", "Hearthstone")
frame:SetAttribute("item1", "item:6948") -- same thing!
 
Note that using items by bagslot will sell or bank them with the corresponding frames open. I.e. just as right-clicking items in bags does. Using items by name or itemstring on the other hand will never do that, just as placing them in an actionbar and clicking them that way won't.
 
-----
 
===macro===
Executes a macro.
<br />
'''Attributes:'''
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-
|-
| macro || (string or integer) Identifier specifying the macro to execute. This takes macro name or id.
| valign="top" | "attribute"
| valign="top" | ["attribute-frame",]<br />"attribute-name"<br />"attribute-value"
| valign="top" | Calls frame:SetAttribute(attributeName, attributeValue). If "attribute-frame" is not specified, the button itself is assumed.
|-
|-
| macrotext || (string) Macro text to be executed.
| valign="top" | Any other value
|}
| valign="top"| "_''type''"
| Action depends on the value of the modified ("_" .. type) attribute, or rawget(button, type), in that order.


Causes this frame to run the macro with ID #1 when left clicked.
* If the value is a function, it is called with (self, unit, button, actionType) arguments
 
* If the value is a string, a restricted snippet stored in the attribute specified by the value on the button is executed as if it was OnClick.
frame:SetAttribute("type1", "macro")
frame:SetAttribute("macro1", 1)
 
Causes this frame to run a macro that announces the player's target.
 
frame:SetAttribute("type1", "macro")
frame:SetAttribute("macrotext", "/party I am targetting %t")
-----
 
===stop===
Cancels spell targeting.
<br />
'''Attributes:'''
 
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| ''None''
|}
|}


Causes this frame to cancel spell targeting when clicked.
Additionally, the "target-item" or "target-bag", "target-slot" attributes allow you to create a button that would target a specific item in your inventory for a spell being cast. This targeting is performed after the main type processing, and only if a spell is currently being targetted. It is therefore possible to create a button that would cast a specific spell on a specific item by setting the relevant attributes. For instance, to disenchant an item in bag 1, slot 1:
btn:SetAttribute("type", "spell");
btn:SetAttribute("spell", "Disenchant");
btn:SetAttribute("target-item", "1 1"); -- ("bag slot")


frame:SetAttribute("type", "stop")
== Other attributes ==
-----
A few more attributes can affect how the button functions:
{| class="darktable"
! style="width: 8em" | Attribute
! style="width: 8em" | Values
! Function
|-
| valign="top" | "downbutton"
| valign="top" | Any string
| Remaps the mouse button if this is a "down" click. This transformation is applied before all others.
|-
| valign="top" | "unitsuffix"
| valign="top" | "pet", "target", etc.
| Appends the attribute's value to the "unit" attribute value when resolving units.
|-
| valign="top" | "toggleForVehicle"
| valign="top" | true, false
| When the unit's owner is in a vehicle, remap the pet to its owner, and its owner to its pet (the vehicle). Based on the original unit:


===target===
* If it was a pet unit ("raidpetX", "pet", etc), and owner is in a vehicle, remap to owner.
Perform an action on the target represented by this button's unit property.
* If it did not contain "target", or "allowVehicleTarget" attribute is set to true, remap the original unit to its pet.
* If you are targeting a spell, casts the spell on this button's unit.
|-
* If you are holding an item, attempts to drop the item onto the unit (initiate trade)
| valign="top" | "allowVehicleTarget"
* Otherwise, targets the unit.
| valign="top" | true, false
<br />
| If true, allows "toggleForVehicle" to remap units like "party1target" to "partypet1target".
'''Attributes:'''
|-
 
| valign="top" | "checkselfcast"
'''Attributes:'''
| valign="top" | true, false
 
| If true, and the SELFCAST modifier is held down, resolves the unit to "player".
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-
 
| valign="top" | "checkfocuscast"
|-----
| valign="top" | true, false
| unit
| If true, and the FOCUSCAST modifier is held down, resolves the unit to "focus".
| (string unitid) This button's unit. Defaults to player's target.
|}
frame:SetAttribute("type", "target")
-----
 
===target-item===
Perform an action (e.g. spell=disenchant) on an item in your bags
<br />
 
'''Attributes:'''
frame:SetAttribute("target-item", "itemName" or "[[itemString]]" or "[[itemLink]]")  -- possibly itemid? not tested
-----
 
===focus===
Sets your focus to this button's ''unit'' attribute.
<br />
'''Attributes:'''
 
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| unit
| (string unitid) This button's unit. Defaults to player's target.
|}
 
Clicking this frame will set your focus to this frame's specified ''unit''.
frame:SetAttribute("type", "focus")
-----
 
===assist===
Assist the unit specified by this button's ''unit'' attribute and attack their target.
<br />
'''Attributes:'''
 
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| unit
| (string unitid) This button's unit. Defaults to player's target.
|}
 
Clicking this frame will cause you to target and start attacking the target of this button's unit.
frame:SetAttribute("type", "assist")
-----
 
===click===
Clicks another button. Allows this button to act as a proxy to another button.
<br />
'''Attributes:'''
 
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| clickbutton
| The button object that this button will proxy its click to when clicked
|}
|}


Clicking this button will call :Click() on myOtherButton.
frame:SetAttribute("type", "click")
frame:SetAttribute("clickbutton", myOtherButton)
-----
===attribute===
Sets attribute for arbitrary frame.
<br />
'''Attributes:'''
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| attribute-frame
| The frame to set attribute for. Defaults to this frame.
|-----
| attribute-name
| Attribute name.
|-----
| attribute-value
| Attribute value.
|}
Clicking this button will call MyOtherButton:SetAttribute("unit","focus").
frame:SetAttribute("type", "attribute")
frame:SetAttribute("attribute-frame", MyOtherButton)
frame:SetAttribute("attribute-name","unit")
frame:SetAttribute("attribute-value","focus")
-----
===menu===
Shows a popup menu.
<br />
'''Attributes:'''
{| border="1" style="border-collapse: collapse;" cellpadding="4"
|-----
| Requires that the button have a "menu" property set. This property should be a function that takes a unit as a parameter.
|}
Clicking this button will call :Click() on myOtherButton.
frame:SetAttribute("type", "menu")
frame.menu = some_function_that_shows_a_menu
----
== Frame Attribute Modifications ==
As the examples above have hinted, frame attributes may be modified to refer to allow for extreme flexibility in binding reactions to buttons.
FrameXML/SecureTemplates.lua offers this documentation:
The "modified attribute" takes the form of: modifier-name-button. The modifier is one of "alt-", "ctrl-", "shift-", or combination of them in '''''this''''' order, and the button is a number from 1 through 5 or hyphen followed custom button name mapped through some means.
* Note that modifiers have to appear in order "alt-ctrl-shift-" to function, if you mess the order that attribute will only consume memory for nothing.
For example, you could set an action that is used for unmodified left click like this:
self:SetAttribute("action1", value);
You could set an action that is used for shift-right-click like this:
self:SetAttribute("shift-action2", value);
You can also use a wildcard in the place of the modifier or button to denote an attribute that is used for any modifier or any button.
For example, you could set an action that is used for any left click like this:
self:SetAttribute("*action1", value);
You could set an action that is used for shift-click with any button like this:
self:SetAttribute("shift-action*", value);
You can exclude an action by explicitly setting its value to ATTRIBUTE_NOOP
For example, you could set an action that was used for all clicks except shift-left-click:
self:SetAttribute("*action*", value);
self:SetAttribute("shift-action1", ATTRIBUTE_NOOP);
Setting the attribute by itself is equivalent to *attribute*
----
SecureActionButtons allow you to map different combinations of modifiers and buttons into actions which are executed when the button is clicked.
For example, you could set up the button to respond to left clicks by targeting the focus:
self:SetAttribute("unit", "focus");
self:SetAttribute("type1", "target");
You could set up all other buttons to bring up a menu like this:
self:SetAttribute("type*", "menu");
self.showmenu = menufunc;
SecureActionButtons are also able to perform different actions depending on whether you can attack the unit or assist the unit associated with the action button. It does so by mapping mouse buttons into "virtual buttons" based on the state of the unit. For example, you can use the following to cast "Mind Blast" on a left click and "Shadow Word: Death" on a right click if the unit can be attacked:
self:SetAttribute("harmbutton1", "nuke1");
self:SetAttribute("type-nuke1", "spell");
self:SetAttribute("spell-nuke1", "Mind Blast");
self:SetAttribute("harmbutton2", "nuke2");
self:SetAttribute("type-nuke2", "spell");
self:SetAttribute("spell-nuke2", "Shadow Word: Death");
In this example, we use the special attribute "harmbutton" which is used to map a virtual button when the unit is attackable. We also have the attribute "helpbutton" which is used when the unit can be assisted.
Although it may not be immediately obvious, we are able to use this new virtual button to set up very complex click behaviors on buttons. For example, we can define a new "heal" virtual button for all friendly left clicks, and then set the button to cast "Flash Heal" on an unmodified left click and "Renew" on a ctrl left click:
self:SetAttribute("*helpbutton1", "heal");
self:SetAttribute("*type-heal", "spell");
self:SetAttribute("spell-heal", "Flash Heal");
self:SetAttribute("ctrl-spell-heal", "Renew");
This system is very powerful, and provides a good layer of abstraction for setting up
a button's click behaviors.
----
The above, step-by-step, does the following:
Creates a virtual button on this button named "nuke1", which will respond to left clicks when this unit's target is attackable.
self:SetAttribute("harmbutton1", "nuke1");
Sets the virtual button "harm1"'s type to "spell"
self:SetAttribute("type-nuke1", "spell");               
         
Sets the virtual button "harm1"'s spell to "Mind Blast"
self:SetAttribute("spell-nuke1", "Mind Blast");                   
The net result is that when you left-click the button and the button's unit is attackable, you will cast Mind Blast (if you are able).
Creates a virtual button on this button named "nuke2", which will respond to right clicks when this unit's target is attackable.
self:SetAttribute("harmbutton2", "nuke2");
Sets the virtual button "harm2"'s type to "spell"
self:SetAttribute("type-nuke2", "spell");
Sets the virtual button "harm2"'s spell to "Shadow Word: Death"
self:SetAttribute("spell-nuke2", "Shadow Word: Death");
The net result is that when you right-click the button and the button's unit is attackable, you will cast Shadow Word:Death (if you are able).
 
With both of these set on the button, you will be able to cast Mind Blast and SW:D by left and right clicking, respectively, while the button's unit is set to an attackable unit.
We can then extend our button so that it also casts heal spells if the button's unit is friendly.
self:SetAttribute("helpbutton1", "heal1");
self:SetAttribute("type-heal1", "spell");
self:SetAttribute("spell-heal1", "Flash Heal");


self:SetAttribute("helpbutton2", "heal2");
self:SetAttribute("type-heal2", "spell");
self:SetAttribute("spell-heal2", "Renew");
The net result is a button that:
* Casts Mind Blast when left-clicked if your target is hostile
* Casts Shadow Word: Death when right-clicked if your target is hostile
* Casts Flash Heal when left-clicked if your target is friendly
* Casts Renew when right-clicked if your target is friendly


[[Category:Interface customization]]
{{API Trail Secure}}

Latest revision as of 04:48, 15 August 2023

The SecureActionButtonTemplate was introduced in Patch 2.0 to allow addons to perform protected actions -- casting spells, executing macros, etc -- by specifying button behavior via its attributes.

Creating a SecureActionButton[edit]

To create a SecureActionButton, simply create a button that inherits from the SecureActionButtonTemplate; to make the button instance useful, specify interesting attributes. This can be done in both XML, Lua and a mix of the two:

Using XML:

<Button name="myButton" inherits="SecureActionButtonTemplate" parent="UIParent">
  <Attributes>
   <Attribute name="type" value="action" />
   <Attribute name="action" value="1" type="number" />
  </Attributes>
</Button>

Using Lua: (Warning: the following code does nothing)

local btn = CreateFrame("Button", "myButton", UIParent, "SecureActionButtonTemplate");
btn:SetAttribute("type", "action");
btn:SetAttribute("action", 1);

Modified attributes[edit]

Attribute Used on...
type Any clicks.
*type1 Any left click.
type1 Unmodified left click.
shift-type2 Shift+right click. (But not Alt+Shift+right click)
shift-type* Shift+any button click.
alt-ctrl-shift-type* Alt+Control+Shift+any button click.
ctrl-alt-shift-type* Invalid, as modifiers are in the wrong order.

Some attribute may change value based on whether a particular combination of modifier keys is held down and/or a particular button is being clicked. Those attributes are typically called modified attributes, and are resolved by the SecureButton_GetModifiedAttribute function.

The "modified attribute" name takes the form of: modifier-name-button. The modifier is one of "alt-", "ctrl-", "shift-", or a combination of them in that order, and the button is a normally number from 1 through 5 or hyphen followed by an arbitrary string. Both the prefix and the suffix can be "*" to signify no regard to the modifier/button; "*attribute*" is thus equivalent to "attribute". Some examples are shown in the table to the right; both the modifier and the button must match the click details in order for the attribute value to be used.

A limited precedence order is defined by the Frame:GetAttribute method.

Button remapping[edit]

SecureActionButtons are also able to change the button being clicked in response to whether your target can be assisted ([help]) or attacked ([harm]) by you; the two relevant attributes are "helpbutton" and "harmbutton". The value of those attributes, should they match, will be used as the button to resolve the "type" and other required arguments.

For example, suppose we wanted to create a button that would alter behavior based on whether you can attack your target. Setting the following attributes has the desired effect:

Attribute Value Purpose
"unit" "target" Make all actions target the player's target.
"*harmbutton1" "nuke1" Remap any left clicks to "nuke1" clicks when target is hostile.
"*harmbutton2" "nuke2" Remap any right clicks to "nuke2" clicks when target is hostile.
"helpbutton1" "heal1" Remap unmodified left clicks to "heal1" clicks when target is friendly.
"type" "spell" Make all clicks cast a spell.
"spell-nuke1" "Mind Flay" Cast Mind Flay on "hostile" left click.
"spell-nuke2" "Shadow Word: Death" Cast Shadow Word: Death on "hostile" right click.
"alt-spell-nuke2" "Mind Blast" Cast Mind Blast on "hostile" alt-right click.
"spell-heal1" "Flash Heal" Cast Flash Heal on "friendly" left click.

If the button is remapped by the "harmbutton" or "helpbutton" attributes, the value of the "unit" attribute is reevaluated with the new button suffix: it is therefore to make a button that would check the hostility of one unit, and perform a reactive action on an entirely different unit.

Action Types[edit]

The action the SecureActionButtonTemplate-inheriting frame actually performs is dependent on the value of its modified type attribute, and possibly additional attributes specific to a type.

The table below lists all valid type values and the attributes they use to perform their actions. All relevant attributes can be modified as previously described; and, to the extent possible, all types respect the "unit" attribute for targeting. Generally, variable names are used to refer to the value of the modified attribute sharing their name.

SecureActionButtonTemplate "type" attributes
Type Used attributes Behavior
"actionbar" "action" Switches the current action bar depending on the value of the "action" attribute:
  • A number: switches to a the bar specified by the number.
  • "increment" or "decrement": move one bar up/down.
  • "a, b", where a, and b are numeric, switches between bars a and b.
"action" "unit", "action"
["actionpage"]
Performs an action specified by the "action" attribute (a number).

If the button:GetID() > 0, paging behavior is supported; see the ActionButton_CalculateAction FrameXML function.

"pet" "unit", "action" Calls CastPetAction(action, unit);
"spell" "unit", "spell" Calls CastSpellByName(spell, unit);
"item" "unit"
"item" OR
["bag", "slot"]
Equips or uses the specified item, as resolved by SecureCmdItemParse.
  • "item" attribute value may be a macro conditioned string, item name, or "bag slot" string (i.e. "1 3").
  • If "item" is nil, the "bag" and "slot" attributes are used; those are deprecated -- use a "bag slot" item string.
"macro" "macro" OR
"macrotext"
If "macro" attribute is specified, calls RunMacro(macro, button); otherwise, RunMacroText(macrotext, button);
"cancelaura" "unit"
"index" OR
"spell"[, "rank"]
Calls either CancelUnitBuff(unit, index) or CancelUnitBuff(unit, spell, rank). The first version

Note: the value of the "index" attribute must resolve to nil/false for the "spell", "rank" attributes to be considered.

"stop"   Calls SpellStopTargeting().
"target" "unit" Changes target, targets a unit for a spell, or trades unit an item on the cursor.

If "unit" attribute value is "none", your target is cleared.

"focus" "unit" Calls FocusUnit(unit).
"assist" "unit" Calls AssistUnit(unit).
"mainassist" "action", "unit" Performs a main assist status on the unit based on the value of the "action" attribute:
  • nil or "set": the unit is assigned main assist status. (SetPartyAssignment)
  • "clear": the unit is stripped main assist status. (ClearPartyAssignment)
  • "toggle": the main assist status of the unit is inverted.
"maintank" "action", "unit" As "mainassist", but for main tank status.
"click" "clickbutton" Calls clickbutton:Click(button)
"attribute" ["attribute-frame",]
"attribute-name"
"attribute-value"
Calls frame:SetAttribute(attributeName, attributeValue). If "attribute-frame" is not specified, the button itself is assumed.
Any other value "_type" Action depends on the value of the modified ("_" .. type) attribute, or rawget(button, type), in that order.
  • If the value is a function, it is called with (self, unit, button, actionType) arguments
  • If the value is a string, a restricted snippet stored in the attribute specified by the value on the button is executed as if it was OnClick.

Additionally, the "target-item" or "target-bag", "target-slot" attributes allow you to create a button that would target a specific item in your inventory for a spell being cast. This targeting is performed after the main type processing, and only if a spell is currently being targetted. It is therefore possible to create a button that would cast a specific spell on a specific item by setting the relevant attributes. For instance, to disenchant an item in bag 1, slot 1:

btn:SetAttribute("type", "spell");
btn:SetAttribute("spell", "Disenchant");
btn:SetAttribute("target-item", "1 1"); -- ("bag slot")

Other attributes[edit]

A few more attributes can affect how the button functions:

Attribute Values Function
"downbutton" Any string Remaps the mouse button if this is a "down" click. This transformation is applied before all others.
"unitsuffix" "pet", "target", etc. Appends the attribute's value to the "unit" attribute value when resolving units.
"toggleForVehicle" true, false When the unit's owner is in a vehicle, remap the pet to its owner, and its owner to its pet (the vehicle). Based on the original unit:
  • If it was a pet unit ("raidpetX", "pet", etc), and owner is in a vehicle, remap to owner.
  • If it did not contain "target", or "allowVehicleTarget" attribute is set to true, remap the original unit to its pet.
"allowVehicleTarget" true, false If true, allows "toggleForVehicle" to remap units like "party1target" to "partypet1target".
"checkselfcast" true, false If true, and the SELFCAST modifier is held down, resolves the unit to "player".
"checkfocuscast" true, false If true, and the FOCUSCAST modifier is held down, resolves the unit to "focus".