Thread Tools Display Modes
08/25/22, 02:39 PM   #1
renfrow
 
renfrow's Avatar
Join Date: Jun 2022
Posts: 5
Exclamation [BUG] /EsoUI/Ingame/Map/WorldMapFilters_Shared.lua:129: attempt to index a nil value

This dialog pops up each time I move from one area to another (e.g. from world to delve). It started happening with the latest update (U35).

================= Stack Trace =================
Code:
/EsoUI/Ingame/Map/WorldMapFilters_Shared.lua:129: attempt to index a nil value
stack traceback:
/EsoUI/Ingame/Map/WorldMapFilters_Shared.lua:129: in function 'OnMapChanged'
|caaaaaa<Locals> mapFilterType = 0, mode = 2 </Locals>|r
/EsoUI/Libraries/Utility/ZO_CallbackObject.lua:132: in function 'ZO_CallbackObjectMixin:FireCallbacks'
|caaaaaa<Locals> self = [table:1]{fireCallbackDepth = 1}, eventName = "OnWorldMapChanged", registry = [table:2]{}, callbackInfoIndex = 8, callbackInfo = [table:3]{4 = F}, callback = /EsoUI/Ingame/Map/WorldMapFilters_Shared.lua:109, deleted = F </Locals>|r
user:/AddOns/TamrielMapping/TamrielMapping.lua:905: in function 'TTMP.CheckMapChange'
|caaaaaa<Locals> does_match = F </Locals>|r
user:/AddOns/TamrielMapping/TamrielMapping.lua:847: in function 'TTMP.OnUpdate'
|caaaaaa<Locals> iNowMillis = 447880 </Locals>|r
TamrielMapping_Update:3: in function '(main chunk)'
|caaaaaa<Locals> self = ud, time = 447.88000488281 </Locals>|r
================= Stack Trace =================

I added debug prints in TTMP.CheckMapChange:

Code:
-- ----------------------------------------------
-- Check if the map has changed and update the current player zone location
-- ----------------------------------------------
function TTMP.CheckMapChange()

	local does_match = DoesCurrentMapMatchMapForPlayerLocation()
	if not does_match then
		TTMP.is_viewing_map = ZO_WorldMap_DidPlayerChooseCurrentMap()
		if not TTMP.is_viewing_map then
			SetMapToPlayerLocation()
if TTMP_MENU_OPTIONS.ShowDebug then
  local mapFilterType = GetMapFilterType()
  if mapFilterType == MAP_FILTER_TYPE_STANDARD then
    dbgPrint("TTMP:CheckMapChange(): map filter type = ".."MAP_FILTER_TYPE_STANDARD")
  elseif mapFilterType == MAP_FILTER_TYPE_AVA_CYRODIIL then
    dbgPrint("TTMP:CheckMapChange(): map filter type = ".."MAP_FILTER_TYPE_AVA_CYRODIIL")
  elseif mapFilterType == MAP_FILTER_TYPE_AVA_IMPERIAL then
    dbgPrint("TTMP:CheckMapChange(): map filter type = ".."MAP_FILTER_TYPE_AVA_IMPERIAL")
  elseif mapFilterType == MAP_FILTER_TYPE_BATTLEGROUND then
    dbgPrint("TTMP:CheckMapChange(): map filter type = ".."MAP_FILTER_TYPE_BATTLEGROUND")
  else
    dbgPrint("TTMP:CheckMapChange(): unknown map filter type = "..mapFilterType)
  end
end
			CALLBACK_MANAGER:FireCallbacks("OnWorldMapChanged")
		end
	end

end

Looking at the stack trace "TamrielMapping.lua:905" is the FireCallbacks() above.

The debug prints out "MAP_FILTER_TYPE_STANDARD" (which has value 1) as the map filter type before we head into system code.

In the 4th line down of the stack trace you see that mapFilterType is 0 (unknown?) in OnMapChanged(). Here is the code for this routine (from https://esoapi.uesp.net/current/src/...hared.lua.html).


Code:
    local function OnMapChanged()
        local mapFilterType = GetMapFilterType()
        local mode = WORLD_MAP_MANAGER:GetMode()
        local newCurrentPanel
        if mapFilterType == MAP_FILTER_TYPE_STANDARD then
            newCurrentPanel = self.pvePanel
            self.pvePanel:SetMapMode(mode)
        elseif mapFilterType == MAP_FILTER_TYPE_AVA_CYRODIIL then
            newCurrentPanel = self.pvpPanel
            self.pvpPanel:SetMapMode(mode)
        elseif mapFilterType == MAP_FILTER_TYPE_AVA_IMPERIAL then
            newCurrentPanel = self.imperialPvPPanel
            self.imperialPvPPanel:SetMapMode(mode)
        elseif mapFilterType == MAP_FILTER_TYPE_BATTLEGROUND then
            newCurrentPanel = self.battlegroundPanel
            self.battlegroundPanel:SetMapMode(mode)
        end
        if self.currentPanel and self.currentPanel ~= newCurrentPanel then
            self.currentPanel:SetHidden(true)
        end
        newCurrentPanel:SetHidden(false)
        self.currentPanel = newCurrentPanel
    end

"newCurrentPanel:SetHidden(false)" is the code trying to index a nil value, meaning that newCurrentPanel is
nil. You'll notice that the if-then-elseif code has no fall through else clause, such that if 'mapFilterType' is not one of the mentioned values, it will remain nil.

Sooo... long question/discussion short, there needs to be an else clause, that sets the newCurrentPanel to a default value, and, they need to find out who is setting it to a bogus value (or clearing it, or not instantiating it).
  Reply With Quote
08/25/22, 03:00 PM   #2
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
I think masteroshi had the very same bug in another map related addon (Fyrakin's MiniMap patch) and he said he could fix it by check if the value of mapFilterType is unknown, then abort further code, or delay the call to the code so the returned mapFilterType will be correct a few ms later.

I think I remember he said the problem is that after a map change the Tamriel map is shortly selected and that makes the mapFilterType return 0, and after that the correct map will be selected and all works fine again. But the code wont "wait" and thus errors.

It's triggered from the OnWorldMapChanged callback that the addons raise to update the map stuff.
For me this is something that ZOs needs to fix in the "if.. else..." of the mapFilterTypes to prevent a nil newCurrentPanel, and I guess for the time until this will be fixed there need to be workarounds like Masteroshi had found.
Or I'm missunderstanding the usage of the code.

btw: If this turns out to be a ZOs caused bug we will move this to the bug sub forum.

Last edited by Baertram : 08/25/22 at 03:05 PM.
  Reply With Quote
08/25/22, 11:45 PM   #3
Masteroshi430
 
Masteroshi430's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2020
Posts: 185
I workarounded that by recalling the same function 50ms later if GetMapFilterType() == 0 in two places but I don't really understand what is really going on:

Lua Code:
  1. local function ZoneCheck()
  2.     if GetMapFilterType() == 0 then zo_callLater(ZoneCheck,50) return end

Lua Code:
  1. function FyrMM.SetMapToPlayerLocation(stealth)
  2.     local changed = false
  3.     if not Stealth then
  4.         if Fyr_MM:IsHidden() then return end
  5.     end
  6.     if GetMapFilterType() == 0 and (FyrMM.SV.WorldMapRefresh or stealth) then zo_callLater(FyrMM.SetMapToPlayerLocation,50) return end

Something is apparently going on during loadscreens, some controls had SetHorizontalScroll() and SetVerticalScroll() to be set again at some point in the code in order to be displayed on screen after a loadscreen like if they were set to nil during the load screen.

Last edited by Masteroshi430 : 08/25/22 at 11:54 PM.
  Reply With Quote
08/26/22, 12:19 PM   #4
ZOS_DanBatson
ZOS Staff!
 
ZOS_DanBatson's Avatar
Yes this person is from ZeniMax!
Join Date: Jul 2015
Posts: 171
A check has been added to prevent the UI error in OnMapChanged. Pretty sure the issue has to do with it being called during a load screen, but I can't be certain. Regardless, the fix will be in Update 36.

Note that with the fix, calling OnMapChanged at that time will still not actually provide any meaningful results. If GetMapFilterType returns 0, that means it's being called at a time when state doesn't exist and it's a meaningless question, so 0 at that point really means "C++ doesn't have the concept of a map or a map filter atm so I don't know how to answer the question of GetMapFilterType. 0 is essentially an "error" value, the function has been called at an invalid time and returns invalid junk results. Under normal use, GetMapFilterType cannot return 0, it's not one of the possible values.
  Reply With Quote
08/26/22, 03:16 PM   #5
renfrow
 
renfrow's Avatar
Join Date: Jun 2022
Posts: 5
I didn't show the debug prints from TTMP.CheckMapChange(), but, immediately prior to going into the system code, it prints out that the value is "MAP_FILTER_TYPE_STANDARD" (which has value 1). So at that point the value *IS* valid. Somewhere between TTMP.CheckMapChange() and OnMapChanged() mapFilterType is getting cleared/object disposed/whatever. And because the value is "valid", in TTMP.CheckMapChange(), you can't tell if you should defer the code... Anyway, just have to live with it till U36 . Thanks!
  Reply With Quote
08/27/22, 05:58 AM   #6
IsJustaGhost
AddOn Author - Click to view addons
Join Date: May 2020
Posts: 37
What is the dbgPrint? If it functions as d() then it will not output during the time the error is caused. So it will only output the proper values returned after player activated.

EDIT: Or has that changed. Or was this not ever a thing?

If this is being done on a registered update you will see multiple occurrences of the error in the interface.log between the times the map is not available. For me, this was 10 to 12 when personally debugging this for MiniMap by Fyrakin patch with an update of 30ms.

It's easy enough to check for GetMapFilterType() == 0 before firing the OnWorldMapChanged callback.

Last edited by IsJustaGhost : 08/29/22 at 05:53 AM.
  Reply With Quote

ESOUI » AddOns » AddOn Help/Support » [BUG] /EsoUI/Ingame/Map/WorldMapFilters_Shared.lua:129: attempt to index a nil value

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off