Page 62 of 111 FirstFirst ... 1252606162636472 ... LastLast
Results 611 to 620 of 1109

Thread: WeakAuras Tutoring Thread

  1. #611

    Default

    Thank you for your answer. It was helpful indeed.

    For that addon I will definitely take a look. It will probably help me save snippets of code that I want to look back on for reference.

    1) sorry I wasn't clear. I understood everything you said, but my question was mainly where those parameters were coming from (the unfiltered event). Again, sorry I wasn't clear in my question.

    2) scoping makes perfect sense. It's a bit hard to think about it all for me because each text box is it's own function within a larger set of code when I'm more use to seeing the grand picture. Thank you for that as well.
    Edit: Can you access global variables outside the aura? (Ex: Icon A uses a variable to calculate something based on a variable in Icon B)

    3) I knew about auto-cloning as well, I was more wondering if auto cloning could be applied to custom triggers?

    Thank you, this has been very helpful and will help me cement ideas and examples for the future when I've been just referring back to old auras to figure out what I did.
    Last edited by Krazyito; 09-10-2014 at 06:25 AM.

  2. #612

    Default

    Quote Originally Posted by Krazyito View Post
    2) scoping makes perfect sense. It's a bit hard to think about it all for me because each text box is it's own function within a larger set of code when I'm more use to seeing the grand picture. Thank you for that as well.
    Edit: Can you access global variables outside the aura? (Ex: Icon A uses a variable to calculate something based on a variable in Icon B)
    Yes you can use them in other Displays, which is in fact why I personally try to shy away from using globals myself since when you have dozens or even hundreds of Displays going with custom code, you can potentially begin to see issues where your variables have similar names that you forgot about.

    So by all means, you can certainly use globals elsewhere, but be careful about the frequency of use and variable names in particular.

    Also, if you really want to get into best practices, it is generally considered proper in Lua to use local variables whenever possible over globals due to better performance. In most applications (WoW addons included) the performance difference is negligible, however it never hurts to learn things right the first time. This excerpt has great information on the topic.

    Quote Originally Posted by Krazyito View Post
    3) I knew about auto-cloning as well, I was more wondering if auto cloning could be applied to custom triggers?
    No, you cannot auto-clone Displays that use Custom Triggers.

    You could somewhat "cheat" that limitation by designing smart enough code that the actual trigger function code of each Display is identical, and Displays would only trigger when it was appropriate. However, you're still going to need one Display for each enemy target (or whatever it is) in most cases.

  3. #613

    Default

    All right thanks. I've been shying away from using local because I was more confused (and somewhat lazy) on how the scope of everything worked and made some bad assumptions. That makes sense now and totally understand how good habits are essential.

    As for auto-cloning, I guess the best way for that would be like you said before, just a dynamic group with near identical code.

  4. #614

    Default

    Small question before I begin: are parameters for events local to that function? I'm assuming yes

    Another event question. If I have multiple events how do I go about using them separately? (I'm using ENCOUNTER_START and ENCOUNTER_END.)

    I have weak aura for Warrior's Shield Block that I'm using as an example, so I'm going to write out what I think is correct.

    Code:
    function(event, ...)
        if event == "COMBAT_LOG_EVENT_UNFILTERED" then
            local stamp, subevent, _, unit, _, _, _, target = ...
            WA_BlockedDamage = WA_BlockedDamage or 0
            if subevent == "SPELL_CAST_SUCCESS" then
                local spell = select(12, ...)
                if  unit == UnitGUID("player") and spell == 2565 then
                    WA_RecordingBlocks = true
                    WA_ConfirmBlock = {}
                    WA_BlockedDamage = 0
                    return true
                end
            elseif WA_RecordingBlocks and  target == UnitGUID("player") then
                if subevent == "SPELL_AURA_REMOVED"  then
                    local aura =  select(12, ...)
                    if aura == 145054 or aura == 132404 then
                        WA_RecordingBlocks = false
                        return true
                    end
                    return false
                end
                
                local blockParam
                if subevent == "SPELL_DAMAGE" then
                    blockParam = 19
                elseif subevent == "SWING_DAMAGE" then
                    blockParam = 16
                elseif subevent == "ENVIRONMENTAL_DAMAGE" then
                    blockParam = 17
                end
                if blockParam then
                    local blocked = select(blockParam, ...)
                    WA_BlockedDamage = WA_BlockedDamage + (((blocked and blocked > 0) and blocked) or 0)
                    return true
                end
                if subevent == "SWING_MISSED" and select(12, ...) == "ABSORB" then
                    local amount = select(14, ...)
                    local mastery = GetMasteryEffect() / 100
                    local averageBlock = (mastery * 0.6) + ((1 - mastery) * 0.3)
                    local estimate = floor((amount / averageBlock) - amount)
                    WA_ConfirmBlock[#WA_ConfirmBlock+1] = {stamp, estimate}
                end
            end
        elseif event == "UNIT_COMBAT" then
            local target, classification, desc, dmg = ...
            if WA_ConfirmBlock and #WA_ConfirmBlock > 0 and target == "player" and classification == "BLOCK" and desc == "ABSORB" then            
                local when, amount = unpack(WA_ConfirmBlock[#WA_ConfirmBlock])
                
                if time() - when < 2 then
                    WA_BlockedDamage = WA_BlockedDamage + amount
                    WA_ConfirmBlock[#WA_ConfirmBlock] = nil
                    return true
                end
                
                WA_ConfirmBlock[#WA_ConfirmBlock] = nil
            end        
        end
    end
    Now, most of that is garbage and does not pertain to my question. The main parts I'm focusing on is how the events are handled.
    His events are: COMBAT_LOG_EVENT_UNFILTERED, UNIT_COMBAT and he uses function(event, ...) in his code. Assumptions are: 'event' variable holds the name of the event being used and '...' is what the event returns? Edit- Actually, it looks like '...' is a token? must be used for something specific then..

    I suppose while we're at it, how do subevents work? Edit - nevermind, subevents was a variable he used in the combat log event.

    The trigger function may work differently because of the multiple events, but if there is only one then you can just save the returns in the parameters. Am I understanding this correctly?


    Lastly - Is there a way in WoWlua I can just print out what an event returns?
    Last edited by Krazyito; 09-10-2014 at 06:50 PM.

  5. #615

    Default

    Quote Originally Posted by Krazyito View Post
    Small question before I begin: are parameters for events local to that function? I'm assuming yes
    Correct.

    Quote Originally Posted by Krazyito View Post
    Another event question. If I have multiple events how do I go about using them separately? (I'm using ENCOUNTER_START and ENCOUNTER_END.)
    What do you mean by "using them separately"?

    I'm assuming you mean in a Custom Trigger, if the Event(s) field you are using multiple events, and you want to know how to distinguish between them within your code? If so, you somewhat answered your own question in the section below.

    When a WeakAura Display is triggered off of an event, the first argument it passes into your custom functions is always the name of the event.

    Quote Originally Posted by Krazyito View Post
    I have weak aura for Warrior's Shield Block that I'm using as an example, so I'm going to write out what I think is correct.

    Code:
    function(event, ...)
        if event == "COMBAT_LOG_EVENT_UNFILTERED" then
            local stamp, subevent, _, unit, _, _, _, target = ...
            WA_BlockedDamage = WA_BlockedDamage or 0
            if subevent == "SPELL_CAST_SUCCESS" then
                local spell = select(12, ...)
                if  unit == UnitGUID("player") and spell == 2565 then
                    WA_RecordingBlocks = true
                    WA_ConfirmBlock = {}
                    WA_BlockedDamage = 0
                    return true
                end
            elseif WA_RecordingBlocks and  target == UnitGUID("player") then
                if subevent == "SPELL_AURA_REMOVED"  then
                    local aura =  select(12, ...)
                    if aura == 145054 or aura == 132404 then
                        WA_RecordingBlocks = false
                        return true
                    end
                    return false
                end
                
                local blockParam
                if subevent == "SPELL_DAMAGE" then
                    blockParam = 19
                elseif subevent == "SWING_DAMAGE" then
                    blockParam = 16
                elseif subevent == "ENVIRONMENTAL_DAMAGE" then
                    blockParam = 17
                end
                if blockParam then
                    local blocked = select(blockParam, ...)
                    WA_BlockedDamage = WA_BlockedDamage + (((blocked and blocked > 0) and blocked) or 0)
                    return true
                end
                if subevent == "SWING_MISSED" and select(12, ...) == "ABSORB" then
                    local amount = select(14, ...)
                    local mastery = GetMasteryEffect() / 100
                    local averageBlock = (mastery * 0.6) + ((1 - mastery) * 0.3)
                    local estimate = floor((amount / averageBlock) - amount)
                    WA_ConfirmBlock[#WA_ConfirmBlock+1] = {stamp, estimate}
                end
            end
        elseif event == "UNIT_COMBAT" then
            local target, classification, desc, dmg = ...
            if WA_ConfirmBlock and #WA_ConfirmBlock > 0 and target == "player" and classification == "BLOCK" and desc == "ABSORB" then            
                local when, amount = unpack(WA_ConfirmBlock[#WA_ConfirmBlock])
                
                if time() - when < 2 then
                    WA_BlockedDamage = WA_BlockedDamage + amount
                    WA_ConfirmBlock[#WA_ConfirmBlock] = nil
                    return true
                end
                
                WA_ConfirmBlock[#WA_ConfirmBlock] = nil
            end        
        end
    end
    Now, most of that is garbage and does not pertain to my question. The main parts I'm focusing on is how the events are handled.
    His events are: COMBAT_LOG_EVENT_UNFILTERED, UNIT_COMBAT and he uses function(event, ...) in his code. Assumptions are: 'event' variable holds the name of the event being used and '...' is what the event returns? Edit- Actually, it looks like '...' is a token? must be used for something specific then..
    The event parameter we already covered above, but ellipses (...) are a special identifier in Lua that represents an "unknown number of parameters/arguments/identifiers". You can find official docs on it here, but it is the sort of thing that is very useful to use as a parameter in a function that can have a varying number of arguments passed to it.

    Use of ... is common in combat log stuff as seen in your example since by nature, COMBAT_LOG_EVENT_UNFILTERED will have a varying number of arguments depending on the type of the event.

    You can see another example of the use in my GetValue function I use frequently. In the case of GetValue, the function can be passed a near-infinite number of arguments (keys in this case) and recursively finds the appropriate value from my table by drilling down based on each key passed into it.

    Quote Originally Posted by Krazyito View Post
    The trigger function may work differently because of the multiple events, but if there is only one then you can just save the returns in the parameters. Am I understanding this correctly?
    Yes, as far I understand your question, I think you have it correct, though I'm somewhat unclear what you mean by "save the returns in the parameters."

    The key thing to keep in mind when dealing with Custom functions for events in WeakAuras is that the game (and therefore WeakAuras itself) has no knowledge or care about which event firings match your list of "triggering events." It is up to you, through your own custom function code, to only pay attention to the actual events you care about.

    COMBAT_LOG_EVENT_UNFILTERED is a great example of this since this event normally fires dozens if not hundreds of times per second in group situations, so from the perspective of WeakAuras, your trigger code is run every single time that event fires. Just like your example code above, it is up to your own functions to check event names, sub-events, and so on to actually work with the specific firings of COMBAT_LOG_EVENT_UNFILTERED that you care about.

    You might check out the variety of snippet functions I have for specifically dealing with the COMBAT_LOG_EVENT_UNFILTERED event. They are all designed to be used by passing in the full parameter list from the parent function (...), like so:

    Code:
    function(...)
       -- IsEventType('SPELL_AURA_APPLIED', ...)
       -- IsEventType('UNIT_DIED', ...)
       -- @value string - Event type
       -- @... list - Value list from CLEU function
       -- return boolean - Whether param value matches logged event type.
       local IsEventType = function(value, ...)
          if not select(1, ...) or select(1, ...) ~= 'COMBAT_LOG_EVENT_UNFILTERED' or not value or type(value) ~= 'string' then return end
          local event = select(3, ...)
          if not event then return end
          if event == value then return true end
       end
       
       if IsEventType('UNIT_DIED', ...) then
          print('Oh noes, it be dead!')
       end
    end
    I left the comments in there just for reference, but the parent function is of course the primary Custom trigger (or untrigger, or whatever) function with one of the firing events of COMBAT_LOG_EVENT_UNFILTERED. So by declaring my IsEventType function at the top, I can then check if IsEventType('UNIT_DIED', ...) is true and print out my message if so.

    Hope that helps a bit with events.

    Quote Originally Posted by Krazyito View Post
    Lastly - Is there a way in WoWlua I can just print out what an event returns?
    No.

    Your best bet is to use a WeakAura with the event(s) you want to track in the Trigger, then have your Custom Trigger function be something simple like:

    Code:
    function(...)
        print(...)
    end
    print is a function that will accept an unknown number of arguments, so it will print out each parameter passed into your function, one after the other in this case.

  6. #616

    Default

    You answered everything. Thank you. Its just going to take me a lot of trial and error now to make stuff work, but now I have a footing to stand on and get started.

    Quote Originally Posted by Kulldam View Post
    Yes, as far I understand your question, I think you have it correct, though I'm somewhat unclear what you mean by "save the returns in the parameters."
    Again, sorry for being unclear. I was asking if you only have one event for your custom trigger, then everything that event returns you can access within the parameters of the function (within the parentheses of function()), Which it seems you said the answer was yes.

  7. #617

    Default

    Quote Originally Posted by Krazyito View Post
    Again, sorry for being unclear. I was asking if you only have one event for your custom trigger, then everything that event returns you can access within the parameters of the function (within the parentheses of function()), Which it seems you said the answer was yes.
    Gotcha, and yes indeed!

  8. #618

    Default

    So I've been messing with the ENCOUNTER_START and ENCOUNTER_END events for a bit now.

    I made a simple text aura that displayed the contents of the event. On and off when I was trying to fiddle with it to get the info I wanted, the display wouldn't update or it would give continuous errors about nil values.

    So I tried finding ways of filling nil values with strings just to get it to display information. Which I had problems with because (as I think about it now) I was concatenating during the return of the display instead of saving the whole thing as a single string and checking for nil during the concatenation process before returning.

    When I finally just took out the extra argument that was part of END and not START (status, what was returning a nil value at the start of the encounter) it finally started working the way I wanted.

    Now, I was going to ask a question about how to fill those nil values that I'm to carry over from the trigger function to the display function, but I realise now that it's probably better to just use that information to trigger what I need instead of using it for what I was essentially doing as a check (which in the long run reduces the amount of global variables I use.) On top of answering my own question before hand as I was writing this.

    I also love that you introduced me to WOWLUA, I've been using it to save triggers of working auras and detailing what they are doing and such for future reference. Makes a nice hand book for myself and to show others if needed.

    So again I just wanted to thank you for explaining everything because I have tried doing things like this before but could not find the resources to show me how it was used. I'll be sure to come back when I have another issue. =)
    Last edited by Krazyito; 09-14-2014 at 05:00 AM.

  9. #619

    Default

    Well, it seems I spoke too soon when I said the hide-on-combat aura worked I tried to fix it myself, but nothing I've tried has worked.

    Right now, on combat the aura will hide the chat frame (and my minimap, as I added my other weak aura to the bottom). However, the chat from pops back up within 15ish seconds of pulling. I've included notes on the different things I did to try to diagnose the issue: it's worth noting that the minimap stays hidden until the end of combat. This happened both with and without the minimap hiding code; I tried removing the event trigger for PLAYER_REGEN_ENABLED, so that the aura would only trigger when combat started, and the chat box still quickly reappeared, meaning the issue is something that happens from the initial trigger. I also tried removing the custom untrigger, instead setting the untrigger to 1 second, but the chat box still reappeared about 15 seconds into combat. All testing was done solo in a dungeon.

    Code:
    function(event)
        local GetValue = function(...)
            if not WeakAuras.CustomValues then WeakAuras.CustomValues = {} end
            if not ... then return end
            local count, data = #{...}
            if count and (count > 1) then
                for i,v in pairs({...}) do
                    if i==1 then WeakAuras.CustomValues[v] = WeakAuras.CustomValues[v] or {} data = WeakAuras.CustomValues[v]
                    else if i ~= count then if not data[v] then data[v] = {} else data = data[v] end else data = data[v] end end
                end
            else data = WeakAuras.CustomValues[select(1, ...)] end
            return data
        end
        local SetValue = function(value, ...)
            if not WeakAuras.CustomValues then WeakAuras.CustomValues = {} end
            if not ... then return end
            local count, data = #{...}
            for i,v in pairs({...}) do
                if i==1 then if count and count == 1 then WeakAuras.CustomValues[v] = value else
                        WeakAuras.CustomValues[v] = WeakAuras.CustomValues[v] or {}
                        data = WeakAuras.CustomValues[v] end
                else if i ~= count then if not data[v] then data[v] = {} end data = data[v] else data[v] = value end end
            end
        end
        if event == 'PLAYER_REGEN_DISABLED' then
            local visibleFrames = {}    
            for count=1,NUM_CHAT_WINDOWS do 
                local window = _G["ChatFrame"..count]
                local tab =_G[('ChatFrame%sTab'):format(count)]
                if window and window:IsVisible() then
                    tinsert(visibleFrames, window:GetName())
                end
                if tab and tab:IsVisible() then
                    tinsert(visibleFrames, tab:GetName())
                end
            end
            SetValue(visibleFrames, 'CombatHiddenFrames')
        end
        
        local frames = GetValue('CombatHiddenFrames')
        for i,frame in pairs(frames) do
            if event == 'PLAYER_REGEN_DISABLED' then
                _G[frame]:Hide()
            elseif event == 'PLAYER_REGEN_ENABLED' then
                _G[frame]:Show()
            end
        end
        if event == 'PLAYER_REGEN_DISABLED' then
            Minimap:Hide()
        elseif event == 'PLAYER_REGEN_ENABLED' then
            Minimap:Show()
        end
    end

  10. #620

    Default

    Quote Originally Posted by Klik View Post
    Well, it seems I spoke too soon when I said the hide-on-combat aura worked I tried to fix it myself, but nothing I've tried has worked.

    Right now, on combat the aura will hide the chat frame (and my minimap, as I added my other weak aura to the bottom). However, the chat from pops back up within 15ish seconds of pulling. I've included notes on the different things I did to try to diagnose the issue: it's worth noting that the minimap stays hidden until the end of combat. This happened both with and without the minimap hiding code; I tried removing the event trigger for PLAYER_REGEN_ENABLED, so that the aura would only trigger when combat started, and the chat box still quickly reappeared, meaning the issue is something that happens from the initial trigger. I also tried removing the custom untrigger, instead setting the untrigger to 1 second, but the chat box still reappeared about 15 seconds into combat. All testing was done solo in a dungeon.
    Hmm, my guess is something strange when quickly entering/leaving combat, but not certain since it's difficult to reproduce.

    I think the best avenue to take is to completely eliminate the "saving" of frames based on combat, and instead move that to a non-combat event. I went with PLAYER_LOGIN, which essentially fires when you login to the game or reload your UI, but otherwise doesn't fire during normal game play. This allows us to set our frame list of hidden candidates essentially once and only once, and then only refer to that last (but never alter it) based on combat events.

    Here is the modified function you should replace your current Trigger function with:

    Code:
    function(event)
      -- BEGIN CONFIG
      local extraFrames = {
        'Minimap'
      }
      -- END CONFIG
      local GetValue = function(...)
        if not WeakAuras.CustomValues then WeakAuras.CustomValues = {} end
        if not ... then return end
        local count, data = #{...}
        if count and (count > 1) then
          for i,v in pairs({...}) do
            if i==1 then WeakAuras.CustomValues[v] = WeakAuras.CustomValues[v] or {} data = WeakAuras.CustomValues[v]
            else if i ~= count then if not data[v] then data[v] = {} else data = data[v] end else data = data[v] end end
          end
        else data = WeakAuras.CustomValues[select(1, ...)] end
        return data
      end
      local SetValue = function(value, ...)
        if not WeakAuras.CustomValues then WeakAuras.CustomValues = {} end
        if not ... then return end
        local count, data = #{...}
        for i,v in pairs({...}) do
          if i==1 then if count and count == 1 then WeakAuras.CustomValues[v] = value else
              WeakAuras.CustomValues[v] = WeakAuras.CustomValues[v] or {}
              data = WeakAuras.CustomValues[v] end
          else if i ~= count then if not data[v] then data[v] = {} end data = data[v] else data[v] = value end end
        end
      end
     
      if event == 'PLAYER_LOGIN' then
        local visibleFrames = {}    
        for count=1,NUM_CHAT_WINDOWS do
          local window = _G["ChatFrame"..count]
          local tab =_G[('ChatFrame%sTab'):format(count)]
          if window and window:IsVisible() then
            tinsert(visibleFrames, window:GetName())
          end
          if tab and tab:IsVisible() then
            tinsert(visibleFrames, tab:GetName())
          end
        end
        if extraFrames then
          for i,name in pairs(extraFrames) do
            tinsert(visibleFrames, name)
          end
        end
        SetValue(visibleFrames, 'HiddenCombatFrames')
      elseif event == 'PLAYER_REGEN_DISABLED' or event == 'PLAYER_REGEN_ENABLED' then
        local frames = GetValue('HiddenCombatFrames')
        for i,frame in pairs(frames) do
          if event == 'PLAYER_REGEN_DISABLED' then
            _G[frame]:Hide()
          elseif event == 'PLAYER_REGEN_ENABLED' then
            _G[frame]:Show()
          end
        end    
      end
    end


    Additionally, add the PLAYER_LOGIN event to the Event(s) box in the trigger, so from PLAYER_REGEN_DISABLED, PLAYER_REGEN_ENABLED to PLAYER_REGEN_DISABLED, PLAYER_REGEN_ENABLED, PLAYER_LOGIN.

    I also added a simple table at the top for you to add the names of extra frames you wish to hide (such as Minimap). Also to that end if you aren't aware already, you can type /framestack in-game to toggle a tooltip that shows the names of all frames you're currently mousing over in case you don't know what is what.

    The caveat with this method that since the frame list is created only on login/reload, you must reload your UI after making any changes to your chat frames (or list of extraFrames to hide).

    Hope that works, lemme know if you have trouble.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •