WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   General Authoring Discussion (https://www.wowinterface.com/forums/forumdisplay.php?f=20)
-   -   Why this addon action is blocked? (https://www.wowinterface.com/forums/showthread.php?t=52484)

alikim 07-09-15 09:48 PM

Why this addon action is blocked?
 
Hi,

I'm writing an addon that disables ExtraActionBarFrame and creates my own frame to use instead.

Code:

PLBARS[10*9+6] - stores a flag to switch between custom and default bars
xRef[9][1]  - my custom frame, "ExtraBarFrame"
xRef[9][2] - texture of xRef[9][1]
xRef[9][3] - secure template button, child of xRef[9][1], "ExtraBarFrameButton"
xRef[9][4] - texture of xRef[9][3]

This is the function that is called on UPDATE_EXTRA_ACTIONBAR:

local function setExtraBar()
        if PLBARS[10*9+6] == 1 then
                xRef[9][1]:Show()
                ExtraActionBarFrame.button:Hide()

                local EABF = ExtraActionBarFrame
                local tex = EABF.button.icon:GetTexture()
                if not HasExtraActionBar() then
                        xRef[9][3]:Hide()
                        xRef[9][2]:SetTexture(unpack(PLBARS[10*9 + 5]))
                else
                        if tex ~= nil then xRef[9][4]:SetTexture(tex) end
                        xRef[9][3]:Show()
                        xRef[9][2]:SetTexture(unpack(barColor["EXTRA"]))
                end
   
        else
                xRef[9][1]:Hide()
                ExtraActionBarFrame.button:Show()
        end
end

Everything works just fine except sometimes when I throw an extra bar item while in combat I have a message that interface action failed because of the addon and my custom secure button is not being hidden.

This is what taint.log says:

Code:

7/10 13:23:52.412  ActionButton_UpdateFlyout()
7/10 13:23:52.412  An action was blocked in combat because of taint from PlayerBars - ExtraBarFrame:Show()
7/10 13:23:52.412      Interface\AddOns\PlayerBars\main.lua:163 setExtraBar()
7/10 13:23:52.412      Interface\AddOns\PlayerBars\main.lua:421
7/10 13:23:52.412  ActionButton_UpdateFlyout()
7/10 13:23:52.412  An action was blocked in combat because of taint from PlayerBars - ExtraActionButton1:Hide()
7/10 13:23:52.412      Interface\AddOns\PlayerBars\main.lua:164 setExtraBar()
7/10 13:23:52.412      Interface\AddOns\PlayerBars\main.lua:421
7/10 13:23:52.412  ActionButton_UpdateFlyout()
7/10 13:23:52.412  An action was blocked in combat because of taint from PlayerBars - ExtraBarFrameButton:Hide()
7/10 13:23:52.412      Interface\AddOns\PlayerBars\main.lua:169 setExtraBar()
7/10 13:23:52.412      Interface\AddOns\PlayerBars\main.lua:421

Can anyone help me to figure out how to fix this?

Thanks,

rowaasr13 07-10-15 04:33 AM

That's obviously because you can't do anything with secure buttons in combat. It is the vary basis of their design: you get access to limited set of secure functions under scheme that prevents you to reprogram it on-the-fly in the combat and thus achieve automation.

alikim 07-10-15 05:51 AM

Quote:

Originally Posted by rowaasr13 (Post 309717)
That's obviously because you can't do anything with secure buttons in combat. It is the vary basis of their design: you get access to limited set of secure functions under scheme that prevents you to reprogram it on-the-fly in the combat and thus achieve automation.

I can make a secure button that casts a spell during combat, so why can't I make a secure button that throws a grenade during combat? I'm not reprogramming it, I just show or hide it.

Anyway, then how do I make my own version of the ExtraActionBar functionality?

rowaasr13 07-10-15 06:12 AM

Quote:

Originally Posted by alikim (Post 309718)
I can make a secure button that casts a spell during combat, so why can't I make a secure button that throws a grenade during combat? I'm not reprogramming it, I just show or hide it.
Anyway, then how do I make my own version of the ExtraActionBar functionality?

No, you're reprogramming it - you're altering its state by and how mouse would interract with it by hiding. Just imagine having buttons for ALL your spells stacked in one position spell and you dynamically hide all of them except one with best combat spell for current situation and here you'd have your mini-combat bot based on clicking the same spot on screen. You cannot alter SECURE frame from insecure code in combat, period. That's the point of entire system.

I can't remember from top of my head, but you might have some success with doing that from inside secure environment itself where you don't have functions that'd let you check combat status - i.e. your button can have secure script to always hide itself right after click.

You can have secure button to throw item in combat - it's pretty much same as spell button, but you won't be able to react to environment changes - e.g. leaving zone that gave you extra action - while in combat. The most you can do is to note relevant changes from events, save them somewhere and do actual modification after PLAYER_REGEN_ENABLED is fired.

You can't duplicate EAB functionality completely because it can change action or appear/disappear in middle in combat. This can only be done from secure Blizzard's code.

alikim 07-10-15 06:23 AM

Quote:

Originally Posted by rowaasr13 (Post 309719)
No, you're reprogramming it - you're altering its state by and how mouse would interract with it by hiding. Just imagine having buttons for ALL your spells stacked in one position spell and you dynamically hide all of them except one with best combat spell for current situation and here you'd have your mini-combat bot based on clicking the same spot on screen. You cannot alter SECURE frame from insecure code in combat, period. That's the point of entire system.

I can't remember from top of my head, but you might have some success with doing that from inside secure environment itself where you don't have functions that'd let you check combat status - i.e. your button can have secure script to always hide itself right after click.

You can have secure button to throw item in combat - it's pretty much same as spell button, but you won't be able to react to environment changes - e.g. leaving zone that gave you extra action - while in combat. The most you can do is to note relevant changes from events, save them somewhere and do actual modification after PLAYER_REGEN_ENABLED is fired.

You can't duplicate EAB functionality completely because it can change action or appear/disappear in middle in combat. This can only be done from secure Blizzard's code.

mmm... do you mean to create a hooksecurefunc on some original button call to turn off my button?

alikim 07-10-15 10:46 AM

Quote:

Originally Posted by rowaasr13 (Post 309719)
...your button can have secure script to always hide itself right after click...

I mean how do you do this?

Lombra 07-11-15 12:59 PM

I actually started to make this some time ago. I think it should work, but I never really bothered finishing it. Not sure if it's of any use to you. I never implemented hiding the default frame it seems. Most of it is copied from the UI source.

Code:

local items = {
        [19183] = true, -- Hourglass Sand
        [24494] = true, -- Tears of the Goddess
        [46029] = true, -- Magnetic Core
}

local bar = ExtraActionBarFrame

local button = CreateFrame("CheckButton", "ExtraExtraActionButton", ExtraActionBarFrame, "ExtraActionButtonTemplate")
button:SetPoint("CENTER")
button:SetAttribute("type", "item")
button.style:SetTexture("Interface\\ExtraButton\\Default")

function button:SetItem(itemID)
        bar:Show()
        bar.outro:Stop()
        bar.intro:Play()
       
        self:SetAttribute("item", "item:"..itemID)
        self.item = itemID
        self.icon:SetTexture(GetItemIcon(itemID))
end

button:RegisterEvent("BAG_UPDATE_COOLDOWN")
button:RegisterEvent("BAG_UPDATE")
button:RegisterEvent("SPELL_UPDATE_USABLE")
button:RegisterEvent("SPELL_UPDATE_COOLDOWN")
button:RegisterEvent("CURRENT_SPELL_CAST_CHANGED")

button:SetScript("OnAttributeChanged", function(self, name, value)
        -- if name == "item" then
                -- self.item = value
        -- end
end)

button:SetScript("OnEvent", function(self)
        local item = self.item
        if not item then return end
        local start, duration, enable = GetItemCooldown(item)
        CooldownFrame_SetTimer(self.cooldown, start, duration, enable)
        if (not item or duration > 0 and enable == 0) then
                self.icon:SetVertexColor(0.4, 0.4, 0.4)
        else
                self.icon:SetVertexColor(1, 1, 1)
        end
       
        self.icon:SetDesaturated(false)
       
        if (GameTooltip:GetOwner() == self) then
                GameTooltip:SetInventoryItemByID(self.item)
        end
end)

button:SetScript("OnEnter", function(self)
        if GetCVar("UberTooltips") == "1" then
                GameTooltip_SetDefaultAnchor(GameTooltip, self)
        else
                local parent = self:GetParent()
                if parent == MultiBarBottomRight or parent == MultiBarRight or parent == MultiBarLeft then
                        GameTooltip:SetOwner(self, "ANCHOR_LEFT")
                else
                        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
                end
        end
        if GameTooltip:SetInventoryItemByID(self.item) then
                -- self.UpdateTooltip = ActionButton_SetTooltip
        -- else
                -- self.UpdateTooltip = nil
        end
end)

button:SetScript("OnUpdate", function(self, elapsed)
        if ( ActionButton_IsFlashing(self) ) then
                local flashtime = self.flashtime;
                flashtime = flashtime - elapsed;
               
                if ( flashtime <= 0 ) then
                        local overtime = -flashtime;
                        if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
                                overtime = 0;
                        end
                        flashtime = ATTACK_BUTTON_FLASH_TIME - overtime;

                        local flashTexture = _G[self:GetName().."Flash"];
                        if ( flashTexture:IsShown() ) then
                                flashTexture:Hide();
                        else
                                flashTexture:Show();
                        end
                end
               
                self.flashtime = flashtime;
        end
       
        -- Handle range indicator
        local rangeTimer = self.rangeTimer
        if rangeTimer then
                rangeTimer = rangeTimer - elapsed

                if rangeTimer <= 0 then
                        local count = _G[self:GetName().."HotKey"]
                        local valid = IsItemInRange(self.item)
                        if count:GetText() == RANGE_INDICATOR then
                                if valid == 0 then
                                        count:Show()
                                        count:SetVertexColor(1.0, 0.1, 0.1)
                                elseif valid == 1 then
                                        count:Show()
                                        count:SetVertexColor(0.6, 0.6, 0.6)
                                else
                                        count:Hide()
                                end
                        else
                                if valid == 0 then
                                        count:SetVertexColor(1.0, 0.1, 0.1)
                                else
                                        count:SetVertexColor(0.6, 0.6, 0.6)
                                end
                        end
                        rangeTimer = TOOLTIP_UPDATE_TIME
                end
               
                self.rangeTimer = rangeTimer
        end
end)


rowaasr13 07-13-15 04:51 AM

Quote:

Originally Posted by alikim (Post 309722)
I mean how do you do this?

Check docs for SecureHandlerWrapScript.

sezz 07-16-15 09:56 AM

Quote:

Originally Posted by alikim (Post 309722)
I mean how do you do this?

this is what I'm using for my profession cds, not sure if it's the right way but it works and doesn't taint ;)

Code:

                button:WrapScript(button, "PreClick", [[
                        if (button == "RightButton") then
                                -- Hide
                                self:SetID(0);
                                self:SetAttribute("userhidden", true);
                                self:SetAttribute("macrotext", nil);
                                self:Hide();

                                -- Update Anchors
                                self:GetParent():RunAttribute("UpdateChildAnchors");
                        elseif (button == "MiddleButton") then
                                -- Toggle Profession
                                self:SetAttribute("macrotext", self:GetAttribute("macrotext-profession"));
                        else
                                -- Create Profession Cooldown Item
                                self:SetAttribute("macrotext", self:GetAttribute("macrotext-tradeskill"));
                        end
                ]]);


btw, why don't you just reskin the original button instead?


All times are GMT -6. The time now is 04:42 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI