Thread Tools Display Modes
08/28/19, 05:59 AM   #1
Deathbat219
Join Date: Mar 2019
Posts: 9
Adding controls to existing menus and getting items prices from traders

Hi.
I wanted to make an addon that will display some additional data in each row of the guild trader search results.
What's the correct way of adding controls to existing menus?
Also how to get prices of items in the search results?
  Reply With Quote
08/28/19, 02:10 PM   #2
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,903
Hello,

the lists normally are some ZO_SortScrollList controls. If you check the source code of them in the esoui source code you get a basic understanding for them (I hope).
Or maybr the forums here or the wiki got some info about them as well.

Normally those lists got a setup function for each "row" of the list which you can use to add controls to them.
Addons like ItemSaver also got some hooks where they add controls to lists if the rows get created:

Lua Code:
  1. local listView = PLAYER_INVENTORY.inventories[INVENTORY_BAGPACK].listView
  2.         if listView and listView.dataTypes and listView.dataTypes[1] then
  3.             local hookedFunctions = listView.dataTypes[1].setupCallback
  4.  
  5.             listView.dataTypes[1].setupCallback =
  6.             function(rowControl, slot)
  7.                 --Call original function of the row
  8.                 hookedFunctions(rowControl, slot)
  9.  
  10.                 --Do not execute if horse is changed
  11.                 if SCENE_MANAGER:GetCurrentScene() ~= STABLES_SCENE then
  12.                    --Do your stuff here
  13.                 end
  14.             end
  15.         end

The prices should be either in the rowControl.dataEntry.data table or there might be API functions (check the API documentation inside the Wiki for current API 100028) which are able to be used with bagId and slotIndex, or itemLink, of the rowControl (the item).
  Reply With Quote
08/29/19, 02:29 AM   #3
Deathbat219
Join Date: Mar 2019
Posts: 9
Thanks for your answer.
I have a few more questions.
How should I access this list? I tried using getControlByName (I figured out from the source code that the name should be ZO_TradingHouseBrowseItemsRightPaneSearchResults) but it returns nil.

When should I run the code you posted? I assume that it should trigger when the guild trader ui shows but I tried using the scene manager template from the wiki and couldn't even display text in chat when inventory is shown or hidden.
  Reply With Quote
08/29/19, 03:34 AM   #4
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,903
This code should be run at your event_add_on_loaded callback function or only once at event_player_activated.

My example code will "hook" the normal inventory, but not the trading house list! So you'd need to find the appropriate listView of the trading house.
Everytime a row is created it will call the code at
--Do your stuff here
so you'd need to create your texture/control here, anchor itt to rowControl properly and show whatever you want in it.
It will also be called if you scroll in the listView.

So you do not need to do stuff as the trading house opens or closes or shows the list as the hook will handle this. But you need to find the correct listView of the trading house sell panel! As my code is for your normal inventory, if you press I. You can try this firstt o see how it works maybe.

Maybe check with zgoo addon the variable TRADING_HOUSE or similar if you have something like TRADING_HOUSE.buyPanel.inventory.list or similar. I never used the trading house stuff.

Check the base code for the trading house in the esoui source code to get the global variable of it, if it's not TRADING_HOUSE:
https://github.com/esoui/esoui/tree/...e/tradinghouse

From what I can see there the global variable would be either TRADING_HOUSE_SEARCH or TRADING_HOUSE

If you checkt he file tradinghouse_keyboard.lua you'll find a local list = self.searchResultsList
So the variable searchResultsList should be somewhere below TRADING_HOUSE I guess and would be the list you need to use for my example code.
Exchange the line local listView = PLAYER_INVENTORY.inventories[INVENTORY_BAGPACK].listView
with it like
local listView = TRADING_HOUSE.whatEver.searchResultsList

Last edited by Baertram : 08/29/19 at 03:36 AM.
  Reply With Quote
08/29/19, 05:04 AM   #5
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,566
The trading house is a bit of a different beast than the regular inventory and you cannot simply hook into it in the events mentioned by Baertram, because it will only fully initialize the first time you actually visit a guild store.

The best way I have found so far is to hook into TRADING_HOUSE:SetCurrentMode and use a flag to run the code only the first time it is called.

Lua Code:
  1. local ranInitialSetup = false
  2. ZO_PreHook(TRADING_HOUSE, "SetCurrentMode", function()
  3.     if(ranInitialSetup) then return end
  4.     ranInitialSetup = true
  5.  
  6.     -- do your setup here
  7. end)

or you can use AwesomeGuildStore as a dependency for your addon and listen to its AFTER_INITIAL_SETUP callback, with the additional advantage that it will already have applied its changes.

Lua Code:
  1. local AGS = AwesomeGuildStore
  2. AGS:RegisterCallback(AGS.callback.AFTER_INITIAL_SETUP, function()
  3.     -- do your setup here
  4. end)
  Reply With Quote
