Thread Tools Display Modes
05-22-12, 11:35 AM   #1
zin99
A Deviate Faerie Dragon
Join Date: Nov 2010
Posts: 12
interrupt lockout duration display

hi, i want to do a script that displays the lockout duration on target/focus when an interrupt hit them. as i am not too confident in my lua knowledge i deciede to make a post on this forums and hope to find some help.

my main problem is, i don't really know how to implement the arguments of COMBAT_LOG _EVENT_UNFILTERED properly for this purpose.

as of now i use:

Code:
t=CreateFrame("Frame")
t:SetPoint("CENTER",0,-100)
t:SetSize(40,40)
t.c=CreateFrame("Cooldown","cd1")
t.c:SetAllPoints(t)
t.t=t:CreateTexture(nil,"BORDER")
t.t:SetAllPoints()
t.t:SetTexture("Interface\\Icons\\ability_kick")


t:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
t:SetScript("OnEvent", function(...) local a,_,_,d = select(4, ...)
if (a == "SPELL_INTERRUPT"and d == UnitName("Player"))
then CooldownFrame_SetTimer(cd1,GetTime(),5,1)end end)
this basically tracks my own interrupts and was created mainly by try and error, copy pasting elements from other scripts. i understand that i will have to create to frames for target and focus and the corresponding destName argument, but couldn't get the code done.
the next step would be to take ANY interrupt spell into account and determining the different lockout duration depending on what interrupt hit the target/focus (ExtraSpellID argument i believe?)
eg: "1766" = 5, -- Kick
"2139"= 8, -- Counterspell

and the final adjustment i'd like to do would be for the icon(s) to only show when they are actually counting down (is cooldown spiral shown = true or sth, really no clue sorry )

any help would be greatly appreciated, thank you for your patience with a lua noob in advance.

Last edited by zin99 : 05-22-12 at 12:08 PM.
  Reply With Quote
05-23-12, 01:55 PM   #2
zin99
A Deviate Faerie Dragon
Join Date: Nov 2010
Posts: 12
ok i got it in a working condition. im am sure the code is anything but pretty, but well it really is the third time im trying to do anything in lua. i basically have a lot of if/elseif stuff for any combination of SpellID und destUnit and its working so far.

now my question is: how can i hide the icon frame displaying the cooldown if it isn't actually counting, and have it pop only if an interrupt hits aka the cooldown spiral is shown on the icon.
  Reply With Quote
05-23-12, 06:03 PM   #3
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by zin99 View Post
ok i got it in a working condition. ... how can i hide the icon frame displaying the cooldown if it isn't actually counting, and have it pop only if an interrupt hits aka the cooldown spiral is shown on the icon.
Without seeing your code, we'd basically be writing all new code for you from the ground up, and I don't know about anyone else, but I have no desire to spend that much time helping you, when I know you already have 90% of the code written.

As has been stated hundreds of times in basically every thread on these forums:

If you want help fixing, changing, cutting down, or adding to your code, post your code.
  Reply With Quote
05-24-12, 04:39 AM   #4
zin99
A Deviate Faerie Dragon
Join Date: Nov 2010
Posts: 12
ok sorry phanx, here it is. i am ready to get laughed at for this code:

Code:
 local addon, addonName = ...

 local frame = CreateFrame("Frame")
 local onEvent = function(self, event, ...)
   if event == "COMBAT_LOG_EVENT_UNFILTERED" then
        local timestamp, subevent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags,
        spellID, spellName, spellSchool, extraSpellID, extraSpellName  = ...;
            if (subevent == "SPELL_INTERRUPT") then
            interruptgo(destName, spellID)
     end
   end
 end
 
 frame:SetScript("OnEvent", onEvent)
 frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
 
target=CreateFrame("Frame")
target:SetPoint("CENTER", TargetFrame, "CENTER",-130,0)
target:SetSize(40,40)
target.c=CreateFrame("Cooldown","cd1")
target.c:SetAllPoints(target)
target.t=target:CreateTexture(nil,"BORDER")
target.t:SetAllPoints()
target.t:SetTexture("Interface\\Icons\\ability_kick")

focus=CreateFrame("Frame")
focus:SetPoint("CENTER", FocusFrame, "CENTER",-130,0)
focus:SetSize(40,40)
focus.c=CreateFrame("Cooldown","cd2")
focus.c:SetAllPoints(focus)
focus.t=focus:CreateTexture(nil,"BORDER")
focus.t:SetAllPoints()
focus.t:SetTexture("Interface\\Icons\\ability_kick")
 
 function interruptgo(destName, spellID)
 
 if spellID == 1766 and destName == (UnitName("target")) then 
 CooldownFrame_SetTimer(cd1,GetTime(),5,1)
 target.t:SetTexture("Interface\\Icons\\ability_kick")
 elseif spellID == 1766 and destName == (UnitName("focus")) then 
 CooldownFrame_SetTimer(cd2,GetTime(),5,1)
 focus.t:SetTexture("Interface\\Icons\\ability_kick")
 
 elseif spellID == 1766 and destName == (UnitName("target")) then 
 CooldownFrame_SetTimer(cd1,GetTime(),4,1)
 target.t:SetTexture("Interface\\Icons\\spell_holy_rebuke")
 elseif spellID == 1766 and destName == (UnitName("focus")) then 
 CooldownFrame_SetTimer(cd2,GetTime(),4,1)
 focus.t:SetTexture("Interface\\Icons\\spell_holy_rebuke")
 
-- and so on for all interrupt spells...


 end
 end
would it be better to do the SpellID and icons textures as arguments of a table so that i can just get the duration and texture by adressing say "kick" in that table? if so i don't know how

but as is said, my main goal now is to not have the icons shown always but only if they are actually counting. is there a way to determine if there is actually an animation running on the CooldownFrame cd1 or cd2, or do i have to do it with an OnUpdate GetTime thingy.

thanx for helping me!

Last edited by zin99 : 05-24-12 at 04:41 AM.
  Reply With Quote
05-26-12, 04:32 AM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
First, some general suggestions for your code:

1. Don't create global variables. Not only are they slower to access than local variables, but they can easily be overwritten by other addons, especially when they have generic names like target.

2. Use a table for spell data instead of a long if-else chain. You already mentioned this; see below to see how to implement it.

3. Don't create one-use functions. In your code, the interruptgo function is only called once, from inside the onEvent function. Function closures cost memory, so it's more efficient to just move the contents of the interruptgo function into the onEvent function. If you were going to call the interruptgo function from different places (eg. more than one frame would call it from its event handler), then factoring out that code into its own function would be a good idea, but that's not the case here.

4. Use consistent, proper indentation. This will make your code much easier to read.

Second, to hide the icon when it's not displaying anything, hook the cooldown object's :Hide() method.

Here is your code with the above optimizations and changes applied, plus lots of comments to help you understand what's going on, and print statements to help you see what's going on in-game. You'll want to comment out the print statements once you know it's working.

I've also attached a copy in Lua file form to this post, so you don't have to copy and paste (and deal with the extra blank lines that are inserted when you copy from highlighted code blocks on this forum).

Lua Code:
  1. local addon, addonName = ...
  2.  
  3. ------------------------------------------------------------------------
  4. --  1. Define a list of spells to track:
  5. ------------------------------------------------------------------------
  6.  
  7. local spellData = {
  8.     [2139] = { -- Counterspell
  9.         duration = 7,
  10.         texture = "Interface\\Icons\\spell_frost_iceshock",
  11.     },
  12.     [1766] = { -- Kick
  13.         duration = 5,
  14.         texture = "Interface\\Icons\\ability_kick",
  15.     },
  16.     [47528] = { -- Mind Freeze
  17.         duration = 4,
  18.         texture = "Interface\\Icons\\spell_deathknight_mindfreeze",
  19.     },
  20.     [6522] = { -- Pummel
  21.         duration = 4,
  22.         texture = "Interface\\Icons\\inv_gauntlets_04",
  23.     },
  24.     [96231] = { -- Rebuke
  25.         duration = 4,
  26.         texture = "Interface\\Icons\\spell_holy_rebuke",
  27.     },
  28.     [80964] = { -- Skull Bash (Bear Form)
  29.         duration = 4,
  30.         texture = "Interface\\Icons\\inv_misc_bone_taurenskull_01",
  31.     },
  32.     [80965] = { -- Skull Bash (Cat Form)
  33.         duration = 4,
  34.         texture = "Interface\\Icons\\inv_bone_skull_04",
  35.     },
  36.     [57994] = { -- Wind Shear
  37.         duration = 2,
  38.         texture = "Interface\\Icons\\spell_nature_cyclone",
  39.     },
  40. }
  41.  
  42. ------------------------------------------------------------------------
  43. --  2. Create the icons to display:
  44. ------------------------------------------------------------------------
  45.  
  46. --  2.1. Create a table to hold the icons:
  47. local unitIcons = {}
  48.  
  49. --  2.2. Create a function that makes an icon:
  50. local newIcon
  51. do
  52.     -- Use scoping to keep variables limited to where they are useful.
  53.     -- The following two functions are only used by the following third
  54.     -- function, and do not need to be accessible anywhere else.
  55.  
  56.     local function icon_OnDragStart(self, mouseButton)
  57.         -- Only allow the icon to be moved if the Alt key is pressed.
  58.         if IsAltKeyDown() then
  59.             self:StartMoving()
  60.         end
  61.     end
  62.  
  63.     local function cooldown_OnHide(self)
  64.         -- Hide the icon when the cooldown ends.
  65.         local icon = self:GetParent()
  66.         icon.texture:SetTexture("")
  67.         icon:Hide()
  68.     end
  69.  
  70.     function newIcon(unit, parentFrame)
  71.         print("newIcon:", unit, parentFrame:GetName())
  72.  
  73.         local icon = CreateFrame("Frame", "$parentInterruptIcon", parentFrame)
  74.         icon:SetPoint("CENTER", parentFrame, -130, 0)
  75.         icon:SetSize(40, 40)
  76.         icon:EnableMouse(true)
  77.         icon:RegisterForDrag("LeftButton")
  78.         icon:SetScript("OnDragStart", icon_OnDragStart)
  79.         icon:SetScript("OnDragStop", icon.StopMovingOrSizing)
  80.         icon:SetScript("OnHide", icon.StopMovingOrSizing)
  81.         -- The OnHide script is needed so the icon doesn't get stuck to
  82.         -- the cursor if it gets hidden while it's being dragged.
  83.  
  84.         local texture = icon:CreateTexture(nil, "ARTWORK")
  85.         texture:SetAllPoints(true)
  86.         icon.texture = texture
  87.  
  88.         local cooldown = CreateFrame("Cooldown", "$parentCooldown", icon)
  89.         cooldown:SetAllPoints(true)
  90.         cooldown:HookScript("OnHide", cooldown_OnHide)
  91.         icon.cooldown = cooldown
  92.  
  93.         icon.unit = unit
  94.         unitIcons[unit] = icon
  95.  
  96.         return icon
  97.     end
  98. end
  99.  
  100. --  2.3. Create the icons you want.
  101. newIcon("target", TargetFrame)
  102. newIcon("focus", FocusFrame)
  103.  
  104. --  You could easily extend this to, for example, add an icon to the
  105. --  arena enemy frames, the boss frames, or even the player frame and
  106. --  party frames to see when your allies were interrupted!
  107. --  The newIcon function returns the icon created, in addition to adding
  108. --  it to the unitIcons table, so you could easily apply custom points
  109. --  or other attributes to a specific icon, eg:
  110.  
  111. --  local playerIcon = newIcon("player", PlayerFrame)
  112. --  playerIcon:ClearAllPoints()
  113. --  playerIcon:SetPoint("LEFT", PlayerFrame, "RIGHT", 40, 0)
  114.  
  115. ------------------------------------------------------------------------
  116. --  3. Watch the combat log for interrupts:
  117. ------------------------------------------------------------------------
  118.  
  119. --  3.1. Create a frame to listen for combat log events:
  120. local eventFrame = CreateFrame("Frame")
  121.  
  122. --  3.2. Tell the frame which event to listen for:
  123. eventFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
  124.  
  125. --  3.3. Tell the frame what to do when the event happens:
  126. eventFrame:SetScript("OnEvent", function(self, event, timestap, combatEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool, extraSpellID, extraSpellName, ...)
  127.     --  3.3.1. Check the combat event:
  128.     if combatEvent ~= "SPELL_INTERRUPT" then
  129.         -- We don't care about this combat event.
  130.         return
  131.     end
  132.  
  133.     --  3.3.2. Check the spell:
  134.     local spell = spellData[spellID]
  135.     if not spell then
  136.         -- We don't care about this spell.
  137.         return
  138.     end
  139.  
  140.     print("event:", combatEvent, "spell:", spellName)
  141.  
  142.     --  3.3.3. Look for an icon for this unit:
  143.     for unit, icon in pairs(unitIcons) do
  144.         print("unit:", unit, "destGUID:", destGUID, "unitGUID:", UnitGUID(unit))
  145.         if destGUID == UnitGUID(unit) then
  146.             -- We found the icon for the affected unit.
  147.             print("Found an icon!")
  148.  
  149.             -- Show the icon:
  150.             icon:Show()
  151.             -- Set the icon's texture:
  152.             icon.texture:SetTexture(spell.texture)
  153.             -- Show the icon's cooldown:
  154.             icon.cooldown:Show()
  155.             -- Start the cooldown animation:
  156.             icon.cooldown:SetCooldown(GetTime(), spell.duration)
  157.  
  158.             -- Done!
  159.             return
  160.         end
  161.     end
  162.  
  163.     --  3.3.4. If we get here, that means we couldn't find an icon.
  164.     --  At this point you don't need to do anything, but if you later
  165.     --  wanted to do something when this happens, you'd do it here.
  166.     print("Could not find icon for unit!")
  167. end)
