1. #1
    Old God Kujako's Avatar
    Join Date
    Oct 2009
    Location
    In the woods, doing what bears do.
    Posts
    10,757

    Help with LUA errors.

    I seem to be getting some LUA errors from a little custom add-on of mine. Specifically, I am getting errors such as 'tried to call the protected function "PartyMemberFrame1:SetAttribute()"' and 'tried to call the protected function "PartyMemberFrame1PetFrame:SetAttribute()"'. It seems to be from the following code, which just flashes a frame when rage is more then 60. I can think of no reason it should be looking at the party frame...

    Code:
    local f = CreateFrame("Frame","rageFrame",WorldFrame);
    f:SetFrameStrata("BACKGROUND");
    f:SetClampedToScreen(true)
    f:SetAllPoints(UIParent)
    local t = f:CreateTexture(nil,"BACKGROUND");
    t:SetTexture("Interface\\AddOns\\TankScripts\\Textures\\rage.tga"); --Interface\\FullScreenTextures\\LowHealth Interface\\FullScreenTextures\\OutofControl
    t:SetAlpha(0.5);
    t:SetBlendMode("ADD");
    t:SetVertexColor(1, 0.1, 0.1);
    t:SetAllPoints(frame);
    f.texture = t;
    f:SetPoint("CENTER",0,0);
    f:Hide();
    Code:
    function MyAddon_OnEvent(self, event, unitID, ...)
        if (unitID == "player") then    
            if (event=="UNIT_POWER") then
                if(UnitPowerType("player")==1 and TS_SAVAGE=="on") then
                    if(UnitPower("player")>=60) then
                        if (UIFrameIsFlashing(f)) then
                        --    f.fadeInTime = 0.4;
                        --    f.fadeOutTime = 0.6;
                        --    f.flashInHoldTime = 1;
                        else
                            UIFrameFlash(f, 0.5, 0.5, -1);
                        end
                    else
                        if (UIFrameIsFlashing(f)) then
                            UIFrameFlashStop(f);
                        end
                    end
                else
                    if (UIFrameIsFlashing(f)) then
                        UIFrameFlashStop(f);
                    end
                end
    ...
    Last edited by Kujako; 2013-10-24 at 08:31 PM.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  2. #2
    Using UIFrameFlash is known to cause taints. In other words, don't use it.
    UI & AddOns expert | Interface & Macros moderator - My work

  3. #3
    Old God Kujako's Avatar
    Join Date
    Oct 2009
    Location
    In the woods, doing what bears do.
    Posts
    10,757
    Quote Originally Posted by Treeston View Post
    Using UIFrameFlash is known to cause taints. In other words, don't use it.
    What's the alternative?
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  4. #4
    The Patient Crudor's Avatar
    Join Date
    Nov 2011
    Location
    Berlin
    Posts
    217
    Quote Originally Posted by Kujako View Post
    What's the alternative?
    http://forums.wowace.com/showthread.php?t=20397

  5. #5
    Old God Kujako's Avatar
    Join Date
    Oct 2009
    Location
    In the woods, doing what bears do.
    Posts
    10,757
    Yea... I've been through that thread before. It comes close, but doesn't really offer equivalent functionality. But I guess it's a place to start.

    - - - Updated - - -

    So following that thread, I end up with this....

    frame definition with animation
    Code:
    local f = CreateFrame("Frame","rageFrame",WorldFrame);
    f:SetFrameStrata("BACKGROUND");
    f:SetClampedToScreen(true)
    f:SetAllPoints(UIParent)
    local t = f:CreateTexture(nil,"BACKGROUND");
    t:SetTexture("Interface\\AddOns\\TankScripts\\Textures\\rage.tga"); --Interface\\FullScreenTextures\\LowHealth Interface\\FullScreenTextures\\OutofControl
    t:SetAlpha(0.5);
    t:SetBlendMode("ADD");
    t:SetVertexColor(1, 0.1, 0.1);
    t:SetAllPoints(frame);
    f.texture = t;
    f:SetPoint("CENTER",0,0);
    f:Hide();
    
    local flasher = f:CreateAnimationGroup()
    local fade1 = flasher:CreateAnimation("Alpha")
    fade1:SetDuration(0.5)
    fade1:SetChange(1)
    fade1:SetOrder(1)
    
    local fade2 = flasher:CreateAnimation("Alpha")
    fade2:SetDuration(0.5)
    fade2:SetChange(-1)
    fade2:SetOrder(2)
    new event handler without UIFlashFrame
    Code:
    function MyAddon_OnEvent(self, event, unitID, ...)
        if (unitID == "player") then    
            if (event=="UNIT_POWER") then
                if(UnitPowerType("player")==1 and TS_SAVAGE=="on") then
                    if(UnitPower("player")>=60) then
                        if (flasher:IsPlaying()==false) then
                            f:Show();
                            flasher:Play();
                        end
                    else
                        flasher:stop();f:Hide();
                    end
                else
                    flasher:stop();f:Hide();
                end
    ...
    Animation is not as smooth as it was, but I can tweak it as I go. Won't be sure this addresses the errors for awhile however as they only happen in groups with pets I think.
    Last edited by Kujako; 2013-10-24 at 10:51 PM.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  6. #6
    Old God Kujako's Avatar
    Join Date
    Oct 2009
    Location
    In the woods, doing what bears do.
    Posts
    10,757
    Turns out the major issue I was having was with the frame name.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  7. #7
    To prevent such a thing you can make use of sth.

    Code:
    local addonName, ns = ...
    local UIP = UIParent
    
    local frame = CreateFrame("Frame", addonName.."MainFrame", UIP)
    --use $parent to prepend the parent frame name
    local subFrame = CreateFrame("Frame", "$parentChild", frame)
    --or just keep using addonName and frame specific names
    local subFrame2 = CreateFrame("Frame", addonName.."AnotherChildFrame", frame)
    --print
    print(frame:GetName())
    print(subFrame:GetName())
    print(subFrame2:GetName())
    Using addonName as part of the frame name keeps your frame names unique which is important. $parent makes frame naming easier.
    Last edited by zorker; 2013-10-29 at 08:58 AM.
    | Simple is beautiful.
    | Roth UI | Roth UI FAQ | Github | Zork (WoW) | Zork (D3) | TDMOG

    "I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

  8. #8
    Old God Kujako's Avatar
    Join Date
    Oct 2009
    Location
    In the woods, doing what bears do.
    Posts
    10,757
    Quote Originally Posted by zorker View Post
    Using addonName as part of the frame name keeps your frame names unique which is important. $parent makes frame naming easier.
    That's more or less what I did, but I added an underscore between the addon and frame names.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  9. #9
    you can just copy the UIFrameFlash function from blizzards code to make a localized version of it so you dont taint the official one. i use this in my own addon and i have never had any taints since:

    Code:
    local frameFlashManager = CreateFrame("FRAME");
     
    local FLASHFRAMES = {};
    local UIFrameFlashTimers = {};
    local UIFrameFlashTimerRefCount = {};
    
    -- Function to see if a frame is already flashing
    local function UIFrameIsFlashing(frame)
        for index, value in pairs(FLASHFRAMES) do
            if ( value == frame ) then
                return 1;
            end
        end
        return nil;
    end
    
    -- Function to stop flashing
    local function UIFrameFlashStop(frame)
        tDeleteItem(FLASHFRAMES, frame);
        frame:SetAlpha(1.0);
        frame.flashTimer = nil;
        if (frame.syncId) then
            UIFrameFlashTimerRefCount[frame.syncId] = UIFrameFlashTimerRefCount[frame.syncId]-1;
            if (UIFrameFlashTimerRefCount[frame.syncId] == 0) then
                UIFrameFlashTimers[frame.syncId] = nil;
                UIFrameFlashTimerRefCount[frame.syncId] = nil;
            end
            frame.syncId = nil;
        end
        if ( frame.showWhenDone ) then
            frame:Show();
        else
            frame:Hide();
        end
    end
    
    -- Called every frame to update flashing frames
    local function UIFrameFlash_OnUpdate(self, elapsed)
        local frame;
        local index = #FLASHFRAMES;
         
        -- Update timers for all synced frames
        for syncId, timer in pairs(UIFrameFlashTimers) do
            UIFrameFlashTimers[syncId] = timer + elapsed;
        end
         
        while FLASHFRAMES[index] do
            frame = FLASHFRAMES[index];
            frame.flashTimer = frame.flashTimer + elapsed;
     
            if ( (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
                UIFrameFlashStop(frame);
            else
                local flashTime = frame.flashTimer;
                local alpha;
                 
                if (frame.syncId) then
                    flashTime = UIFrameFlashTimers[frame.syncId];
                end
                 
                flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0));
                if (flashTime < frame.fadeInTime) then
                    alpha = flashTime/frame.fadeInTime;
                elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)) then
                    alpha = 1;
                elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime) then
                    alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime);
                else
                    alpha = 0;
                end
                 
                frame:SetAlpha(alpha);
                frame:Show();
            end
             
            -- Loop in reverse so that removing frames is safe
            index = index - 1;
        end
         
        if ( #FLASHFRAMES == 0 ) then
            self:SetScript("OnUpdate", nil);
        end
    end
     
    -- Function to start a frame flashing
    local function UIFrameFlash(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
        if ( frame ) then
            local index = 1;
            -- If frame is already set to flash then return
            while FLASHFRAMES[index] do
                if ( FLASHFRAMES[index] == frame ) then
                    return;
                end
                index = index + 1;
            end
     
            if (syncId) then
                frame.syncId = syncId;
                if (UIFrameFlashTimers[syncId] == nil) then
                    UIFrameFlashTimers[syncId] = 0;
                    UIFrameFlashTimerRefCount[syncId] = 0;
                end
                UIFrameFlashTimerRefCount[syncId] = UIFrameFlashTimerRefCount[syncId]+1;
            else
                frame.syncId = nil;
            end
             
            -- Time it takes to fade in a flashing frame
            frame.fadeInTime = fadeInTime;
            -- Time it takes to fade out a flashing frame
            frame.fadeOutTime = fadeOutTime;
            -- How long to keep the frame flashing
            frame.flashDuration = flashDuration;
            -- Show the flashing frame when the fadeOutTime has passed
            frame.showWhenDone = showWhenDone;
            -- Internal timer
            frame.flashTimer = 0;
            -- How long to hold the faded in state
            frame.flashInHoldTime = flashInHoldTime;
            -- How long to hold the faded out state
            frame.flashOutHoldTime = flashOutHoldTime;
             
            tinsert(FLASHFRAMES, frame);
             
            frameFlashManager:SetScript("OnUpdate", UIFrameFlash_OnUpdate);
        end
    end
    just stick it before all your main code



    AddOn Author of: SpellNotReadyYet, Rune of Powa

Posting Permissions

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