08/29/19, 08:51 AM   #6
Deathbat219
Join Date: Mar 2019
Posts: 9
Thank you guys for your help.
I got it working but I have two more problems. During the first search the code where I'm creating the label executes twice.
For example if there are 5 items in the first search results and 4 in the second search it executes 10 times during the first but 4 times during the second.
And the second problem is that the created label doesn't disappear when serch results change.
Here's the code:
Lua Code:
  1. local count = 0
  2. local function setupSearchResults()
  3.     local listView = TRADING_HOUSE.searchResultsList
  4.     if listView and listView.dataTypes and listView.dataTypes[1] then
  5.         local hookedFunctions = listView.dataTypes[1].setupCallback
  6.  
  7.         listView.dataTypes[1].setupCallback = function(rowControl, slot)
  8.             --Call original function of the row
  9.             hookedFunctions(rowControl, slot)
  10.  
  11.             --Do not execute if horse is changed
  12.             if SCENE_MANAGER:GetCurrentScene() ~= STABLES_SCENE then
  13.                     count = count + 1
  14.                 local label = CreateControl("Label" .. count, rowControl, CT_LABEL)
  15.                 label:SetText(slot.purchasePrice)
  16.                 label:SetFont("ZoFontGameLargeBold")
  17.                 label:SetAnchor(CENTER, rowControl, CENTER, 50, 0)
  18.             end
  19.         end
  20.     end
  21. end
  22.  
  23. local function OnAddOnLoaded(_, addOnName)
  24.     if addOnName ~= ADDON_NAME then
  25.         return
  26.     end
  27.     EVENT_MANAGER:UnregisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED)
  28.  
  29.     local ranInitialSetup = false
  30.     ZO_PreHook(
  31.         TRADING_HOUSE,
  32.         "SetCurrentMode",
  33.         function()
  34.             if (ranInitialSetup) then
  35.                 return
  36.             end
  37.             ranInitialSetup = true
  38.             setupSearchResults()
  39.         end
  40.     )
  41. end
  42.  
  43. EVENT_MANAGER:RegisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED, OnAddOnLoaded)

Last edited by Deathbat219 : 08/29/19 at 09:11 AM.
  Reply With Quote
08/29/19, 09:11 AM   #7
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,903
If it runs twice at the first search the setupCallback of the rows seem to be called twice somehow.
I don't know why. Maybe due to other addons? Disable all other addons and try if it's still called twice.

Oh and remove this from your code as the stable scene won't be active for the guild store at all
It was the example for the normal inventory which gets called if you buy more inventory space at the stable master.
Lua Code:
  1. --Do not execute if horse is changed
  2.             if SCENE_MANAGER:GetCurrentScene() ~= STABLES_SCENE then
  3.             -- Do your stuff here
  4.             end
  Reply With Quote
08/29/19, 09:18 AM   #8
Deathbat219
Join Date: Mar 2019
Posts: 9
It is Arkadius Trade Tools that runs the code twice. But the labels still don't disappear after search results change.
  Reply With Quote
08/29/19, 09:46 AM   #9
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,903
The setupCallback function runs as the rows are created and updated (on scroll). The rows are "reused" afaik like 12 rows are created (they are the visible rows) and if you scroll the setupCallback function will be call again and you only need to update the labels.

So be sure to create them only once and anchor them to the rowControl, set their parent to the rowControl so they hide with the row autoamtically.
And always check if the rowControl got the label already. If so, read your actual data from rowControl.dataEntry.data (or wherever you get the data from) and update the label with the actual rows data.
Otherwise each scroll would re-create another and another and another label and just show it on top of the others (if the name of the labels differ).

I'd use something like

Lua Code:
  1. local myLabelName = rowControl:GetName() .. "_myAddonLabel"
  2. local myLabel = WINDOW_MANAGER:GetControlByName(myLabelName, "")
  3. if not myLabel then
  4.     --I do not know the exact create control function anymore so just see this as example: name, parentControl, typeOfControl
  5.       myLabel = WINDOW_MANAGER:CreateControl(myLabelName, rowControl, CT_LABEL)
  6. end

Last edited by Baertram : 08/29/19 at 09:52 AM.
  Reply With Quote
08/29/19, 09:52 AM   #10
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,566
You forgot to set a color, so you can likely just not see it.
Lua Code:
  1. label:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())

Some tips:
Don't access the dataTypes table directly, instead use ZO_ScrollList_GetDataTypeTable:
Lua Code:
  1. local SEARCH_RESULTS_DATA_TYPE = 1
  2. local searchResultDataType = ZO_ScrollList_GetDataTypeTable(TRADING_HOUSE.searchResultsList, SEARCH_RESULTS_DATA_TYPE)
  3. local originalSearchResultSetupCallback = searchResultDataType.setupCallback
  4. searchResultDataType.setupCallback = function(rowControl, result)
  5.     originalSearchResultSetupCallback(rowControl, result)
  6. ...

The setup callback is called every time the row is used, which means with your current code you are leaking controls, since they cannot be destroyed. You should instead check if the control already exists and only create it when needed:

Lua Code:
  1. local label = rowControl.myAddOnLabel -- pick some unique name so other addons won't collide with it
  2. if(not label) then
  3.     label = rowControl:CreateControl("$(parent)MyAddOnLabel", CT_LABEL) -- you can just use the parent name to avoid having to ensure a unique name yourself
  4.     label:SetFont("ZoFontGameLargeBold")
  5.     label:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
  6.     label:SetAnchor(CENTER, rowControl, CENTER, 50, 0)
  7.     rowControl.myAddOnLabel = label
  8. end
  9. label:SetText(slot.purchasePrice)
  Reply With Quote
08/29/19, 09:55 AM   #11
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,903
Good to know about ZO_ScrollList_GetDataTypeTable.
I should probably change this in FCOItemSaver then, once I have collected all the dataType contants (like SEARCH_RESULTS_DATA_TYPE ) for the different inventory lists...
  Reply With Quote
08/29/19, 09:56 AM   #12
Deathbat219
Join Date: Mar 2019
Posts: 9
Thank you very much for your help. Everything works perfectly now
  Reply With Quote
08/29/19, 10:16 AM   #13
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,903
Try to add

## OptionalDepensOn: AwesomeGuildStore ArkadiusTradeTools

to your manifest txt file so the 2 addons are loaded before yours and thus your hook into the setupCallback also contains there hooks already.
Maybe for AwesomeGuildStore needs some more things to check like sirinsidiator already wrote and showed you the function which says "all ready" before.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Adding controls to existing menus and getting items prices from traders

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