WoWInterface (
-   Lua/XML Help (
-   -   WorldMapFrame Tainting (Not Green Maps) (

Clamsoda 12-10-12 12:26 AM

WorldMapFrame Tainting (Not Green Maps)
Good evening everyone,

I have been working on a lightweight AddOn to perform some fairly simple modifications to the WorldMapFrame. I am running into issues with the WorldMapFrame tainting when it is opened in combat. I attempted to code my AddOn in such a way that the map won't be touched until combat is dropped, but it is still tainting. Would you guys look over my code and give me some advice?

Lua Code:
  1. -- Local definitions
  2. local hooksecurefunc = hooksecurefunc -- I don't know if this acctually helps, I just want to be cool =[
  3. local mapScale = 0.60 -- Map scale for easy modification
  5. -- Nevcariel's function for fixing the scale of dropdown menus parented to the WorldMapFrame.
  6. local function dropdownScaleFix(self)
  7.     ToggleDropDownMenu(nil, nil, self:GetParent())
  8.     DropDownList1:SetScale(mapScale)
  9. end
  11. local function onShow()
  12.     WorldMapFrame:SetScale(mapScale)
  13. end
  15. local function sizeDown()
  16.     WorldMap_ToggleSizeUp()
  17. end
  19. local function sizeUp()
  20.     WorldMapFrame:SetAttribute("UIPanelLayout-area", "center")
  21.     BlackoutWorld:Hide()
  22.     WorldMapFrame:EnableKeyboard(false)
  23.     WorldMapFrame:EnableMouse(false)
  24. end
  26. local function modifyMap()
  27.     if eventHandler then eventHandler:UnregisterEvent("PLAYER_REGEN_ENABLED") end
  29.     WorldMap_ToggleSizeUp()
  31.     UIPanelWindows["WorldMapFrame"] = {area = "center", pushable = 9}
  32.     hooksecurefunc(WorldMapFrame, "Show", onShow)
  33.     hooksecurefunc("WorldMap_ToggleSizeDown", sizeDown)
  34.     hooksecurefunc("WorldMap_ToggleSizeUp", sizeUp)
  35.     WorldMapContinentDropDownButton:SetScript("OnClick", dropdownScaleFix)
  36.     WorldMapZoneDropDownButton:SetScript("OnClick", dropdownScaleFix)
  37. end
  39. -- Perhaps a workaround to players opening the map in combat?  Who knows.
  40. do
  41.     if not InCombatLockdown() then
  42.         modifyMap()
  43.     else
  44.         local eventHandler = CreateFrame("Frame")
  45.         eventHandler:SetScript("OnEvent", modifyMap)
  46.         eventHandler:RegisterEvent("PLAYER_REGEN_ENABLED")
  47.     end
  48. end

Also, the
Lua Code:
  1. local eventHandler = CreateFrame("Frame")
  2. eventHandler:SetScript("OnEvent", modifyMap)
block of code only works when I create the frame and set the script outside of the ELSE condition in the IF statement. I can't conditionally create the frame?

I am generally at a loss of what to do. The map acts so quirky, and I feel like some of the code is pretty hacked up. Any advice would be most appreciated, as usual.

Thanks so much!

Phanx 12-10-12 01:20 AM


Originally Posted by Clamsoda (Post 270470)

        if not InCombatLockdown() then
                local eventHandler = CreateFrame("Frame")
                eventHandler:SetScript("OnEvent", modifyMap)

... I can't conditionally create the frame?

You can, but here's the thing -- that block of code is only read and executed once, when your addon loads. Since you are never considered InCombatLockdown() when your addon's files are first being read and executed, your code is modifying the map once, and never creating a frame.

You should just be able to call the modifyMap function in the main chunk, instead of that whole do-end block at the end of your code (containing the above) since, again, InCombatLockdown() is never true when non-LoD addons are initially read.

Also, upvaluing hooksecurefunc is pointless. The purpose of upvaluing global functions is to speed up access time, but the speed-up is so minute that it's only useful for functions that are potentially called hundreds of times per second inside an OnUpdate handler or COMBAT_LOG_EVENT_UNFILTERED event handler. For a function that you call once or twice during the loading process, the upvalue is just a (granted, minute) waste of disk space and memory.

As for the taint problem, I don't really know, but my first guess would be related to the dropdown menu stuff, since the dropdown menu system is basically a house of cards in a dark basement. Try using a secure post-hook instead:


local function dropdownScaleFix(self)
-  ToggleDropDownMenu(nil, nil, self:GetParent())
+  if DropDownList1:IsVisible() then
+  end



    WorldMapContinentDropDownButton:HookScript("OnClick", dropdownScaleFix)
    WorldMapZoneDropDownButton:HookScript("OnClick", dropdownScaleFix)

Clamsoda 12-10-12 01:31 AM

Thanks a lot for the insight Phanx. I implemented your changes, but I am still getting "Interface action failed because of an AddOn" message when I open the map while in combat.

Here is a link to the TaintLog produced:

I see the the DropDownMenu is being tainted, but there are also other aspects of the map that are being tainted. As for the DropDownMenu, I am grabbing that directly from Mapster(Thanks Nev <.<), and I don't ever recall Mapster producing any issues -- and further more, how will I make any changes to the map if it just breaks in combat?

Phanx 12-10-12 03:51 AM

I have seen taint errors from Mapster when opening the map in combat, though it's pretty rare.

Do you get the same errors when your world map addon is the only addon enabled?

Other than that, try just doing SetScale and SetAttribute once when you load, instead of every time the map is shown. I'm not sure why you'd need to repeat them. SetAttribute in particular is likely to have issues in combat.

Clamsoda 12-10-12 04:07 AM

When I was reading about InCombatLockdown(), it specified that setting frame attributes, and moving frames without a hardware event were protected, so I KNOW that is causing tainting issues.

Setting the WorldMapFrame scale doesn't work on load, it seems to only work on the map's Show method. m_Map, Mapster, and tekMapEnhancer all have the SetScale for the WorldMapFrame OnShow.

I think I am going to start fresh, after ~12 hours of looking and staring at it, and constant modifications, I am sure my code is less than optimal.

Clamsoda 12-12-12 04:48 AM

Sorry for the double post!

So I have done some work on my map mod, and I've got it producing no taint at all. The only issue I am running into is that to set the scale for the WorldMapFrame, it has to be done OnShow, and to avoid taint, I have to use a combat lockdown function to handle scaling the map OnShow, so if the map is opened in combat, it doesn't taint, but the scale is wrong.

Is there any way to set the scale of the map permanently? Even doing:
Lua Code:
  1. /run WorldMapFrame:SetScale(0.60)
doesn't affect the scale of the world map, unless run when the frame is opened.

Code for refrence:
Lua Code:
  1. -- Local definitions
  2. local mapScale = 0.60 -- Map scale for easy modification
  4. -- Thanks Nevcariel for the function, and Phanx for the modifiaction!
  5. local function dropdownScaleFix(self)
  6.     if DropDownList1:IsVisible() then
  7.         DropDownList1:SetScale(mapScale)
  8.     end
  9. end
  11. do
  12.     local mini = GetCVarBool("miniWorldMap")
  13.     SetCVar("miniWorldMap", nil)
  14.     if mini then
  15.         WorldMap_ToggleSizeUp()
  16.     end
  18.     WorldMapFrame:SetAttribute("UIPanelLayout-defined", true)
  19.     -- WorldMapFrame:SetAttribute("UIPanelLayout-enabled", true)
  20.     WorldMapFrame:SetAttribute("UIPanelLayout-area", "center")
  21.     WorldMapFrame:EnableKeyboard(false)
  22.     WorldMapFrame:EnableMouse(false)
  23.     WorldMapFrameSizeDownButton:Disable()
  24.     WorldMapContinentDropDownButton:HookScript("OnClick", dropdownScaleFix)   -----------------------------------------
  25.     WorldMapZoneDropDownButton:HookScript("OnClick", dropdownScaleFix)        -- Thanks for the modification, Phanx! --
  26.     WorldMapZoneMinimapDropDownButton:HookScript("OnClick", dropdownScaleFix) -----------------------------------------
  27.     BlackoutWorld:Hide()
  29.     hooksecurefunc(WorldMapFrame, "Show", function(self)
  30.         if not InCombatLockdown() then
  31.             self:SetScale(mapScale)
  32.         end
  33.     end)
  35.     hooksecurefunc(BlackoutWorld, "Show", function(self) self:Hide() end)
  37.     -- This may not be neccesary because the map is forced to size up, then the frame attributes are set.
  38.     -- hooksecurefunc("WorldMap_ToggleSizeUp", function() WorldMapFrame:SetAttribute("UIPanelLayout-area", "center") end)
  40.     -- Thanks very much Leatrix!
  41.     WorldMapButton:SetScript("OnMouseWheel", function(self, delta)
  42.         local newLevel = GetCurrentMapDungeonLevel() - delta
  43.         if newLevel >= 1 and newLevel <= GetNumDungeonMapLevels() then
  44.             SetDungeonMapLevel(newLevel)
  45.         end
  46.     end)
  48.     -- Thanks very much Leatrix!
  49.     WorldMapShowDigSites:HookScript("OnClick", function(self)
  50.         local filename, texheight, void, void, sub = GetMapInfo()
  51.         if sub or not filename then
  52.             MiniMapWorldMapButton:Click(); MiniMapWorldMapButton:Click();
  53.         end
  54.     end)
  55. end

Clamsoda 12-12-12 02:12 PM

Yay three posts in a row =/.

I was able to achieve the desired a bit of a round-about fashion. I did some investigating as to what would cause the WorldMapFrame's scale to reset to 1 every time it is shown, and I noticed that it doesn't have a parent frame, which I thought was interesting. I tried parenting it to UIParent as a test, and voila, it inherited UIParent's scale.

I was able to manage the scale of the frame, without having to hook the OnShow function, by creating my own frame, setting that frame's scale, and parenting the WorldMapFrame to it. I'd like to not have to create my own frame just to handle the scaling, so if anyone has any insight, I'd greatly appreciate it.

Thanks so much for the time, help, and effort.

All times are GMT -6. The time now is 02:34 AM.

vBulletin © 2018, Jelsoft Enterprises Ltd
© 2004 - 2017 MMOUI