Quantcast
Help with XML controls - ESOUI
Thread Tools Display Modes
04/29/20, 09:19 AM   #1
EscherechiaColi
Join Date: Apr 2020
Posts: 9
Help with XML controls

Hi! I am new to Addon development, and I have been fiddling around trying things to get a hold on things.

However, I am stuck on something I don't quite understand yet...

I have followed this tutorial:
and from there I have added a auto ready check accept when using LFG

Lua Code:
  1. EVENT_MANAGER:RegisterForEvent(self.name, EVENT_GROUPING_TOOLS_READY_CHECK_UPDATED, self.OnLFGReadyCheckState)
  2. [...]
  3. function RemiCustomAddon.OnLFGReadyCheckState(event)
  4.     if HasLFGReadyCheckNotification() then
  5.         AcceptLFGReadyCheckNotification()
  6.     end
  7. end

And it works perfectly!

I just wanted to add now a message display that tells me when I'm close to full on my bag (less than 10 space left). I copied everything I did for the combat system in the tutorial (which still works well) and created a new XML file for this. However, whenever the addon should update with the message, I get the infamous "nil index...".

Could someone give me a hand?

.lua file:
Lua Code:
  1. EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED, self.DoesBagHaveSpace)
  2. [...]
  3. function RemiCustomAddon.DoesBagHaveSpace(eventCode, initial)
  4.     itemSpace = GetNumBagFreeSlots(1)
  5.     if itemSpace < 10 then
  6.         RemiCustomAddonIndicator:SetHidden(false) -- Here is the faulty line
  7.     end
  8. end

.xml file:
Code:
<GuiXml>
  <Controls>
    <TopLevelControl name="FightIndicator" mouseEnabled="true" movable="true" clampedToScreen="true">
      <Dimensions x="200" y="25" />
      <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="CENTER" offsetY="-20" />
      <OnInitialized>
          -- LUA code here. This is where you'd check to see if the control needs to be hidden or not.
          FightIndicator:SetHidden(not IsUnitInCombat('player'))
      </OnInitialized>
      <OnMoveStop>
        RemiCustomAddon.OnIndicatorMoveStopFight()
      </OnMoveStop>

      <Controls>
        <Label name="$(parent)Label" width="200" height="25" font="ZoFontWinH1" inheritAlpha="true" color="FF0000"
            wrapMode="TRUNCATE" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Fighting!">
          <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" />
        </Label>
      </Controls>
    </TopLevelControl>
  </Controls>
</GuiXml>
.txt file:
Code:
## Title: RemiCustomAddon
## APIVersion: 100030
## SavedVariables: RemiCustomAddonSavedVariables

RemiCustomAddon.lua
RemiCustomAddon.xml
Fight.xml
Note that I tried putting .xml files before AND after the .lua, to no avail.

Thanks in advance!
  Reply With Quote
04/29/20, 10:57 AM   #2
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
RemiCustomAddonIndicator Where is this control defined?
It should be inside your XML file but I cannot see it.
Is it in the other xml file? You need to post this then.

Last edited by Baertram : 04/29/20 at 11:03 AM.
  Reply With Quote
04/29/20, 11:04 AM   #3
Rhyono
AddOn Author - Click to view addons
Join Date: Sep 2016
Posts: 660
I'm wondering if that should be where it says FightIndicator currently.
  Reply With Quote
04/29/20, 11:04 AM   #4
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
I guess it's in the 2nd xml file which he did not show us here:
RemiCustomAddon.xml
  Reply With Quote
04/30/20, 12:16 AM   #5
EscherechiaColi
Join Date: Apr 2020
Posts: 9
Missing XML file

I totally messed up sorry! Of course, here is the correct .xml file:

Code:
<GuiXml>
  <Controls>
    <TopLevelControl name="RemiCustomAddonIndicator" mouseEnabled="true" movable="true" clampedToScreen="true">
      <Dimensions x="200" y="25" />
      <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="CENTER" offsetY="-20" />
      <OnInitialized>
          -- LUA code here. This is where you'd check to see if the control needs to be hidden or not.
          RemiCustomAddonIndicator:SetHidden(not (GetNumBagFreeSlots(1) < 10))
      </OnInitialized>
      <OnMoveStop>
        RemiCustomAddon.OnIndicatorMoveStopBagSpace()
      </OnMoveStop>

      <Controls>
        <Label name="$(parent)Label" width="200" height="25" font="ZoFontWinH1" inheritAlpha="true" color="FFA500"
            wrapMode="TRUNCATE" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Your bag is almost full!">
          <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" />
        </Label>
      </Controls>
    </TopLevelControl>
  </Controls>
