Thread Tools Display Modes
03-12-13, 05:47 PM   #1
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
How to incorporate cooldowns on clickable button frames generated in xml file.

I am trying to redo an outdated Hunter Trap mod. This is my first attempt at addons. I want to add cooldowns to existing frames and cannot find a method that works. The button frames are in the xml file. Is there a website (other than "Hello World") that can point me in the right direction? Thank you.
  Reply With Quote
03-12-13, 06:23 PM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
First of all, I'd highly recommend rewriting your frames in Lua, and avoid using XML.

Secondly, to add a cooldown, you create a new frame with the "Cooldown" object type (instead of "Frame" or "Button"), parent and anchor to your frame, give it the same size as your frame (or use SetAllPoints, or SetPoint if you need offsets). Then :Show() your cooldown and use :SetCooldown(...) to start the sweeping animation.

See also:
* http://www.wowpedia.org/Widget_API#Cooldown
* http://www.wowpedia.org/API_Cooldown_SetCooldown (there's a code example here)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-12-13, 06:30 PM   #3
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,359
SetCooldown

He's adding a cooldown on top of the playerframe for the example.
You would do the same for your frames.

If you want to do that in .xml you'd add a Cooldown as a child of your frame something like this:
Code:
<Frame name="YourFrameNameHere">
 <Frames>
  <Cooldown name="$parentCD" inherits="CooldownFrameTemplate" parentKey="cooldown" />
 </Frames>
</Frame>
The inherits and parentKey attributes are optional, parentKey makes it so you have a reference to your cooldown frame on its parent ie _G["YourFrameNameHere"].cooldown let's you run methods on the cooldown.
  Reply With Quote
03-13-13, 11:45 AM   #4
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
Still unable to get the cooldowns on buttons.

Thank you guys for your informative and rapid responses. I agree that .lua would be a better choice, especially for what I eventually want to do in the Addon. But I do have a better understanding of what needs to be done here. I have researched the material you've provided and through trial and error am still unable to get a CD on the button(s). There's 4 Trap buttons and the Launcher on this set up and I have included part of the beginning .xml. I have been working on the 1st trap-Explosive- and if you would again point me in the proper direction I will be able to get back to the 'Daily' marathon that is MoP. Thank you.
Sorry--have never included attachments before and not sure so I am placing an original part of the .xml here devoid of any changes that I tried.
<Script file="EZTrap.lua" />
<Frame name="Frame1" parent="UIParent" toplevel="true" movable="true" enableMouse="true">
<Size>
<AbsDimension x="110" y="110" />
</Size>
<Anchors>
<Anchor point="CENTER">
<Offset x="-1" y="-144" />
</Anchor>
</Anchors>
<Backdrop bgFile="Interface\FrameGeneral\UI-Background-Rock" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets>
<AbsInset left="11" right="12" top="12" bottom="11" />
</BackgroundInsets>
<TileSize>
<AbsValue val="32" />
</TileSize>
<EdgeSize>
<AbsValue val="32" />
</EdgeSize>
</Backdrop>
<Frames>
<Button name="Explosive" inherits="SecureActionButtonTemplate">
<Size>
<AbsDimension x="28" y="28" />
</Size>
<Anchors>
<Anchor point="CENTER">
<Offset x="32" y="30" />
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
self:RegisterForClicks("LeftButtonUp");
self:SetAttribute("type1", "spell");
self:SetAttribute("spell1", "Explosive Trap");
</OnLoad>
</Scripts>
<NormalTexture file="Interface\Icons\Spell_fire_selfdestruct" />
</Button>
  Reply With Quote
03-13-13, 11:52 AM   #5
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,359
Haven't looked at your actual code yet but you can use a [code]your code here[/code] ( button at the post editor) to make your code easier to read and make it create a fixed size scrollable region in your post.
  Reply With Quote
03-13-13, 01:31 PM   #6
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
Thanks. Here it is again.

