Thread Tools Display Modes
05/28/14, 03:01 AM   #1
fosley
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
Where do I find info about the stock UI?

So I'm trying to make an addon that adds two new "stats" to the stat screen, and put my names and values into the new stats. I found a couple addons that do similar things, but I'm not understanding exactly how they work, or where they figured out how to use what they have written.

Specifically, SoftcapInfo over-rides
function ZO_Stats:AddStatRow(statType1, statType2)
with his own code. I can hack his code to do what I want, but I'd like to do it as a separate addon, and allow his addon to continue what it's doing.

Harven's Extended Stats uses some weird stuff to add in a bunch of new rows with the ZO_Stats.AddStatRow function. I can hack his code to add a new row with arbitrary stats, but I'm not sure how to access those new rows to put my information in them.

I feel like I should be able to do the following:
Code:
function MyAddon:Initialize()
  ZO_Stats.AddStatRow(some vars)
  ModifyNewRowToUseMyNameAndValue
  EVENT_MANAGER:RegisterForEvent(self.name, EVENT_STATS_UPDATED, self.OnStatsUpdated)
end
function MyAddon.OnStatsUpdated()
  CalculateMyValue
  ModifyNewRowToUseMyValue
end
Unfortunately, I don't know anything about what the AddStatRow function is expecting for arguments, and can't find any reference to that function or information about the ZO_Stats table anywhere. Also, I'm not sure how to reference the row once I've created it in order to change its values. In a C or VB style language, I would do something like:
Code:
ZO_Stats.StatRows[IndexOfMyNewRow].statEntries[0].name:SetText("My First Text")
ZO_Stats.StatRows[IndexOfMyNewRow].statEntries[0].value:SetText(MyFirstValue)
ZO_Stats.StatRows[IndexOfMyNewRow].statEntries[1].name:SetText("My Second Text")
ZO_Stats.StatRows[IndexOfMyNewRow].statEntries[1].value:SetText(MySecondValue)
Because it appears that each StatRows object contains two statEntries, which each contain a name and value object. What I'm not sure how to do is access the "StatRows" object (or whatever it's called), or get to its sub-items.

Obviously some people figured out a lot of the internal workings of the stock UI, but I'm not sure how they did it, or where the information would be online. I tried the the wiki.esoui.com pages, but they don't seem to have anything about ZO_Stats except in the raw dump where it tells me it's a table.

If I could dig through the structure of the ZO_Stats object, and see what datatypes the function were expecting, I could probably figure out the rest. But I'm not sure where to dig through the structure at.
  Reply With Quote
05/28/14, 03:41 AM   #2
Harven
 