Attached Files
File Type: lua wowi-t43459.lua (5.3 KB, 502 views)
__________________
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
05-26-12, 05:09 PM   #6
zin99
A Deviate Faerie Dragon
Join Date: Nov 2010
Posts: 12
thank you so much phanx, especially for the explanations, really helps me a lot to understand lua better.

you should consider releasing this as an addon i guarantee a lot of people would appreciate it if they don't find or expect to find it in the forums.

edit: maybe as a plugin for losecontrol, the two would be a perfect fit

Last edited by zin99 : 05-26-12 at 05:12 PM.
  Reply With Quote
05-27-12, 10:19 PM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I probably won't release an addon like this, since publishing an addon I don't personally use is just too much of a hassle to try to maintain and support. I will never notice when a patch breaks it, for example, or when something doesn't work right, or when something needs to be added.

However, you (or anyone else) are free to turn it into an addon or publish it. I absolutely don't care what anyone does with my code, either code I've posted on the forums, or code from my addons; the main restriction in the license I use for my addons is that you have to pick your own name for the addon (eg. if you copy code from my addon PhanxChat and use it in your own addon, you can't call your addon PhanxChatPlus). The reasons for this are that (a) I don't want anyone coming to me to get help with your addon, and (b) if your addon sucks, I don't want people thinking I had anything to do with it.
__________________
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

WoWInterface » Developer Discussions » Lua/XML Help » interrupt lockout duration display


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