Thread Tools Display Modes
03/14/24, 08:51 AM   #1
Saint-Ange
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 10
Need help with an addon writting

Hi, sorry I know everyone is very busy atm but I'm getting crazy over here. Yesterday I finished testing an addon and all was fine and published it: ToggleGroupFrame. Today I log in and catastrophe I got this error:
Code:
:1: function expected instead of nil
stack traceback:
:1: in function '(main chunk)'
	<Locals> keybind = "TOGGLE_GROUP_FRAME" </Locals>
and I'm unable to solve the problem. I'm a beginner, I try to follow guides, I've spent alone more time on this than I'd like to admit, my energy is depleted and my capacities aren't what they were. I need help to sort this out, especially now that I've clearly made the mistake to upload too early.

Here's the lua:
Code:
local addon = { name = "ToggleGroupFrame" }
local em = GetEventManager()
local groupFrameHidden = true
local showInCombat = true

ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_GROUP_FRAME", "Show/Hide group frame")
ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_GROUP_FRAME_IN_COMBAT", "Show/Hide in combat")

local function OnAddOnLoaded(event, addonName)
   if addonName ~= addon.name then return end
   Initialize()
end

function Initialize()
   ZO_UnitFramesGroups:SetHidden(true)

   local savedVariables = ZO_SavedVars:New("ToggleGroupFrameSavedVariables", 1, nil, {}, GetWorldName())

   SLASH_COMMANDS['/togglegroupframe'] = function()
      groupFrameHidden = not groupFrameHidden
      ZO_UnitFramesGroups:SetHidden(groupFrameHidden)
      savedVariables.groupFrameHidden = groupFrameHidden
   end
   SLASH_COMMANDS['/tgf'] = SLASH_COMMANDS['/togglegroupframe']
   
   SLASH_COMMANDS['/togglegroupframeincombat'] = function()
      showInCombat = not showInCombat
      savedVariables.showInCombat = showInCombat
      UpdateGroupFrameVisibility()
   end
   SLASH_COMMANDS['/tgfc'] = SLASH_COMMANDS['/togglegroupframeincombat']
   SLASH_COMMANDS['/tgfic'] = SLASH_COMMANDS['/togglegroupframeincombat']

   em:RegisterForEvent(addon.name, EVENT_PLAYER_COMBAT_STATE, OnCombatStateChanged)
   em:UnregisterForEvent(addon.name, EVENT_ADD_ON_LOADED)
end

function UpdateGroupFrameVisibility()
   if IsUnitInCombat("player") then
      if showInCombat then
         ZO_UnitFramesGroups:SetHidden(false)
      else
         ZO_UnitFramesGroups:SetHidden(true)
      end
   else
      ZO_UnitFramesGroups:SetHidden(groupFrameHidden)
   end
end

function OnCombatStateChanged(event, inCombat)
   if not groupFrameHidden then
      return
   end

   UpdateGroupFrameVisibility()
end

em:RegisterForEvent(addon.name, EVENT_ADD_ON_LOADED, OnAddOnLoaded)
and the xml just to be sure:
Code:
<Bindings>
  <Layer name="SI_KEYBINDINGS_LAYER_GENERAL">
    <Category name="ToggleGroupFrame">
      <Action name="TOGGLE_GROUP_FRAME">
        <Down>SLASH_COMMANDS["/togglegroupframe"]()</Down>
      </Action>
      <Action name="TOGGLE_GROUP_FRAME_IN_COMBAT">
        <Down>SLASH_COMMANDS["/togglegroupframeincombat"]()</Down>
      </Action>
    </Category>
  </Layer>
</Bindings>
Any help would be much much much appreciated.
  Reply With Quote
03/14/24, 09:24 AM   #2
Dolgubon
 
Dolgubon's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2016
Posts: 409
First, you'll want to look at the error. What line does it say, and what code is on that line? That's always critical information for figuring out errors. Second, what does function expected instead of nil mean? Well, it means that on that line of code, you have functionName(), but functionName is actually nil. So make sure the function is actually declared.


Finally, you need to either make your functions local, or pop them in your addon table. They are currently global, so if anyone addon declares a global Initialize function (pretty likely tbh) it'll overwrite yours
  Reply With Quote
03/14/24, 11:31 AM   #3
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Not sure why but if I dowload your currently uploaded addon file Windows Defender pops in and says your file is a virus.
Maybe a false positive but are you sure you had uploaded the actual addon and nothing else?


And yes, please, as Dolgubon already said:
Always put a local in front of your function names! Or if you define a table local addon, add the functions to that table

function addon.OnCombatStateChanged(param)
function addon.Initialize(param)
function addon.UpdateGroupFrameVisibility(param)


and call them the same addon.OnCombatStateChanged(...) or addon.Initialize, or addon.UpdateGroupFrameVisibility
-> Keep in mind that local functions and code cannot be accessed from XML files of your addon, so see below how to fix this.

Else you might overwrite other addons/ZOs lua code, or some other addon might do that at your addon.

Everything not explicitly defined local is global and must use a very unique name, which in your case could be
function ToggleGroupFrame_OnCombatStateChanged e.g. but actually that's not needed. Keep it local.
Or create 1 global table ToggleGroupFrame = {} and add all functions and variables to that, so you can call it from XML code.
Else it may overwrite, or get overwritten!

Last edited by Baertram : 03/14/24 at 11:36 AM.
  Reply With Quote
03/14/24, 02:09 PM   #4
Saint-Ange
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 10
Originally Posted by Dolgubon View Post
First, you'll want to look at the error. What line does it say, and what code is on that line? That's always critical information for figuring out errors. Second, what does function expected instead of nil mean? Well, it means that on that line of code, you have functionName(), but functionName is actually nil. So make sure the function is actually declared.


Finally, you need to either make your functions local, or pop them in your addon table. They are currently global, so if anyone addon declares a global Initialize function (pretty likely tbh) it'll overwrite yours
That's exactly what happened, my addon overwrote an other one wich lost its saved variable, glad I had a save. Thank you very much
  Reply With Quote
03/14/24, 02:15 PM   #5
Saint-Ange
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 10
Originally Posted by Baertram View Post
Not sure why but if I dowload your currently uploaded addon file Windows Defender pops in and says your file is a virus.
Maybe a false positive but are you sure you had uploaded the actual addon and nothing else?


And yes, please, as Dolgubon already said:
Always put a local in front of your function names! Or if you define a table local addon, add the functions to that table

function addon.OnCombatStateChanged(param)
function addon.Initialize(param)
function addon.UpdateGroupFrameVisibility(param)


and call them the same addon.OnCombatStateChanged(...) or addon.Initialize, or addon.UpdateGroupFrameVisibility
-> Keep in mind that local functions and code cannot be accessed from XML files of your addon, so see below how to fix this.

Else you might overwrite other addons/ZOs lua code, or some other addon might do that at your addon.

Everything not explicitly defined local is global and must use a very unique name, which in your case could be
function ToggleGroupFrame_OnCombatStateChanged e.g. but actually that's not needed. Keep it local.
Or create 1 global table ToggleGroupFrame = {} and add all functions and variables to that, so you can call it from XML code.
Else it may overwrite, or get overwritten!
Ok, for the virus I recon it was a bit too much but it's good to live on the edge
Now, I've followed your indications and came up with this, it works though my saved variables .. aren't saved anymore so more work needed.

Code:
ToggleGroupFrame = {}

local addon = { name = "ToggleGroupFrame" }
local em = GetEventManager()
local groupFrameHidden = true
local showInCombat = true

ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_GROUP_FRAME", "Show/Hide group frame")
ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_GROUP_FRAME_IN_COMBAT", "Show/Hide in combat")

function addon.OnAddOnLoaded(event, addonName)
   if addonName ~= addon.name then return end
   addon.Initialize()
end

function addon.Initialize()
   ZO_UnitFramesGroups:SetHidden(true)

   local savedVariables = ZO_SavedVars:New("ToggleGroupFrameSavedVariables", 1, nil, {}, GetWorldName())

   SLASH_COMMANDS['/togglegroupframe'] = function()
      groupFrameHidden = not groupFrameHidden
      ZO_UnitFramesGroups:SetHidden(groupFrameHidden)
      savedVariables.groupFrameHidden = groupFrameHidden
   end
   SLASH_COMMANDS['/tgf'] = SLASH_COMMANDS['/togglegroupframe']
   
   SLASH_COMMANDS['/togglegroupframeincombat'] = function()
      showInCombat = not showInCombat
      savedVariables.showInCombat = showInCombat
      addon.UpdateGroupFrameVisibility()
   end
   SLASH_COMMANDS['/tgfc'] = SLASH_COMMANDS['/togglegroupframeincombat']
   SLASH_COMMANDS['/tgfic'] = SLASH_COMMANDS['/togglegroupframeincombat']

   em:RegisterForEvent(addon.name, EVENT_PLAYER_COMBAT_STATE, addon.OnCombatStateChanged)
   em:UnregisterForEvent(addon.name, EVENT_ADD_ON_LOADED)
end

function addon.UpdateGroupFrameVisibility()
   if IsUnitInCombat("player") then
      if showInCombat then
         ZO_UnitFramesGroups:SetHidden(false)
      else
         ZO_UnitFramesGroups:SetHidden(true)
      end
   else
      ZO_UnitFramesGroups:SetHidden(groupFrameHidden)
   end
end

function addon.OnCombatStateChanged(event, inCombat)
   if not groupFrameHidden then
      return
   end

   addon.UpdateGroupFrameVisibility()
end

em:RegisterForEvent(addon.name, EVENT_ADD_ON_LOADED, addon.OnAddOnLoaded)
Thank you very much lads! You know how it is when you .. just can't anymore. It's a lot to learn.
  Reply With Quote

ESOUI » AddOns » AddOn Help/Support » Need help with an addon writting


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