Harven's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 135
Hey,
ZO_Stats like most of ingame windows/panel is a table but it contains "control" variable which is a container of all elements in that window. You can just create your own custom control and attach it to that ZO_Stats.control.
Since ZO_Stats is a table you can iterate through it to find out functions names and variables that it contains. You can then hook to choosen function and capture what parameters it recives. Basically you can handle yourself without the default UI code (which hasn't been releaased yet) but it requires some lua knowledge. But on the other hand I'm pretty sure you can find the UI code using google
  Reply With Quote
05/28/14, 10:06 PM   #3
fosley
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
I was finally able to decompile some of the lua, and now I see where some other people got their code.

Anyhow, I'm not sure what to do with ZO_Stats.control. Any references to ZO_Stats.control, ZO_Stats.controls, ZO_Stats.Control, or ZO_Stats.Controls all say "nil", and iterating through all the k/v pairs in ZO_Stats shows nothing but functions. I also tried ZO_Stats["control"] and got "nil". Is there some other way to see the control variable besides d(ZO_Stats.control) or trying to iterate through its k/v pairs?

I tried using the ZO_PreHook function to get the control variable passed into ZO_Stats:Initialize, but I can't figure out how to make the prehook work. The best I can do is not get errors popping up -- the prehook itself doesn't seem to do anything.

I was able to get something passable by setting my custom control's parent to the stats window (so it shows/hides with the stats window), and formatting the text so it looks like the normal stats, but I had to stick it by the Active Mount title so it showed up, and it's fairly narrow to fit in that space. I'd rather just bump the other stats down one and insert my control at the end of the StatRow items.
  Reply With Quote
05/29/14, 04:53 AM   #4
Garkin
 
Garkin's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 832
Originally Posted by fosley View Post
I was finally able to decompile some of the lua, and now I see where some other people got their code.

Anyhow, I'm not sure what to do with ZO_Stats.control. Any references to ZO_Stats.control, ZO_Stats.controls, ZO_Stats.Control, or ZO_Stats.Controls all say "nil", and iterating through all the k/v pairs in ZO_Stats shows nothing but functions. I also tried ZO_Stats["control"] and got "nil". Is there some other way to see the control variable besides d(ZO_Stats.control) or trying to iterate through its k/v pairs?
Download and install addon: Zgoo - data inspection tool. Then type /zgoo ZO_Stats to inspect ZO_Stats object.

Originally Posted by fosley View Post
I tried using the ZO_PreHook function to get the control variable passed into ZO_Stats:Initialize, but I can't figure out how to make the prehook work. The best I can do is not get errors popping up -- the prehook itself doesn't seem to do anything.
I think this won't work as ZO_Stats:Initialize(...) function is called before your addon is loaded.
  Reply With Quote
05/29/14, 05:07 AM   #5
fosley
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
I knew I'd seen an addon like that, just didn't remember where to find it. I'm about to head to bed, but I'll check it out tomorrow, hopefully it can give me some useful information.
  Reply With Quote
05/30/14, 12:59 AM   #6
fosley
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
I guess that addon isn't listed in Minion's stuff, hence why I didn't see it when I was looking through Utilities. I downloaded it, and there's definitely a lot of cool stuff I found. However, I'm still having issues.

First, there's still no such thing as ZO_Stats.control. I'm guessing you didn't just make that up, so I'm not sure what's going on, but that variable doesn't exist any way I look for it, and I'm not sure how to just add my control to it's list.

So, I tried a couple things to get my control working, and I'm almost there. I just need to figure out a way to run my control setup *after* the stat screen is opened the first time. If I initialize immediately, none of the controls I need to anchor to exist yet, so I get nil reference exceptions and so forth.

I tried the following code from another thread, but it doesn't wait until the first function fires:
Code:
local postHook = function(funcName, callback)
  local tmp = _G[funcName]
    _G[funcName] = function(...)
      tmp(...)
    callback()
  end
end

function MyAddon:Initialize()
  postHook("ZO_Stats:OnShown", MyAddon:SetupPosition())
end
I plugged a function replacement into my addon, and ZO_Stats:OnShown is getting fired when I expected:
Code:
function ZO_Stats:OnShown()
  d("ZO_Stats:OnShown")
  MyAddonArmorName:SetText("|cFF0000ZO_Stats:OnShown".."|r")
end
This does not set my addon text until I actually open the window, so the postHook function isn't working correctly.

Ok, so I looked through the ZO_Stats:OnShown function, and it calls ZO_Stats:InitializeKeybindButtons right at the end. So I should be able to prehook that and get my controls setup just after the rest of the screen is finished:
Code:
function MyAddon:Initialize()
  ZO_PreHook("ZO_Stats:InitializeKeybindButtons", function() MyAddon:SetupPosition() end)
end
Code:
function MyAddon:Initialize()
  ZO_PreHook("ZO_Stats:InitializeKeybindButtons", MyAddon:SetupPosition())
end
If I use the first code, nothing ever happens. If I use the second code, it fires as soon as the addon loads. I'm not sure what else I'm supposed to do to make the prehook work. I also over-rode the code like earlier, and confirmed the keybind function is not getting called by something else prior to the stat screen opening, so the ZO_PreHook function isn't working correctly.

I did finally make it work by copy/pasting the stock UI code for the OnShown function into my addon, then inserting a call to my SetupPosition function at the end of it. However, this seems like a pretty bad hack.
  Reply With Quote
05/30/14, 02:57 AM   #7
Aicam
Join Date: Apr 2014
Posts: 16
Trying to prehook initalization methods is prety futile since most are only called before any addon loads.
  Reply With Quote
05/30/14, 04:30 AM   #8
fosley
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
Both of the functions I'm trying to call only activate after you open the stats window. They don't open prior to that, and they definitely fire at that time. Otherwise I wouldn't even need to bother, since the stats pane would be set up completely by the time my addon loaded, and I wouldn't be getting reference errors.
  Reply With Quote
05/30/14, 04:39 AM   #9
Harven
 
Harven's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 135
Originally Posted by fosley View Post
...
First, there's still no such thing as ZO_Stats.control. I'm guessing you didn't just make that up, so I'm not sure what's going on, but that variable doesn't exist any way I look for it, and I'm not sure how to just add my control to it's list.
...
Hey, sorry, it looks like i have misled you. You should use STATS.control. ZO_Stats is just a metatable of STATS table, so you can think of it like this: ZO_Stats - class, STATS - object of ZO_Stats class. It seems that most of the default UI if built that way. For example ZO_InventoryManager is a metatable of PLAYER_INVENTORY, but some metatables are local so you can only access the "object" (CHAT_SYSTEM as an example).

About hooking to *Initialize* functions - like others said, in most cases these functions are called before your addon is loaded so it will not work. Try using STATS "object" and it's "control" variable.

EDIT: right, ZO_Stats:InitializeKeybindButtons is called when you open stats window

EDIT 2: I think you are using the ZO_PreHook function wrong. You should use it like this:
Code:
ZO_PreHook(ZO_Stats, "OnShown", MyAddon.SetupPosition)
or better
Code:
ZO_PreHook(STATS, "OnShown", MyAddon.SetupPosition)
EDIT 3: sorry, didn't noticed you use some other hook function. But still you use it wrong postHook function will work only for global functions and not for functions defined in other tables. Use the ZO_PreHook instead or write another version of postHook that will work with tables:
Code:
local postHook = function(table, funcName, callback)
  local tmp = table[funcName]
    table[funcName] = function(...)
      tmp(...)
    callback()
  end
end
and use it that way:
Code:
postHook(ZO_Stats, "OnShown", MyAddon.SetupPosition)
or better:
Code:
postHook(STATS, "OnShown", MyAddon.SetupPosition)

Last edited by Harven : 05/30/14 at 05:08 AM.
  Reply With Quote
05/30/14, 06:35 AM   #10
Garkin
 
Garkin's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 832
Simple hook:
Lua Code:
  1. -- Note that there is no (). If you use Backup = Function(),
  2. -- variable Backup will contain return value from the function
  3. -- and not the function itself.
  4. local Backup = Function
  5.  
  6. Function = function(...)
  7.    --your code here
  8.    Backup(...)
  9.    --your code here
  10. end

If you want to hook method (see: Object Orientation Tutorial), you should keep in mind that:
Lua Code:
  1. Class:Method(...)
is just syntax sugar for:
Lua Code:
  1. Class.Method(self, ...)

So, to hook method you have to use:
Lua Code:
  1. local Backup = Class.Method
  2.  
  3. Class.Method = function(self, ...)
  4.    --your code here
  5.    Backup(self, ...)
  6.    --your code here
  7. end

Last edited by Garkin : 05/30/14 at 06:37 AM.
  Reply With Quote
05/30/14, 11:51 PM   #11
fosley
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
Ok, I got the prehook to work like this:
Code:
ZO_PreHook(ZO_Stats, "InitializeKeybindButtons", function() self:SetupPosition() end)
I had tried using "stats" before, but I didn't do "STATS", so now I'm finding it in zgoo. I'm still researching how to index userdata, but at least I have something to index now.

At some point I'll get around to changing my setup function to add the control to the list so it auto-formats everything around it, but for now I have it working without over-writing any stock code, and it plays nicely with both Extended Stats and Soft Cap Info, so I think I'm going to just play the game for a while.

Thanks for the help, I'm sure at some point I'll be bugging you guys again with all my noob questions.

Edit:
The addon is uploaded here, if anyone cares.

Last edited by fosley : 05/31/14 at 04:26 AM.
  Reply With Quote
05/31/14, 01:20 PM   #12
katkat42
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 155
Originally Posted by fosley View Post
Ok, I got the prehook to work like this:
I had tried using "stats" before, but I didn't do "STATS", so now I'm finding it in zgoo.
Yes, lua is case-sensitive, which has Bitten-Me-before.
  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » Where do I find info about the stock UI?


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