1. #1
    Deleted

    Need help fixing Lua Code

    Hey guys, dont know much about LUA, maybe someone can help me out. I am trying to track cc on my Healer, so I can easily dispel it with Blessing of Sanctuary.

    Code:
    Unitdebuff(
    	name, rank, icon, count, dispelType, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, _, nameplateShowAll, timeMod, value1, value2, value3 = UnitDebuff	("HealerNameGoesHere", index [, "filter"])
    
    		if name = "Storm Bolt" or "Shockwave" or "Intimidating Shout" or "Static Shock" or "Intimidation" or "Legsweep" or "Cheap Shot" or "Kidney Shot" or "Between the Eyes" or "Asphyxiate" or "Strangulate" or "Hammer of Justice" or "Fist of Justice" or "Mind Bomb" or "Psychic Scream" or "Fear"
    	then
    			CreateFrame("Frame","bosw",UIParent)
    			bosw:SetWidth(48)
    			bosw:Setheight(48)
    			bosw:SetPoint("CENTER",0,0)
    			bosw:CreateTexture("boswtexture")
    			boswtexture:SetAllPoint()
    			boswtexture:SetTexture("Interface\Icons\Spell_Holy_GreaterBlessingofSanctuary.blp")
    
    end

  2. #2
    Two obvious things:
    = means "set the variable to this value", not "check if variable equals this value". You need to use ==
    You are using 'or' incorrectly, its 'a==b or a==c or a==d', not 'a==b or c or d'.

    Code:
    if name == "Storm Bolt" or name =="Shockwave" or name =="Intimidating Shout" or name =="Static Shock" or name =="Intimidation" or name =="Legsweep" or name =="Cheap Shot" or name =="Kidney Shot" or name =="Between the Eyes" or name =="Asphyxiate" or name =="Strangulate" or name =="Hammer of Justice" or name =="Fist of Justice" or name =="Mind Bomb" or name =="Psychic Scream" or name =="Fear"
    BreweRyge: Adds a resource meter for Brewmaster brews, as if they were on a rage- or energy-type system.
    Hidden Artifact Tracker: Adds your progress on unlocking the extra tints for your hidden artifact appearance to the item tooltip.

  3. #3
    Deleted
    Thanks for the quick answer, however it's still not working. Anyone else able to help out ?

  4. #4
    Moderator Cilraaz's Avatar
    15+ Year Old Account
    Join Date
    Feb 2009
    Location
    PA, USA
    Posts
    10,139
    Quote Originally Posted by Fr33z4 View Post
    Thanks for the quick answer, however it's still not working. Anyone else able to help out ?
    Is the addon presenting an error of any kind?

    Also, I'm slightly confused by your quoted text block in the OP. Why does it start with "Unitdebuff("?

    Are name/rank/icon/etc declared earlier in the code? If not, you probably want to declare them as a local. Also, if you're not going to use anything other than name, you shouldn't declare the rest. It's just chewing up memory. Lastly, your filter string is not done properly and could just be ignored. It should be something like:

    Code:
    local name = UnitDebuff("HealerNameGoesHere", index)
    Based on the "index" portion of the UnitDebuff call, I'm guessing this is part of an iterative block? Really, seeing the entire code would help tremendously.

    Edit: You'd probably want this block to look more like this:

    Code:
    local index
    for index = 1, 40 do
      local name = UnitDebuff(unitid, index)
      if name == "Storm Bolt" or name == "Shockwave" or name == "Intimidating Shout" or name == "Static Shock" or name == "Intimidation" or name == "Legsweep" or name == "Cheap Shot" or name == "Kidney Shot" or name == "Between the Eyes" or name == "Asphyxiate" or name == "Strangulate" or name == "Hammer of Justice" or name == "Fist of Justice" or name == "Mind Bomb" or name == "Psychic Scream" or name == "Fear" then
        CreateFrame("Frame","bosw",UIParent)
        bosw:SetWidth(48)
        bosw:Setheight(48)
        bosw:SetPoint("CENTER",0,0)
        bosw:CreateTexture("boswtexture")
        boswtexture:SetAllPoint()
        boswtexture:SetTexture("Interface\Icons\Spell_Holy_GreaterBlessingofSanctuary.blp")
      end
    end

    Another edit: I don't think the unit call for UnitDebuff takes a unit name. I think you'd have to use a UnitID. The easiest would probably be focus, though you'd then have to set the healer as your focus target. If grouped, you could do partyx (where x is the party member number), but this could vary.

    Yet another edit: Removed the super long-hand declares that used "name, _, _, _". If just wanting the debuff name, it can just be declared as "name =".
    Last edited by Cilraaz; 2017-05-22 at 03:46 PM.

  5. #5
    Deleted
    Based on the "index" portion of the UnitDebuff call, I'm guessing this is part of an iterative block? Really, seeing the entire code would help tremendously.
    That's actually the entire block of my Code. Like I said I have no clue about any programming language.

    Is the addon presenting an error of any kind?
    Also, I'm slightly confused by your quoted text block in the OP. Why does it start with "Unitdebuff("?

    Are name/rank/icon/etc declared earlier in the code? If not, you probably want to declare them as a local. Also, if you're not going to use anything other than name, you shouldn't declare the rest. It's just chewing up memory. Lastly, your filter string is not done properly and could just be ignored. It should be something like:

    Not that I know of, is there any way to check besides the taint.log or ingame Lua errors?
    Not sure about what you meant. I just googled a way to check for debuffs and found the Unitdebuff() function on wowprogramming. Then I looked at the variables(?) that I can choose from like name, rank, icon, etc. My next step was to set the debuff name variable to the debuffs I wanted to track, hence I tried
    Code:
    if name="Debuff1" or ... then create my texture frame
    I'm not an native English speaker so I hope what I wrote makes sense.

  6. #6
    Deleted
    Not sure what happend but my answer just disappeared.

    Based on the "index" portion of the UnitDebuff call, I'm guessing this is part of an iterative block? Really, seeing the entire code would help tremendously.
    Actually that is all of my code. I have no clue about programming languages, this is only what I came up with after using Google for some help.

    Is the addon presenting an error of any kind?
    No taintlog entry or ingame errors afaik. Is there any other way to check?

    Could you please explain this part here
    Code:
     local index
    for index = 1, 40 do...
    From what I can tell is you create a local variable called index but I dont get the "for index = 1,40 do" part.
    Another edit: I don't think the unit call for UnitDebuff takes a unit name. I think you'd have to use a UnitID. The easiest would probably be focus, though you'd then have to set the healer as your focus target. If grouped, you could do partyx (where x is the party member number), but this could vary
    Sorry but I don't think that would work for me since I want to use this addon for arenas - having my healer always on focus or always as party1 would be quite the bummer.

  7. #7
    Moderator Cilraaz's Avatar
    15+ Year Old Account
    Join Date
    Feb 2009
    Location
    PA, USA
    Posts
    10,139
    Quote Originally Posted by Fr33z4 View Post
    Not sure what happend but my answer just disappeared.
    It was thrown into the moderation queue due to low post count and code sometimes appearing sketchy to the filters.

    Quote Originally Posted by Fr33z4 View Post
    No taintlog entry or ingame errors afaik. Is there any other way to check?
    Well, do you have the addon properly created? Does it have a toc file that actually loads the addon and calls this code?

    Quote Originally Posted by Fr33z4 View Post
    Could you please explain this part here
    Code:
     local index
    for index = 1, 40 do...
    From what I can tell is you create a local variable called index but I dont get the "for index = 1,40 do" part.
    The UnitDebuff call looks at a specific index to check debuff slots. This iterates the following code block (checking UnitDebuff, then checking if name is one of the listed debuffs) for each of the 40 debuff slots.

    Quote Originally Posted by Fr33z4 View Post
    Sorry but I don't think that would work for me since I want to use this addon for arenas - having my healer always on focus or always as party1 would be quite the bummer.
    Unfortuantely, there's not much choice. UnitDebuff will not accept a character name. It needs a UnitID.

    This code would also need a lot more work to be functional. There's no function call for the addon to know when to check the debuffs. There's no code to destroy the frame once the debuff is cleared. This is just a snippet of code that would be used within a much larger block. You might be better off checking Curse for an already existing addon.

  8. #8
    Deleted
    Well, do you have the addon properly created? Does it have a toc file that actually loads the addon and calls this code?
    Yup.

    Unfortuantely, there's not much choice. UnitDebuff will not accept a character name. It needs a UnitID. This code would also need a lot more work to be functional. There's no function call for the addon to know when to check the debuffs. There's no code to destroy the frame once the debuff is cleared. This is just a snippet of code that would be used within a much larger block. You might be better off checking Curse for an already existing addon.
    Oh I see. That's unfortunate. Is there any other function I could use? I already tried curse but couldn't find any addon for Blessing of Sanctuary.
    Last edited by mmoc22378e8fa7; 2017-05-22 at 04:12 PM.

  9. #9
    Quote Originally Posted by Fr33z4 View Post
    I am trying to track cc on my Healer, so I can easily dispel it with Blessing of Sanctuary.

    Wouldn't this be easier done with WeakAuras or any of the arena addons?

    Here is a proof-of-concept of your code but it's very barebones
    Code:
    local healer = "HealerNameGoesHere"
    
    local t = {
    	[107570] = true, -- Storm Bolt
    	[46968] = true, -- Shockwave
    	[5246] = true, -- Intimidating Shout
    	-- Static Shock (?)
    	[19577] = true, -- Intimidation
    	[119381] = true, -- Leg Sweep
    	[1833] = true, -- Cheap Shot
    	[408] = true, -- Kidney Shot
    	[199804] = true, -- Between the Eyes
    	[93424] = true, -- Asphyxiate
    	[47476] = true, -- Strangulate
    	[853] = true, -- Hammer of Justice
    	-- Fist of Justice (?)
    	[205369] = true, -- Mind Bomb
    	[8122] = true, -- Psychic Scream
    	[5782] = true, -- Fear
    }
    
    local f = CreateFrame("Frame")
    f:SetPoint("CENTER")
    f:SetSize(48, 48)
    
    local tex = f:CreateTexture()
    tex:SetAllPoints(f)
    
    local function OnEvent(self, event, ...)
    	local timestamp, subevent, _, sourceGUID, sourceName, _, _, destGUID, destName, _, _, spellID, spellName = ...
    	if subevent == "SPELL_AURA_APPLIED" then
    		if strfind(destName, healer) and t[spellID] then
    			local icon = select(3, GetSpellInfo(spellID))
    			tex:SetTexture(icon)
    		end
    	end
    end
    
    f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    f:SetScript("OnEvent", OnEvent)

    You can get more help on WoWInterface if you post your full code there
    Last edited by Ketho; 2017-05-22 at 05:15 PM.

  10. #10
    Moderator Cilraaz's Avatar
    15+ Year Old Account
    Join Date
    Feb 2009
    Location
    PA, USA
    Posts
    10,139
    Quote Originally Posted by Fr33z4 View Post
    Oh I see. That's unfortunate. Is there any other function I could use? I already tried curse but couldn't find any addon for Blessing of Sanctuary.
    No, UnitDebuff would be the only function to check a unit's debuffs. You could add a for loop that checks party1 through party4 and sees if that unit name matches the healer's name, then launch into the debuff check. This would cycle through each party member, and if the party member's name matches the healer's name, cycle through debuffs looking for the listed debuffs.

    This still comes back to the issue that no event is being checked that would tell the addon to run through this code. As coded, it would check once when the addon loads, then never again. You would have to register an event so it knows when to check. You could do something like:

    Code:
    function OnLoad()
      this:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    end
    
    function OnEvent(self, event, ...)
      local healerName = "HealersName"
      local bosw = bosw or CreateFrame("Frame","bosw",UIParent)
      bosw:SetWidth(48)
      bosw:Setheight(48)
      bosw:SetPoint("CENTER",0,0)
      bosw:CreateTexture("boswtexture")
      boswtexture:SetAllPoint()
      boswtexture:SetTexture("Interface\Icons\Spell_Holy_GreaterBlessingofSanctuary.blp")
      bosw:Hide()
      local type = select(2, ...)
      if event == "COMBAT_LOG_EVENT_UNFILTERED" then
        if type == "SPELL_AURA_APPLIED" then
          local spellTarget = select(9, ...)
          if spellTarget == healerName then
            local spellId, spellName, spellSchool = select(12, ...)
            if spellName == "Storm Bolt" or spellName == "Shockwave" or spellName == "Intimidating Shout" or spellName == "Static Shock" or spellName == "Intimidation" or spellName == "Legsweep" or spellName == "Cheap Shot" or spellName == "Kidney Shot" or spellName == "Between the Eyes" or spellName == "Asphyxiate" or spellName == "Strangulate" or spellName == "Hammer of Justice" or spellName == "Fist of Justice" or spellName == "Mind Bomb" or spellName == "Psychic Scream" or spellName == "Fear" then
              bosw:Show()
            end
          end
        end
        if type == "SPELL_DISPEL" then
          local spellTarget = select(9, ...)
          if spellTarget == healerName then
            local spellId, spellName, spellSchool = select(12, ...)
            if spellName == "Storm Bolt" or spellName == "Shockwave" or spellName == "Intimidating Shout" or spellName == "Static Shock" or spellName == "Intimidation" or spellName == "Legsweep" or spellName == "Cheap Shot" or spellName == "Kidney Shot" or spellName == "Between the Eyes" or spellName == "Asphyxiate" or spellName == "Strangulate" or spellName == "Hammer of Justice" or spellName == "Fist of Justice" or spellName == "Mind Bomb" or spellName == "Psychic Scream" or spellName == "Fear" then
              bosw:Hide()
            end
          end
        end
      end
    end

    You can see if this works. If not, you might have an easier time making a weak aura that checks for certain debuffs on arena teammates.

    Edit: Ketho's code is nicer than mine. Use theirs as a base instead, lol.

  11. #11
    Deleted
    As some of the posters above note..

    1) you need to iterate over the index in order to get all debuffs.

    2) If you only need name, then it isnt needed to assign every value the function returns.
    Example:

    local name, _ , _ , _ , dispeltype = UnitDebuff(unitname,index)

    would assign only name and dispeltype as local variables on the 'index'd debuff on the unit refered to in variable unitname. if no such debuff exist, name would equal nil.

    3) NEVER create frames in code intended to be iterated over continously. Instead, create frame once, store a reference, and use that reference.

    4) Remember to NOT overwrite a search-result by later non-debuff (as a for-loop well may do). A break or resultstore in the loop is needed at the point of discovery.

    5) Remember to DO overwrite a previous searchresult, if you cant find one in the most resent iteration. Otherwise your Icon/alert simply wont clear.

    6) Remember to test for nil before testing with using it as an index ; E.g. (name and spells[name]). otherwise your addon can crash and you have to reload.

    7) design choice: Using a timed event instead of combat_log events has the benefit that it ALWAYS will run only e.g. 5 times per second, instead of 100 of times per second in a hectic combat situation. The calculations needed is hence constant throughout time. But this is up to you. If you decide to use combat_log events, then you MUST make the initial called filter function small and the conditions sensible. Remember it will run on EVERY matched event.


    I can give you a (hopefully -- untested) working example (with reservation for typos).. you need to complete the spells to look for and frame appearance yourself. Remember that you'll also need a toc file. Load it up in e.g. notepad++, to edit it, and you can ofc remove as much of the comments as you'd like.

    Code:
    -- ////////////////////////////////////////////////////////////////////////////////////////////////// --
    
    -- using aceaddon for simple timer use
    local your_addon_namespace = LibStub( "AceAddon-3.0" ):NewAddon( "your_addon_namespace", "AceTimer-3.0", "AceEvent-3.0")
    
    -- 'global' variables in your namespace/contained variable; values set here, set in a function or read from file etc.
    -- only have one place where you enter fixed values, here in the top of the file; VERY easy to find and update
    local mod					= {}										-- mod variables
    mod.updateinterval 			= 0.2										-- seconds between updates
    mod.location 				= {["x"]=802,["y"]=-875}						-- top left corner
    mod.size					= {["width"]=600,["height"]=400}				-- mod size
    
    local settings 				= {}										-- settings
    settings.your_spells 			= {["Storm Bolt"] = true, ["Shockwave"] = 388 } 	-- your spell names stored as keys. values if you want to store and process any information
    settings.your_frame			= nil
    settings.your_unit 			= "unitreference"							-- use "player" for self. use "partyX" and "raidX" for other targets.
    																-- these can be programmatically found through UnitName() and a conversion table.
    
    local frame_settings			= {}
    frame_settings.width			= 48
    frame_settings.height			= 48
    frame_settings.valueifset		= 5
    frame_settings.valueifclear		= 0
    frame_settings.texture		= "Interface\Icons\Spell_Holy_GreaterBlessingofSanctuary.blp"
    -- ... your other settings
    
    -- ////////////////////////////////////////////////////////////////////////////////////////////////// --
    
    local your_main_addon_frame = CreateFrame("frame",nil,UIParent) -- your addon main frame
    -- this will allow you to position all of your addons subframes, images, text and elements
    
    your_main_addon_frame:SetPoint("TOPLEFT", mod.location.x , mod.location.y)
    your_main_addon_frame:SetWidth(mod.size.width)
    your_main_addon_frame:SetHeight(mod.size.height)
    your_main_addon_frame:SetBackdrop(nil)
    
    -- ////////////////////////////////////////////////////////////////////////////////////////////////// --
    
    -- initialize function, called once in the start
    function your_addon_namespace:initialize_function()
    
    	if settings.your_frame == nil then
    		-- prevent recreation of frames, in case of unexpected code behavior
    	
    		local f = CreateFrame("frame", nil, your_main_addon_frame )
    		-- no need to name it if you store references
    		-- the parent to this frame is your addon mainframe
    
    		f:SetWidth(frame_settings.width)
    		f:SetHeight(frame_settings.height)
    		--... your other stuff
    		--... position in reference to specified addon_mainframe point
    
    		local t = f:CreateTexture(nil)
    		t:SetAllPoints()
    		t:SetTexture(frame_settings.texture)
    
    		settings.your_frame = f
    	end
    end
    
    -- function to call continously, like every 0.2 second
    function your_addon_namespace:debuff_function()
    
    	-- local aliases and references to improve readability and execution speeds
    	local unit			= settings.your_unit		-- local alias
    	local spells			= settings.your_spells		-- local alias
    	local f			= settings.your_frame		-- local alias
    
    	-- prepare result storage
    	local found_spell	= nil
    
    	-- iterator function
    	-- NOTE: not efficient to use for-loop, as even though only 40 index values makes sense in UnitDebuff result, its no point in doing 40 iterations if you only have like 3 spells
    	local index = 1
    	while true do
    
    		local name = UnitDebuff(unit,index)	-- just get name
    
    		if (not name) then break end		-- jump out of the whileloop if you cant find a name
    
    		if spells[name] then				-- only run if name != nil and name exists in spell table and hence not return nil
    			found_spell = name			-- store result
    			break					-- a spell has been found, no need to search any more, and breaks repeat. index contains spell index if you need more processing.
    		end
    
    		index = index + 1				-- move to next debuff's index
    	end
    
    	-- evaluate results
    	if (found_spell) then
    		f:Show()
    		f:SetValue(frame_settings.valueifset)
    		--... your other stuff
    	else
    		f:Hide()				-- important to negate previously found spells, if you cant find any this run
    		f:SetValue(frame_settings.valueifclear)
    	end	
    end
    
    -- ////////////////////////////////////////////////////////////////////////////////////////////////// --
    
    -- initialize function
    function your_addon_namespace:OnEnable()
    
    	your_addon_namespace:initialize_function()		-- create frames
    	your_addon_namespace:debuff_function()		-- its up to you if you want to run checks now, or wait for first timer
    
    	your_addon_namespace.updateTimer = self:ScheduleRepeatingTimer("debuff_function", mod.updateinterval)
    
    	DEFAULT_CHAT_FRAME:AddMessage("Your awsome addon is loaded")
    end
    
    
    -- ////////////////////////////////////////////////////////////////////////////////////////////////// --

  12. #12
    Deleted
    Thanks for the amazing help guys, really appreciate it!

    I'll have to wait till tomorrow to try out your solutions, but from what I have gathered a nice and clean way would be to combine Weakauras with Ketho's Code.

    So I'd have to create a custom trigger with this part
    Code:
    local t = {
    	[107570] = true, -- Storm Bolt
    	[46968] = true, -- Shockwave
    	[5246] = true, -- Intimidating Shout
    	-- Static Shock (?) Capacitator Totem
    	[19577] = true, -- Intimidation
    	[119381] = true, -- Leg Sweep
    	[1833] = true, -- Cheap Shot
    	[408] = true, -- Kidney Shot
    	[199804] = true, -- Between the Eyes
    	[93424] = true, -- Asphyxiate
    	[47476] = true, -- Strangulate
    	[853] = true, -- Hammer of Justice
    	-- Fist of Justice (?) (probably has no ID since it's a modified version of Hammer of Justice
    	[205369] = true, -- Mind Bomb
    	[8122] = true, -- Psychic Scream
    	[5782] = true, -- Fear
    }
    And let the Weakaura check for these spells if "SPELL_AURA_APPLIED" is on my Healer

Posting Permissions

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