Thank ya, D. Let's try that.
Code:
	<Frame name="Frame1" parent="UIParent" toplevel="true" movable="true" enableMouse="true">
		<Size>
			<AbsDimension x="110" y="110" />
		</Size>
		<Anchors>
			<Anchor point="CENTER">
				<Offset x="-1" y="-144" />
			</Anchor>
		</Anchors>
		<Backdrop bgFile="Interface\FrameGeneral\UI-Background-Rock" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
			<BackgroundInsets>
				<AbsInset left="11" right="12" top="12" bottom="11" />
			</BackgroundInsets>
			<TileSize>
				<AbsValue val="32" />
			</TileSize>
			<EdgeSize>
				<AbsValue val="32" />
			</EdgeSize>
		</Backdrop>
		<Frames>
			<Button name="Explosive" inherits="SecureActionButtonTemplate">
				<Size>
					<AbsDimension x="28" y="28" />
				</Size>
				<Anchors>
					<Anchor point="CENTER">
						<Offset x="32" y="30" />
					</Anchor>
				</Anchors>
				<Scripts>
					<OnLoad>
						self:RegisterForClicks("LeftButtonUp");
						self:SetAttribute("type1", "spell");
						self:SetAttribute("spell1", "Explosive Trap");
					</OnLoad>
				</Scripts>
				<NormalTexture file="Interface\Icons\Spell_fire_selfdestruct" />
			</Button>
  Reply With Quote
03-13-13, 03:55 PM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Please don't use names like "Frame1" for your frames. Those names are global, which means they sit in the same namespace as Lua functions, WoW API functions, WoW UI objects and functions, other addons' global objects, etc.

Instead, use names that are both (a) descriptive, so users can easily match them to their parent addon, and (b) unique, so they won't collide with other badly named global variables. A simple and effective tactic is to prepend your addon's name, so "MyAddon_Frame1" would be fine, though "MyAddon_TrapButton1" or "MyAddon_Cooldown1" would be even better.

When you're referring to your frames in Lua, you can create a local reference with a shorter name that's easier to work with, eg:

Code:
local f = MyAddon_TrapButton1
f:Show()
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-17-13, 12:36 PM   #8
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
Still unable to connect the dots for cooldowns on buttons.

Thanks again. I have tried to employ both the methods from links and suggestions offered here. I guess this is a simple process but it still eludes me. I will try to correctly send my last attempted codes. Any suggestions will more than be appreciated.
Attached Files
File Type: lua EZTrap.lua (462 Bytes, 373 views)
File Type: xml EZTrap.xml (2.5 KB, 385 views)
  Reply With Quote
03-17-13, 06:41 PM   #9
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
EZTrap.xml
http://pastebin.com/raw.php?i=EW3GamHi
With this, you don't need the Lua file at all. The main problem was that you were just sticking the cooldown code in a random place, instead of putting it inside a <Frames> element for the button. Also you had some errors in your syntax, which is another problem with XML. If you're using Lua, you get descriptive error messages in-game. If you're using XML, you have to log in, log out, and check the game's FrameXML.log file for cryptic error messages.

Alternatively, you can rewrite it all in Lua so it is easier to read and work with:
http://pastebin.com/raw.php?i=30WRE8tP
With this, you don't need the XML file at all.

If you plan to add more buttons for other traps, I'd strongly recommend using either a template (XML) or a factory (Lua) to generate your trap buttons, so you aren't copying and pasting the same code for every button. Let me know if that's something you're interested in.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 03-17-13 at 06:45 PM.
  Reply With Quote
03-18-13, 07:49 AM   #10
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
So I said,"Why not put a coolldown on it..."

Thanks so much. Briefly: 2 Trap Mod.'s - a basic .xml displaying 5 traps + Launcher (no cd's) and a more advanced .lua Mod that builds 5 traps as you learn them (no launcher). I had planned to try to update both. I was quickly able to modify, reshape and update the content (no immoloation) of the .xml to reflect WoW's changes. It also gave me a more visual idea of what .lua was doing, I thought. Since that was so easy, I wanted to distance myself from the original by adding the cd's. I would then tackle the button building .lua mod. Looked good on paper.

I looked at your examples and today will attempt to make them work. I was able to get the main frame on the .lua to display without cd's and am looking into a 'cooldown value nil' or something close to that. As all traps will be included, I am interested in the template and factory methods and will be exploring both after i get something to show me a blessed cd.

Again, I greatly appreciate your time and effort.
  Reply With Quote
03-18-13, 08:10 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
The same Lua I posted before, modified to create the individual trap buttons using a factory function:
http://pastebin.com/YReaEXx6

I'll post the XML version later, but you should really just use Lua... XML is sooooooo ugly.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-19-13, 10:58 PM   #12
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
Above and beyond...

You are correct (of course) concerning .xml and this code has convinced me to abandon the .xml project- .Lua is so much smoother and easier to work with. I am currently looking at the lua and am stuck with: lua:33 ")" expected near "," but will continue until I can see a daggone trap that shows me a cooldown.
Many thanks.

Last edited by shamby : 03-19-13 at 10:59 PM. Reason: typo
  Reply With Quote
03-20-13, 09:30 AM   #13
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Line 33 should real:

Lua Code:
  1. local function TrapButton_OnEvent(self, event, ...)
  Reply With Quote
03-20-13, 05:37 PM   #14
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
That's a nice copypasta.

Also fixed another error I noticed:
http://pastebin.com/YatppdeJ
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-20-13, 05:39 PM   #15
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Originally Posted by Phanx View Post
That's a nice copypasta.
Don't worry Phanx, that's one for you to my 500.
  Reply With Quote
03-21-13, 09:36 AM   #16
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
function self:About_To_Give_Up

With all of the love that I've received I am unable to display the trap cooldowns. I was wondering if the function CooldownFrame_SetTimer(self, start, duration, enable) would work in the button factory? Also, should I just try to stick a 30 sec timer on the trap buttons?
Anyway, thanks for all of your help. It's still a useful addon.
  Reply With Quote
03-21-13, 01:45 PM   #17
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Try adding some debug prints to see what's going on:
Code:
        local function TrapButton_OnEvent(self, event, ...)
                local start, duration = GetSpellCooldown(self.spellID)
                if duration > 0 then
                        print(self:GetAttribute("spell"), "is on cooldown for", duration, "seconds.")
                        self.cooldown:Show()
                        self.cooldown:SetCooldown(start, duration)
                else
                        print(self:GetAttribute("spell"), "is not on cooldown.")
                        self.cooldown:Hide()
                end
        end
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-21-13, 05:47 PM   #18
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
Results for new code.

With original 'function code' error reads:
320x EZTrap\EZTrap-5.2-lua:39: attempt to index field "cooldown" (a nil value)
EZTrap\EZTrap-5.2.lua:39: in function <EZTrap\EZTrap.lua33

With new 'function code' error reads:
32x EZTrap\EZTrap-5.2-lua:41: attempt to index field "cooldown" (a nil value)
<in C code>
<string>: "CAMERORSELECTORMOVE":4 in function
<string>: "CAMERORSELECTORMOVE":1
Locals
("temporary")=nil
("temporary")="SPELL_UPDATE_COOLDOWN"
("temporary")="SPELL_UPDATE_COOLDOWN"
("temporary")= <func>= |c|: -1
Chat messages indicate when traps are on and off 30 sec cooldown as well as GCD.
  Reply With Quote
03-21-13, 05:53 PM   #19
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Post the code (or the link to the code) you are using when you get that error. Without the code, there's no way for anyone to tell you why the code is raising that error.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
03-21-13, 06:49 PM   #20
shamby
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 17
codes:

Sorry.This code gives the the error which follows.
Code:
-- Disable the addon if the player is not a hunter:
if select(2, UnitClass("player")) ~= "HUNTER" then
	return DisableAddOn("EZTrap")
end

------------------------------------------------------------------------
-- Create the base frame:
local EZTrap = CreateFrame("Frame", "EZTrap", UIParent)
EZTrap:SetPoint("CENTER", -1, -144)
EZTrap:SetSize(110, 110)

-- Make it draggable:
EZTrap:EnableMouse(true)
EZTrap:SetMovable(true)
EZTrap:RegisterForDrag("RightButton")
EZTrap:SetScript("OnDragStart", EZTrap.StartMoving)
EZTrap:SetScript("OnDragStop", EZTrap.StopMovingOrSizing)
EZTrap:SetScript("OnHide", EZTrap.StopMovingOrSizing)

-- Add the background:
EZTrap:SetBackdrop({
	bgFile = [[Interface\FrameGeneral\UI-Background-Rock]], tile = true, tileSize = 32,
	edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], edgeSize = 32,
	insets = { left = 11, right = 12, top = 12, bottom = 11 }
})

------------------------------------------------------------------------
-- Set up a button factory:
local CreateTrapButton
do
	-- Share the same event handler function between buttons
	-- instead of creating duplicate functions:
	local function TrapButton_OnEvent(self, event, ...)
		local start, duration = GetSpellCooldown(self.spellID)
		if duration > 0 then
			self.cooldown:Show()
			self.cooldown:SetCooldown(start, duration)
		else
			self.cooldown:Hide()
		end
	end

	function CreateTrapButton(spellID)
		-- Get the name and icon for the specificed spell:
		local spellName, _, spellIcon = GetSpellInfo(spellID)
		if not spellName then
			-- That's not a valid spell ID!
			return
		end

		-- Create the button:
		local button = CreateFrame("Button", "$parent"..gsub(spellName, "[^%a]", ""), EZTrap, "SecureActionButtonTemplate")
		button:SetSize(30, 30)

		-- Set the correct trap spell properties:
		button:SetAttribute("type", "spell")
		button:SetAttribute("spell", spellName)
		button:SetNormalTexture(spellIcon)
		button.spellID = spellID

		-- Add a cooldown to the button:
		local cd = CreateFrame("Cooldown", "$parentCooldown", button, "CooldownFrameTemplate")
		cd:SetAllPoints(true)
		cd:Hide()

		-- Update the cooldown when needed:
		button:RegisterEvent("SPELL_UPDATE_COOLDOWN")
		button:SetScript("OnEvent", TrapButton_OnEvent)

		-- Hand the button back to the calling code:
		return button
	end
end

------------------------------------------------------------------------
-- Add a button for Freezing Trap:
local Freezing = CreateTrapButton(1499)
Freezing:SetPoint("TOPLEFT")

------------------------------------------------------------------------
-- Add a button for Explosive Trap:
local Freezing = CreateTrapButton(13813)
Freezing:SetPoint("BOTTOMLEFT")

------------------------------------------------------------------------
-- Add buttons for other traps (or even other spells) as desired.
Error for the code directly above: 320x EZTrap\EZTrap-5.2-lua:39: attempt to index field "cooldown" (a nil value)
EZTrap\EZTrap-5.2.lua:39: in function <EZTrap\EZTrap.lua33

The following code generates the error which follows it:
Code:
-- Disable the addon if the player is not a hunter:
if select(2, UnitClass("player")) ~= "HUNTER" then
	return DisableAddOn("EZTrap")
end

------------------------------------------------------------------------
-- Create the base frame:
local EZTrap = CreateFrame("Frame", "EZTrap", UIParent)
EZTrap:SetPoint("CENTER", -1, -144)
EZTrap:SetSize(85, 85)

-- Make it draggable:
EZTrap:EnableMouse(true)
EZTrap:SetMovable(true)
EZTrap:RegisterForDrag("RightButton")
EZTrap:SetScript("OnDragStart", EZTrap.StartMoving)
EZTrap:SetScript("OnDragStop", EZTrap.StopMovingOrSizing)
EZTrap:SetScript("OnHide", EZTrap.StopMovingOrSizing)

-- Add the background:
EZTrap:SetBackdrop({
	bgFile = [[Interface\Icons\ability_ensnare]], tile = false, tileSize = 0,
	edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], edgeSize = 32,
	insets = { left = 11, right = 12, top = 12, bottom = 11 }
})

------------------------------------------------------------------------
-- Set up a button factory:
local CreateTrapButton
do
	-- Share the same event handler function between buttons
	-- instead of creating duplicate functions:
	    local function TrapButton_OnEvent(self, event, ...)
                local start, duration = GetSpellCooldown(self.spellID)
                if duration > 0 then
                        print(self:GetAttribute("spell"), "is on cooldown for", duration, "seconds.")
                        self.cooldown:Show()
                        self.cooldown:SetCooldown(start, duration)
                else
                        print(self:GetAttribute("spell"), "is not on cooldown.")
                        self.cooldown:Hide()
                end
        end

	function CreateTrapButton(spellID)
		-- Get the name and icon for the specificed spell:
		local spellName, _, spellIcon = GetSpellInfo(spellID)
		if not spellName then
			-- That's not a valid spell ID!
			return
		end

		-- Create the button:
		local button = CreateFrame("Button", "$parent"..gsub(spellName, "[^%a]", ""), EZTrap, "SecureActionButtonTemplate")
		button:SetSize(30, 30)

		-- Set the correct trap spell properties:
		button:SetAttribute("type", "spell")
		button:SetAttribute("spell", spellName)
		button:SetNormalTexture(spellIcon)
		button.spellID = spellID

		-- Add a cooldown to the button:
		local cd = CreateFrame("Cooldown", "$parentCooldown", button, "CooldownFrameTemplate")
		cd:SetAllPoints(true)
		cd:Hide()

		-- Update the cooldown when needed:
		button:RegisterEvent("SPELL_UPDATE_COOLDOWN")
		button:SetScript("OnEvent", TrapButton_OnEvent)

		-- Hand the button back to the calling code:
		return button
	end
end

------------------------------------------------------------------------
-- Add a button for Freezing Trap:
local Freezing = CreateTrapButton(1499)
Freezing:SetPoint("BOTTOMLEFT")

------------------------------------------------------------------------
-- Add a button for Explosive Trap:
local Freezing = CreateTrapButton(13813)
Freezing:SetPoint("TOPLEFT")

------------------------------------------------------------------------
-- Add a button for Ice Trap:
local Freezing = CreateTrapButton(13809)
Freezing:SetPoint("BOTTOMRIGHT")

------------------------------------------------------------------------
-- Add a button for Trap Launcher:
local Freezing = CreateTrapButton(77769)
Freezing:SetPoint("CENTER")
------------------------------------------------------------------------
-- Add a button for Snake Trap:
local Freezing = CreateTrapButton(34600)
Freezing:SetPoint("TOPRIGHT")

-- Add buttons for other traps (or even other spells) as desired.
Error generated for the code direcly above :
32x EZTrap\EZTrap-5.2-lua:41: attempt to index field "cooldown" (a nil value)
<in C code>
<string>: "CAMERORSELECTORMOVE":4 in function
<string>: "CAMERORSELECTORMOVE":1
Locals
("temporary")=nil
("temporary")="SPELL_UPDATE_COOLDOWN"
("temporary")="SPELL_UPDATE_COOLDOWN"
("temporary")= <func>= |c|: -1
-Chat messages correctly indicate when traps are on and off 30 sec cooldown as well as GCD.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » How to incorporate cooldowns on clickable button frames generated in xml file.

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off