</GuiXml>
Thank you for your answers so far!
  Reply With Quote
04/30/20, 02:07 AM   #6
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
Could you also show the error message text (complete, expand it to show the error message).
I recommand using LibDebugLogger and DebugLogViewer -> Addon settings of DebugLogViewer -> LiBDebugLogger -> Enable stack trace.
It helps showing error message callbacks and watch them later on + creates a SavedVariables file LibDebugLogger.lua which you are able to view / share online here for us:
https://sir.insidi.at/or/logviewer/
Share button at the top then to create the link.

Try to use and addon like this here to inspect the global variable RemiCustomAddonIndicator.

https://www.esoui.com/downloads/info...dImproved.html
https://www.esoui.com/downloads/info...oGreymoor.html

You can use /tbug (or /tb) RemiCustomAddonIndicator or /zgoo RemiCustomAddonIndicator to inspect it then.

Is it available after login and player ready (event_player_activated)?

Or does it say in chat: NIL / doesn't zgoo open?
  Reply With Quote
04/30/20, 02:30 AM   #7
EscherechiaColi
Join Date: Apr 2020
Posts: 9
Ok i'm going to install your addon to see what I can give you
  Reply With Quote
04/30/20, 02:37 AM   #8
EscherechiaColi
Join Date: Apr 2020
Posts: 9
First error message:
Code:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:12: attempt to index a nil value /* <== this line is: RemiCustomAddonIndicator:ClearAnchors() */
stack traceback:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:12: in function 'RemiCustomAddon:RestorePositionBagSpace'
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:34: in function 'RemiCustomAddon:Initialize'
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:77: in function 'RemiCustomAddon.OnAddOnLoaded'
Second error message is basically the same but line uh... 43 if I recall correctly (this line)
Code:
        RemiCustomAddonIndicator:SetHidden(false)
Here is the "Bag" portion of the .lua file:
Lua Code:
  1. function RemiCustomAddon:RestorePositionBagSpace()
  2.     local leftBagSpace = self.savedVariables.leftBagSpace
  3.     local topBagSpace = self.savedVariables.topBagSpace
  4.    
  5.     RemiCustomAddonIndicator:ClearAnchors()
  6.     RemiCustomAddonIndicator:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, leftBagSpace, topBagSpace)
  7. end
  8. [...]
  9. function RemiCustomAddon:Initialize()
  10.     self.inCombat = IsUnitInCombat("player");
  11.    
  12.  
  13.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_COMBAT_STATE, self.OnPlayerCombatState)
  14.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_GROUPING_TOOLS_READY_CHECK_UPDATED, self.OnLFGReadyCheckState)
  15.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED, self.DoesBagHaveSpace)
  16.  
  17.     self.savedVariables = ZO_SavedVars:New("RemiCustomAddonSavedVariables", 1, nil, {})
  18.     self:RestorePositionBagSpace()
  19.     self:RestorePositionFight()
  20. end
  21. [...]
  22. function RemiCustomAddon.DoesBagHaveSpace(eventCode, initial)
  23.     itemSpace = GetNumBagFreeSlots(1)
  24.     if itemSpace < 10 then
  25.         RemiCustomAddonIndicator:SetHidden(false)
  26.    end
  27. end
  28. [...]
  29. function RemiCustomAddon.OnIndicatorMoveStopBagSpace()
  30.     RemiCustomAddon.savedVariables.leftBagSpace = RemiCustomAddonIndicator:GetLeft()
  31.     RemiCustomAddon.savedVariables.topBagSpace = RemiCustomAddonIndicator:GetTop()
  32. end

And finally, here is the addon tbug test that you required:
"tbug: No inspector for 'RemiCustomAddonIndicator' ("nil")

Once again, thank you for your time, and sorry for my replies hours, I currently live in Korea

Last edited by EscherechiaColi : 04/30/20 at 02:39 AM. Reason: Added faulty line for error 1
  Reply With Quote
04/30/20, 02:51 AM   #9
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
Could you please post the TOTAL lua files and do not replace any tetx with [...] as the line numbers of the error mesages do not match your code shown here. It's improtant to see the complete code to see what is run in which order and map it to the errors.

Also if you expand the error messages as they show you can see the variable and table contents. It should show you that the variable is NIL already or at least show you the variables that are not nil, containing there values. This way you are able to see yourself, directly in the lua error message, what is missing/wrong content or value.

As RemiCustomAddonIndicator is nil the xml file is either not loaded or loaded after your event_add_on_loaded fires.
Change the load order (but you said you already did?) in your txt file maybe before the lua file.
Maybe your code in the XML file initialization is causing errors you do not see in chat, so try LibDebugLogger for this!
Remove the code in <OnInitialization> of the XML file of the bagspace stuff and try if it works then.

Last edited by Baertram : 04/30/20 at 02:55 AM.
  Reply With Quote
04/30/20, 03:28 AM   #10
EscherechiaColi
Join Date: Apr 2020
Posts: 9
Sorry... I thought it would be better that way. So here we go:

Lua Code:
  1. -- First, we create a namespace for our addon by declaring a top-level table that will hold everything else.
  2. RemiCustomAddon = {}
  3.  
  4. -- This isn't strictly necessary, but we'll use this string later when registering events.
  5. -- Better to define it in a single place rather than retyping the same string.
  6. RemiCustomAddon.name = "RemiCustomAddon"
  7.  
  8. function RemiCustomAddon:RestorePositionBagSpace()
  9.     local leftBagSpace = self.savedVariables.leftBagSpace
  10.     local topBagSpace = self.savedVariables.topBagSpace
  11.    
  12.     RemiCustomAddonIndicator:ClearAnchors()
  13.     RemiCustomAddonIndicator:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, leftBagSpace, topBagSpace)
  14. end
  15.  
  16. function RemiCustomAddon:RestorePositionFight()
  17.     local leftFight = self.savedVariables.leftFight
  18.     local topFight = self.savedVariables.topFight
  19.    
  20.     FightIndicator:ClearAnchors()
  21.     FightIndicator:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, leftFight, topFight)
  22. end
  23.  
  24. -- Next we create a function that will initialize our addon
  25. function RemiCustomAddon:Initialize()
  26.     self.inCombat = IsUnitInCombat("player");
  27.    
  28.  
  29.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_COMBAT_STATE, self.OnPlayerCombatState)
  30.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_GROUPING_TOOLS_READY_CHECK_UPDATED, self.OnLFGReadyCheckState)
  31.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED, self.DoesBagHaveSpace)
  32.  
  33.     self.savedVariables = ZO_SavedVars:New("RemiCustomAddonSavedVariables", 1, nil, {})
  34.     self:RestorePositionBagSpace()
  35.     self:RestorePositionFight()
  36. end
  37.  
  38. function RemiCustomAddon.DoesBagHaveSpace(eventCode, initial)
  39.     itemSpace = GetNumBagFreeSlots(1)
  40.     if itemSpace < 10 then
  41.         RemiCustomAddonIndicator:SetHidden(false)
  42.    end
  43. end
  44.  
  45. function RemiCustomAddon.OnLFGReadyCheckState(event)
  46.     if HasLFGReadyCheckNotification() then
  47.         AcceptLFGReadyCheckNotification()
  48.     end
  49. end
  50.  
  51. function RemiCustomAddon.OnPlayerCombatState(event, inCombat)
  52.     -- The ~= operator is "not equal to" in Lua.
  53.     if inCombat ~= RemiCustomAddon.inCombat then
  54.       -- The player's state has changed. Update the stored state...
  55.       RemiCustomAddon.inCombat = inCombat
  56.    
  57.       -- ...and then update the control.
  58.       FightIndicator:SetHidden(not inCombat)
  59.     end
  60. end
  61.  
  62. function RemiCustomAddon.OnIndicatorMoveStopFight()
  63.     RemiCustomAddon.savedVariables.leftFight = FightIndicator:GetLeft()
  64.     RemiCustomAddon.savedVariables.topFight = FightIndicator:GetTop()
  65. end
  66.  
  67. function RemiCustomAddon.OnIndicatorMoveStopBagSpace()
  68.     RemiCustomAddon.savedVariables.leftBagSpace = RemiCustomAddonIndicator:GetLeft()
  69.     RemiCustomAddon.savedVariables.topBagSpace = RemiCustomAddonIndicator:GetTop()
  70. end
  71.  
  72. -- Then we create an event handler function which will be called when the "addon loaded" event
  73. -- occurs. We'll use this to initialize our addon after all of its resources are fully loaded.
  74. function RemiCustomAddon.OnAddOnLoaded(event, addonName)
  75.   -- The event fires each time *any* addon loads - but we only care about when our own addon loads.
  76.   if addonName == RemiCustomAddon.name then
  77.     RemiCustomAddon:Initialize()
  78.   end
  79. end
  80.  
  81. -- Finally, we'll register our event handler function to be called when the proper event occurs.
  82. EVENT_MANAGER:RegisterForEvent(RemiCustomAddon.name, EVENT_ADD_ON_LOADED, RemiCustomAddon.OnAddOnLoaded)

As for the error messages, here it is (expanded):
Code:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:12: attempt to index a nil value
stack traceback:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:12: in function 'RemiCustomAddon:RestorePositionBagSpace'
|caaaaaa<Locals> self = [table:1]{inCombat = F, name = "RemiCustomAddon"} </Locals>|r
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:34: in function 'RemiCustomAddon:Initialize'
|caaaaaa<Locals> self = [table:1] </Locals>|r
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:77: in function 'RemiCustomAddon.OnAddOnLoaded'
|caaaaaa<Locals> event = 65536, addonName = "RemiCustomAddon" </Locals>|r
But to be honest, I don't really see what to do with this information myself... I don't quite understand what would be missing.

For LibDebugLogger, sorry it took quite a lot of time for me to understand how to use it...
Here is the file:
https://sir.insidi.at/or/logviewer/NVxFbP

As for the .txt file, yes I tried putting .xml files before and after the .lua file, no change. I also already tried removing the OnInitialization code (commenting it with --) to no avail.
  Reply With Quote
04/30/20, 04:03 AM   #11
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
Code:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:12: attempt to index a nil value
-> Error in line 12 of your file /AddOns/RemiCustomAddon/RemiCustomAddon.lua

Code:
stack traceback:
-> Shows you what was called until the error in line 12 appeared (read it from bottom to top -> a stack).

Code:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:12: in function 'RemiCustomAddon:RestorePositionBagSpace'

|caaaaaa<Locals> self = [table:1]{inCombat = F, name = "RemiCustomAddon"} </Locals>|r
-> <Locals> Shows you the local variables that existes + their contents, as the error ocured. Either your addon's variables and contents, or ZOs vanila code, or both. Function parameters, tables {...} etc.
e.g.

self = [table:1]{} means self is the first table in the stack traceback and the string between {} is the content of the table.
It got a variable inCombat and name

inCombat is a variable of your addon's table, which you point to with the self variable. It shows the current value = F (false) / T (true).
You can see from that code that in your function RemiCustomAddon:Initialize the variable self.inCombat is false and the self.name "RemiCustomAddon"

Code:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:34: in function 'RemiCustomAddon:Initialize'

|caaaaaa<Locals> self = [table:1] </Locals>|r
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:77: in function 'RemiCustomAddon.OnAddOnLoaded'
|caaaaaa<Locals> event = 65536, addonName = "RemiCustomAddon" </Locals>|r

About LibDebugLogger:
It basically shows the same as the stack trace back above. It only provides a cleaner view of the variables.
You can watch the source code you have posted at your LibDebugLogger link. The red lien with the error message. Click it and below you'll see the local variables as parsed "clean view" or raw (like within the error message).


I can see you are using several addons, like HarvestMap and others.
For the test of your addon you should always disable all other addons and not needed libraries. Reloadui will be much faster then and you can test if your addon alone works, or not.

You can use Circonians Addon Selector to create a "addon test" profile and "normal profile" so you are able to switch quickly e.g.


Error reason
The error happens as your control is NIL: RemiCustomAddonIndicator
As the addon tries to access it in the event_add_on_loaded callback function Initialize via your call to RestorePositionBagSpace.

Try to move the calls from the initialize function, to RestorePositionBagSpace and RestorePositionCombat to the event_player_activated callback function!

It's called later as the chat is ready and all addons were loaded. Event_add_on_loaded also triggers before the UI is ready and might be the problem with the XML control not properly created yet.

The benefit: Event_player_activated also fires after a zone change e.g. and would reposition and update the labels.

If it also shows an error at event_player_activated your XML might be wrong somehow. Not seeing where though.

Edit2
Think I found somehting in your XML file:

Code:
<OnInitialized>
          -- LUA code here. This is where you'd check to see if the control needs to be hidden or not.
          RemiCustomAddonIndicator:SetHidden(not (GetNumBagFreeSlots(1) < 10))
      </OnInitialized>
Try to change RemiCustomAddonIndicator to self!

Last edited by Baertram : 04/30/20 at 04:23 AM.
  Reply With Quote
04/30/20, 05:03 AM   #12
EscherechiaColi
Join Date: Apr 2020
Posts: 9
Well... I did both the changes that you said could help, and here is what I got
Code:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:39: attempt to index a nil value
|rstack traceback:
user:/AddOns/RemiCustomAddon/RemiCustomAddon.lua:39: in function 'RemiCustomAddon.DoesBagHaveSpace'
|caaaaaa<Locals> eventCode = 589824, initial = F </Locals>|r
which is the line in the EVENT_PLAYER_ACTIVATED callback refering to the self:RestorePositionBagSpace() call. However, the message seems to appear properly now that I changed the condition to > 10 in OnInitialize in my .xml file. Will check if it works properly with the initial condition of under 10.
  Reply With Quote
04/30/20, 05:54 AM   #13
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
Did you try to remove the <OnInit...> handler in the xml file completely to see if it loads properly then?
Not sure what causes this, I can have a look this evening with your code, if you attach the total addon (all files!) as ZIP file e.g.
  Reply With Quote
04/30/20, 09:20 AM   #14
Drummerx04
AddOn Author - Click to view addons
Join Date: Sep 2017
Posts: 49
Post

I think your issue is related to the somewhat confusing process Addons go through while the game is loading. There are a couple key points to consider.
  • Each xml element of your code has to be instantiated before you make a call to it, otherwise it will be nil
  • Your files get loaded in the order present in the .txt manifest file (which looks fine for your purposes)
  • When a file is loaded, all lua/xml code is processed and run at that point. This is usually safe for variable and function declarations only.
  • Your RemiCustomAddon.lua binds your addon to EVENT_ADD_ON_LOADED before all of your elements are actually initialized. Since this is done in the global code area, this happens before your xml has been processed
  • ESO is then calling your OnAddonLoaded() function before processing the xml files.

What I usually do to avoid this is to avoid binding to any events from the global space of a LUA file. I instead create an initialize function, then call the initialize function from the <OnInitialized> tags from my xml gui (which then also lets you pass the xml control in to your initialize functions). In your case it would look something like this.

xml Code:
  1. <GuiXml>
  2.   <Controls>
  3.     <TopLevelControl name="RemiCustomAddonIndicator" mouseEnabled="true" movable="true" clampedToScreen="true">
  4.       <Dimensions x="200" y="25" />
  5.       <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="CENTER" offsetY="-20" />
  6.       <OnInitialized>
  7.           -- Call your initialize function from here
  8.           RemiCustomAddon:Initialize(self)
  9.       </OnInitialized>
  10.       <OnMoveStop>
  11.         RemiCustomAddon.OnIndicatorMoveStopBagSpace()
  12.       </OnMoveStop>
  13.  
  14.       <Controls>
  15.         <Label name="$(parent)Label" width="200" height="25" font="ZoFontWinH1" inheritAlpha="true" color="FFA500"
  16.            wrapMode="TRUNCATE" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Your bag is almost full!">
  17.           <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" />
  18.         </Label>
  19.       </Controls>
  20.     </TopLevelControl>
  21.   </Controls>
  22. </GuiXml>

Then your initialize function would look like this
Lua Code:
  1. function RemiCustomAddon:Initialize(control)
  2.     -- control -> RemiCustomAddonIndicator
  3.     self.inCombat = IsUnitInCombat("player");
  4.    
  5.  
  6.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_COMBAT_STATE, self.OnPlayerCombatState)
  7.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_GROUPING_TOOLS_READY_CHECK_UPDATED, self.OnLFGReadyCheckState)
  8.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED, self.DoesBagHaveSpace)
  9.  
  10.     -- Bind the addon load from here.
  11.     EVENT_MANAGER:RegisterForEvent(RemiCustomAddon.name, EVENT_ADD_ON_LOADED, RemiCustomAddon.OnAddOnLoaded)
  12.  
  13.     -- Shouldn't need this call because you also bound it to PLAYER_ACTIVATED, but I included it because you had it in the xml originally
  14.     self.DoesBagHaveSpace()
  15.     self.savedVariables = ZO_SavedVars:New("RemiCustomAddonSavedVariables", 1, nil, {})
  16.     self:RestorePositionBagSpace()
  17.     self:RestorePositionFight()
  18. end

That should fix your problem.

Edit: Upon review, you may need to add another initialize function to handle the flightIndicator, change the load order of the xml files, or simply combine your two xml files into one.

Here is what a combination could look like:
xml Code:
  1. <GuiXml>
  2.   <Controls>
  3.     <TopLevelControl name="RemiCustomAddonIndicators" mouseEnabled="true" movable="true" clampedToScreen="true">
  4.       <Dimensions x="200" y="25" />
  5.       <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="CENTER" offsetY="-20" />
  6.       <OnInitialized>
  7.           -- Call your initialize function from here
  8.           RemiCustomAddon:Initialize(self)
  9.       </OnInitialized>
  10.       <OnMoveStop>
  11.         RemiCustomAddon.OnIndicatorMoveStopBagSpace()
  12.       </OnMoveStop>
  13.  
  14.       <Controls>
  15.     <Control name="BagIndicator" mouseEnabled="true" movable="true" clampedToScreen="true">
  16.       <Dimensions x="200" y="25" />
  17.       <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="CENTER" offsetY="-20" />
  18.       <OnMoveStop>
  19.             RemiCustomAddon.OnIndicatorMoveStopBagSpace()
  20.       </OnMoveStop>
  21.       <Controls>
  22.         <Label name="$(parent)Label" width="200" height="25" font="ZoFontWinH1" inheritAlpha="true" color="FFA500"
  23.            wrapMode="TRUNCATE" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Your bag is almost full!">
  24.               <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" />
  25.             </Label>
  26.       </Controls>
  27.     </Control>
  28.    
  29.     <Control name="FightIndicator" mouseEnabled="true" movable="true" clampedToScreen="true">
  30.       <Dimensions x="200" y="25" />
  31.       <Anchor point="BOTTOM" relativeTo="GuiRoot" relativePoint="CENTER" offsetY="-20" />
  32.       <OnMoveStop>
  33.             RemiCustomAddon.OnIndicatorMoveStopFight()
  34.       </OnMoveStop>
  35.       <Controls>
  36.             <Label name="$(parent)Label" width="200" height="25" font="ZoFontWinH1" inheritAlpha="true" color="FF0000"
  37.            wrapMode="TRUNCATE" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Fighting!">
  38.               <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" />
  39.             </Label>
  40.       </Controls>
  41.     </Control>
  42.       </Controls>
  43.     </TopLevelControl>
  44.   </Controls>
  45. </GuiXml>

This will change the global name bindings, but it also lets you do some nice things in the lua
lua Code:
  1. function RemiCustomAddon:Initialize(control)
  2.     -- You can now grab child elements of your top level control without worrying about the full global names.
  3.     local bagIndicator = GetControl(control, "BagIndicator");
  4.     local fightIndicator = GetControl(control, "FightIndicator");
  5.  
  6.     --You can also do this
  7.     GetControl(bagIndicator, "Label"):SetText("Now your label text has changed")
  8.  
  9.  
  10.     self.inCombat = IsUnitInCombat("player");
  11.    
  12.  
  13.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_COMBAT_STATE, self.OnPlayerCombatState)
  14.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_GROUPING_TOOLS_READY_CHECK_UPDATED, self.OnLFGReadyCheckState)
  15.     EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED, self.DoesBagHaveSpace)
  16.  
  17.     -- Bind the addon load from here.
  18.     EVENT_MANAGER:RegisterForEvent(RemiCustomAddon.name, EVENT_ADD_ON_LOADED, RemiCustomAddon.OnAddOnLoaded)
  19.  
  20.     -- Shouldn't need this call because you also bound it to PLAYER_ACTIVATED, but I included it because you had it in the xml originally
  21.     self.DoesBagHaveSpace()
  22.     self.savedVariables = ZO_SavedVars:New("RemiCustomAddonSavedVariables", 1, nil, {})
  23.     self:RestorePositionBagSpace()
  24.     self:RestorePositionFight()
  25. end

Last edited by Drummerx04 : 04/30/20 at 09:40 AM.
  Reply With Quote
04/30/20, 09:44 AM   #15
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
Interesting, thanks Drummerx04

Didn't know the EVENT_ADD_ON_LOADED would fire BEFORE actually the XML files are loaded,
IF the load order in the txt files woould be

Lua Code:
  1. XML
  2. lua

But I wonder why the problem persists if he changed the code from event_add_on_loaded to event_player_activated as at this point all XML and addon code normally was loaded properly, and exists.

Not sure why the xml created control would be nil then, at that time
  Reply With Quote
04/30/20, 10:01 AM   #16
Drummerx04
AddOn Author - Click to view addons
Join Date: Sep 2017
Posts: 49
Originally Posted by Baertram View Post
Interesting, thanks Drummerx04

Didn't know the EVENT_ADD_ON_LOADED would fire BEFORE actually the XML files are loaded,
IF the load order in the txt files woould be

Lua Code:
  1. XML
  2. lua

But I wonder why the problem persists if he changed the code from event_add_on_loaded to event_player_activated as at this point all XML and addon code normally was loaded properly, and exists.

Not sure why the xml created control would be nil then, at that time
Yeah, I saw some of your back and forth, but I was primarily answering the original issue he was having.

I was honestly a little surprised that the event appears to fire before the entire addon is initialized, but that is the most logical explanation for the stack track and error he posted originally.
  Reply With Quote
04/30/20, 10:13 AM   #17
Drummerx04
AddOn Author - Click to view addons
Join Date: Sep 2017
Posts: 49
As a new developer, you might also benefit from a standalone addon I wrote a while back. Lilith's Command History

What it does is to provide a history of /script commands executed in ESO which is persistent across UI reloads, support for multi line lua scripts within the game, running/editing commands stored in the list, and it also provides some additional little quality of life changes like a customizable binding for reloading the UI.

I think you'd find it pretty helpful.
  Reply With Quote
04/30/20, 10:24 AM   #18
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,480
Originally Posted by Drummerx04 View Post
Yeah, I saw some of your back and forth, but I was primarily answering the original issue he was having.

I was honestly a little surprised that the event appears to fire before the entire addon is initialized, but that is the most logical explanation for the stack track and error he posted originally.
The event does not fire before all files including the saved vars have been loaded. If it did, it would be a pretty severe bug that affects all addons and would have been reported a million times already.
__________________
https://www.imperialtradingcompany.eu/ - My Addons - The Vault (Early updates and experimental projects) - My patreon - My blog
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
  Reply With Quote
04/30/20, 10:30 AM   #19
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 3,597
Right, exactly what I thougth and experienced until today.

Not sure what the problem here is but I never had these NIL problems happening if:
-txt file order of XML was before lua and no <OnInitialization> tried to access stuff that was inside the lua file
-even_player_activated or event_add_on_loaded fired

Thats why I asked for the complete source.

Perhaps your files use UTF-8 encoding with a ByteOrderMark. Sometimes this freaks out the ingame addon manager, especially if this is set at the addon's txt file!
So make sure if utf8 is used the BOM is removed on all txt and lua files.
  Reply With Quote
04/30/20, 10:39 AM   #20
Drummerx04
AddOn Author - Click to view addons
Join Date: Sep 2017
Posts: 49
Originally Posted by sirinsidiator View Post
The event does not fire before all files including the saved vars have been loaded. If it did, it would be a pretty severe bug that affects all addons and would have been reported a million times already.
You might be right, but:
  • His global scope control variable is nil. As far as we (and the author) can see, there isn't a typo.
  • The XML is loaded after the lua
  • The lua binds to ADD_ON_LOADED before the xml file is loaded
  • The stacktrace shows his bound function being called first (presumably by the event triggering)

If I'm right, then it likely does affect all addons, but authors already have functional workarounds so we don't really notice it.

Edit: Also the track record for bug fixes in ESO isn't exactly stellar
Edit2: Also he maybe has the wrong xml file name in his .txt so the control is never loaded in the first place.

Last edited by Drummerx04 : 04/30/20 at 11:01 AM.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Help with XML controls

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