WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Executing skills (https://www.wowinterface.com/forums/showthread.php?t=39302)

Arxae 03-15-11 06:36 PM

Executing skills
 
I have been messing around with frames a bit and it is going pretty well :)
but i came to a point where i want to execute a skill when i click the frame.
I created a frame using CreateFrame()
Set a texture using CreateTexture() and assigned it to the frame
And then i used the SetScript function to set a OnMouseDown event. Then the dread began: frame needs to be protected.

My problem first of all is how? i followed the text on the wiki but i can't seem to get it to work.
Second of all, i read that the position and state (hidden/shown) can't be changed. Is there no way around this?

Il try to explain with a bit of an example :)
The thing i wanted to make is that some buttons show up under certain (combat) situations.
So i create all the frames beforehand and hide them (only one atm)
Then when the situation happens (a skill procs for example) the corresponding frame needs to be shown. When i click on the frame, the skill needs to be cast and the frame hidden again.

Can anyone help me on my way with this? :)

Akkorian 03-15-11 09:16 PM

Hi Arxae,

In order to cast a spell, use an item, run a macro, target a unit, or do anything like that, your frame has to use one of Blizzard’s secure templates.

You can make buttons that appear when you enter combat, or appear when you target an enemy while in combat, but you can’t make them appear (or change which ability is on them) when you gain a buff or when a reactive ability becomes available. The conditions you can use to automatically show, hide, or modify secure frames while in combat are the same conditions you can check for in macros.

I’d recommend looking at the addon CrowBar for a simple secure button example. States for auto-showing are a little trickier, and I haven’t ever worked with actual button states, but you could parent the button to a secure state driver frame and set up visibility conditions on that. There’s a simple example of that in ImprovedTotemFrame.

Looking at action bar addons might also help, though they tend to be pretty complicated. The same goes for the Blizzard UI code.

Hope that helps!

Arxae 03-16-11 07:48 AM

Ive been looking around a bit and i got a (supposedly) protected frame to show using this code:
Code:

        local f = CreateFrame("Frame", nil, UIParent, "SecureHandlerClickTemplate")
        f:SetFrameStrata("HIGH")
        f:SetWidth(64)
        f:SetHeight(64)
        f:EnableMouse(true)

        local t = f:CreateTexture(nil, "BACKGROUND")
        t:SetTexture("Interface\\Icons\\Inv_Sword_122.blp")
        t:SetAllPoints(f)
        f.texture = t

        f:SetPoint("CENTER", 0, 0)
        f:Show()

the problem now is that i cannot get a click event working
i tried using SetScript but it doesn't work, tried using SetAttribute, but that doesn't work either
the button does show up using SetAttribute, but the click event doesn't do anything, i'm using this example from wowpedia:
Code:

-- Assume widget is a frame inheriting from SecureHandlerClickTemplate.
widget:SetAttribute("_onclick", [=[ -- self, button, down are considered "arguments" to the _onclick handler
 if button == "RightButton" then
  self:Hide();
 end
]=]);

i changed the if statement to just print("test") tho, but it doesn't do anything at all :(

Akkorian 03-16-11 02:50 PM

I think the SecureHandlerClickTemplate template is for creating click-cast unit frames, not for making action buttons. Also, to get click handlers your frame must be a Button, not a regular Frame. Try this instead:

Code:

local f = CreateFrame("Button", nil, UIParent, "SecureActionButtonTemplate")
Then, you can make it do things when clicked by setting its attributes, like this:

Code:

f:SetAttribute( "type1", "spell" )
f:SetAttribute( "spell1", "Frost Shock" )

Or, if you want to run some code instead of casting a spell:

Code:

f:SetAttribute( "type1", "macro" )
f:SetAttribute( "macrotext1", "/run MyButton:Hide()" )

Or, to run some code and cast a spell:

Code:

f:SetAttribute( "type1", "macro" )
f:SetAttribute( "macrotext1", [[/cast Frost Shock
/run MyButton:Hide()]] )

In order to access the button from inside the macro though, you have to give it a global name:

Code:

local f = CreateFrame("Button", "MyButton", UIParent, "SecureActionButtonTemplate")
There’s some documentation about the SecureActionButton attributes in Blizzard’s SecureTemplates.lua file:

Code:

-- 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.


Arxae 03-17-11 04:49 AM

That is working as i wanted :D

one small problem tho. Whenever i try to use a macro command a spell (your third example)
it does the first thing, but just says the second thing (as in /s say :))
in this case:
f:SetAttribute( "macrotext1", [[/cast Frost Shock
/run MyButton:Hide()]] )
it casts the spell
then does ?/run MyButton:Hide() as a /s command

ps: thanks so much for the help :D

SDPhantom 03-17-11 06:51 AM

Is there actually a newline or a space between the two macro commands?

Arxae 03-17-11 08:43 AM

I tried both with space and newline
Newline gives me the weird ?/ error
Space makes the button do absolutely nothing :p

here are the specific snippets i'm talking about
Code:

f:SetAttribute("macrotext1", [[/cast horn of winter /run button:Hide()]])
Code:

f:SetAttribute("macrotext1", [[/cast horn of winter
/run button:Hide()]])

I also tried by sepparating the 2 macro commands with , and ;
, makes the button unresponsive
and ; makes the button only execute the first command

sacrife 03-17-11 08:45 AM

Try using end. (; sign)

f:SetAttribute("macrotext1", [[/cast horn of winter /;run button:Hide()]])

Arxae 03-17-11 08:57 AM

I think you didn't see my edit :) but ive tried that and it didn't work :<
you also had a typo :3

Seerah 03-17-11 01:59 PM

New line is added with \n

Arxae 03-17-11 03:33 PM

Quote:

Originally Posted by Seerah (Post 232077)
New line is added with \n

i think you are misunderstanding :)
i need to let the following command execute 2 actions:
Code:

f:SetAttribute("macrotext1", [[/run MyButton:Hide()]])

Seerah 03-17-11 03:58 PM

f:SetAttribute("macrotext1", [[/cast horn of winter\n/run button:Hide()]])

Arxae 03-17-11 04:58 PM

Quote:

Originally Posted by Seerah (Post 232085)
f:SetAttribute("macrotext1", [[/cast horn of winter\n/run button:Hide()]])

I used this exact code, and now the button is just unresponsive
It shows up, but when i click it, nothing happens

SDPhantom 03-18-11 03:58 AM

Do you have "Show Lua Errors" enabled in the interface options? I'm thinking it's throwing an error trying to access a frame referenced by a global variable named "button" that doesn't exist.


Quote:

Originally Posted by Seerah (Post 232077)
New line is added with \n

Quote:

Originally Posted by Arxae (Post 232093)
Quote:

Originally Posted by Seerah (Post 232085)
f:SetAttribute("macrotext1", [[/cast horn of winter\n/run button:Hide()]])

I used this exact code, and now the button is just unresponsive
It shows up, but when i click it, nothing happens

The "\n" escape only applies to quoted strings. The entire purpose of the bracket notation is to not need escapes, therefore they aren't processed at all.

Kayja 03-18-11 05:10 AM

I have a feeling he's got a random space somewhere, example (for OP mostly):

Will Work
Code:

f:SetAttribute("macrotext1", [[
/cast Frost Shock
/run MyButton:Hide()
]])

Will NOT Work
Code:

f:SetAttribute("macrotext1", [[
 /cast Frost Shock
 /run MyButton:Hide()
]])

It's the same as a macro directly written into the /macro window. If you add erroneous spaces in the macro it'll bugger it, in this case a random space at the start of each command will cause the line to be printed in /s rather than ran as a command. Alternatively, yeah you can use the \n but as SDPhantom points out it has to be inside of quotations not brackets, such as:

Code:

f:SetAttribute("macrotext1", "/cast Frost Shock\n/run MyButton:Hide()")

SDPhantom 03-18-11 12:57 PM

Quote:

Originally Posted by Kayja (Post 232206)
I have a feeling he's got a random space somewhere, example (for OP mostly):
Will Work
Code:

f:SetAttribute("macrotext1", [[
/cast Frost Shock
/run MyButton:Hide()
]])

[/code]

This is still missing the first point I made in my last post, the global variable "MyButton" in this example needs to exist. WoW is trying to throw an "attempt to index nil" error, but for some reason, the game client isn't showing it. My guess is the OP never turned on the option to show errors.

The OP needs to assign the frame to a global variable and use that in the macro. The /run macro command only inherits the global environment, it does not share any upvalues.

Phanx 03-18-11 03:36 PM

Quote:

Originally Posted by Arxae (Post 232057)
Code:

f:SetAttribute("macrotext1", [[/cast horn of winter
/run button:Hide()]])

I also tried by sepparating the 2 macro commands with , and ;
, makes the button unresponsive
and ; makes the button only execute the first command

1. Commas and semicolons are not valid characters for delimiting separate chat commands. Commas and semicolons are only valid within specific chat commands, such as "/castrandom Spell A, Spell B" or "/cast [condition] Spell A; Spell B". Semicolons are also valid (though ugly and unnecessary) separators within a single "/run" command, such as "/run local var = "x"; FunctionA(var); FunctionB(var)". In order to delimit separate chat commands you must use a newline, either by putting an actual newline character in your Lua file or by using the "\n" escape sequence in your string.

2. You didn't fully read and/or understand Akkorian's original post. I've underlined the relevant parts you should re-read:

Quote:

Originally Posted by Akkorian (Post 231967)
Code:

f:SetAttribute( "type1", "macro" )
f:SetAttribute( "macrotext1", [[/cast Frost Shock
/run MyButton:Hide()]] )

In order to access the button from inside the macro though, you have to give it a global name:

Code:

local f = CreateFrame("Button", "MyButton", UIParent, "SecureActionButtonTemplate")


Akkorian 03-19-11 02:18 AM

Hi Arxae,

Sorry, I forgot to add that you also have to register the button for clicks:

Code:

f:RegisterForClicks("AnyUp")
Also make sure you’re using the button’s global name, as other people pointed out. :)


All times are GMT -6. The time now is 04:19 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI