Thread Tools Display Modes
08-05-16, 04:13 PM   #1
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
Transmog/Wardrobe LUA function help needed

Hey guys, hoping to get some help from someone far smarter than I regarding some LUA code I'm trying to write. Two specific questions regarding the transmog wardrobe UI and how to make changes to my set's mogged items (prior to hitting "Accept").

How can I create a table of known transmog item IDs for a certain slot? For example, I want to create an array where each entry in the array is the six-digit item ID of a Plate Helm that I am currently able to transmog.

Once I have that six-digit ID, what is the best/simplest way to apply the mog for that Item ID on to the Wardrobe window, so I can apply the mog or save it as an outfit?

Any help would be greatly appreciated. I've been scouring the web today and found limited success on these two items. Thanks!!!
  Reply With Quote
08-05-16, 07:31 PM   #2
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Hi,

C_TransmogCollection.GetCategoryAppearances(category) gives you a table of "appearances" (basically item models) The appearance tables contain a key .visualID. The visual ID can then be used with C_TransmogCollection.GetAppearanceSources(visualID) to get all the items using the model in question. (a source refers to an item) Similarly, the source tables contain a key .sourceID, (basically another item ID) which you then can use with C_TransmogCollection.GetAppearanceSourceInfo(sourceID) (sixth return) to get the item link. Extract the item ID from that.

Code:
local availableItems = {}

for i, appearance in ipairs(C_TransmogCollection.GetCategoryAppearances(LE_TRANSMOG_COLLECTION_TYPE_HEAD)) do
	for i, source in ipairs(C_TransmogCollection.GetAppearanceSources(appearance.visualID)) do
		local _, _, _, _, _, link = C_TransmogCollection.GetAppearanceSourceInfo(source.sourceID)
		local itemID = GetItemInfoInstant(link)
		tinsert(availableItems, itemID)
	end
end
Available category IDs here:
https://www.townlong-yak.com/framexm....lua/diff#1445

A few things to note. C_TransmogCollection.GetAppearanceSourceInfo is for some reason very slow. (edit: well, maybe it's not particularly slow and there just are a lot of sources) Calling it for every source in the wardrobe takes several seconds. Also, using item ID might not be a good idea as a single item ID can have several appearances depending on whether it's normal, heroic, etc version of the item. I recommend using the full link or, if possible, even the source ID.

To apply transmog, use C_Transmog.SetPending(slotID, LE_TRANSMOG_TYPE_APPEARANCE, sourceID).
__________________
Grab your sword and fight the Horde!

Last edited by Lombra : 08-05-16 at 07:35 PM.
  Reply With Quote
08-05-16, 07:49 PM   #3
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
Originally Posted by Lombra View Post
Hi,

C_TransmogCollection.GetCategoryAppearances(category) gives you a table of "appearances" (basically item models) The appearance tables contain a key .visualID. The visual ID can then be used with C_TransmogCollection.GetAppearanceSources(visualID) to get all the items using the model in question. (a source refers to an item) Similarly, the source tables contain a key .sourceID, (basically another item ID) which you then can use with C_TransmogCollection.GetAppearanceSourceInfo(sourceID) (sixth return) to get the item link. Extract the item ID from that.

Available category IDs here:
https://www.townlong-yak.com/framexm....lua/diff#1445

A few things to note. C_TransmogCollection.GetAppearanceSourceInfo is for some reason very slow. (edit: well, maybe it's not particularly slow and there just are a lot of sources) Calling it for every source in the wardrobe takes several seconds. Also, using item ID might not be a good idea as a single item ID can have several appearances depending on whether it's normal, heroic, etc version of the item. I recommend using the full link or, if possible, even the source ID.

To apply transmog, use C_Transmog.SetPending(slotID, LE_TRANSMOG_TYPE_APPEARANCE, sourceID).
First off, thank you so much for the response. Couple questions. Right now, I'm focusing on just the helm slot. So I'm using:

Code:
local button = CreateFrame("Button", "ClownSuitButton", WardrobeTransmogFrame.Inset,"UIPanelButtonTemplate")
	button:SetWidth(120)
	button:SetHeight(25)
	button:SetPoint("BOTTOMLEFT",450,0)
	button:RegisterForClicks("AnyUp")
	button:SetText("Clown Suit")
	button:SetScript("OnClick", function() clownHelm() end)
	button:SetFrameLevel(button:GetFrameLevel() + 1)

function clownHelm()
	C_TransmogCollection.ClearSearch() -- empties out the search trash to ensure we get a full list
	local knownMogCount = C_TransmogCollection.GetCategoryCollectedCount(1) -- Gets a count of how many helms are known
	local listOfHelms = C_TransmogCollection.GetCategoryAppearances(1) -- Creates a table of appearences (.visualID)
	local tempHelm = C_TransmogCollection.GetAppearanceSources(listOfHelms[10].visualID) -- Gets the .sourceID of item 10 on table
	C_Transmog.SetPending(1,LE_TRANSMOG_COLLECTION_TYPE_HEAD,tempHelm) -- Sets Pending head slot item to tempHelm

end

For now, I just want to apply one of the helms I know (I don't care which, the goal is to get a random int between 1 and knownMogCount and apply that, but for now it doesn't matter so I'm using 10). However, I feel like I'm not getting from the .visualID to the .sourceID I need to use C_Transmog.SetPending. I'm also a bit unsure on the SetPending parameters, if I'm using them correctly. Can you expand a little bit on that? How can I extract the necessary sourceID from the "listOfHelms" item I've created?


I feel like I'm close but as I mentioned, I'm early in my learning.

Last edited by greengoo : 08-05-16 at 08:06 PM.
  Reply With Quote
08-05-16, 08:13 PM   #4
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
I think you need only change tempHelm to tempHelm[1].sourceID.

Don't change LE_TRANSMOG_TYPE_APPEARANCE in SetPending. That value is meant to indicate whether it's an "appearance" (item) or an "illusion" (enchant). The first parameter is traditional inventory slot ID; not wardrobe category ID. In both cases that happens to be 1 for helm though, so you're good.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-05-16, 08:29 PM   #5
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
Almost got it! I can print the link item at the end and get an ingame link for the helm... just can't seem to actively set it as the "on deck" or pending mog (mimicing the action of clicking on a helm). I can't seem to get C_Transmog.SetPending(1, LE_TRANSMOG_TYPE_APPEARANCE, itemID) to work. Everything else seems to work fine, but it's not *actually* setting it, even if I feed in a direct itemID such as 28180 .



Code:
local button = CreateFrame("Button", "ClownSuitButton", WardrobeTransmogFrame.Inset,"UIPanelButtonTemplate")
	button:SetWidth(120)
	button:SetHeight(25)
	button:SetPoint("BOTTOMLEFT",450,0)
	button:RegisterForClicks("AnyUp")
	button:SetText("Clown Suit")
	button:SetScript("OnClick", function() clownHelm() end)
	button:SetFrameLevel(button:GetFrameLevel() + 1)

function clownHelm()
	C_TransmogCollection.ClearSearch() -- empties out the search trash to ensure we get a full list
	local knownMogCount = C_TransmogCollection.GetCategoryCollectedCount(1) -- Gets a count of how many helms are known
	local listOfHelms = C_TransmogCollection.GetCategoryAppearances(1) -- Creates a table of appearences (.visualID)
	local tempHelm = C_TransmogCollection.GetAppearanceSources(listOfHelms[12].visualID) -- Gets the .sourceID of item 12 on table
	local _, _, _, _, _, link = C_TransmogCollection.GetAppearanceSourceInfo(tempHelm[1].sourceID)
		print("Link: ",link)
	local itemID = GetItemInfoInstant(link)
		print("itemID: ",itemID)
	C_Transmog.SetPending(1, LE_TRANSMOG_TYPE_APPEARANCE, itemID) -- Sets Pending head slot item to itemID

end

Last edited by greengoo : 08-05-16 at 09:16 PM.
  Reply With Quote
08-06-16, 05:04 AM   #6
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
You have to use the source ID. Item ID won't work.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-07-16, 10:50 PM   #7
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
Originally Posted by Lombra View Post
You have to use the source ID. Item ID won't work.
You are correct, and I got that working now. At this point, it will successfully work for helms, and I've created individual buttons to randomize the helm slot as well as the shoulder slot. Your insights have been absolutely spot on and appreciated.


edit: I solved my issue... as you mentioned and I ignored to my peril wardrobe slot != item slot. Working on it

Last edited by greengoo : 08-07-16 at 11:40 PM.
  Reply With Quote
08-07-16, 11:58 PM   #8
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
New issue... I've dialed in the randomize buttons so that I can do any individual button, but there's a catch. The individual buttons (shoulder, helm, etc) work totally perfect... ***IF*** that slot is currently selected as the active mog slot in the wardrobe interface. If it is not, or if I try to do multiple pieces at once (using the transmog all slots button) then each one may or may not function. I can't quite figure out what's causing it, but my guess is that it has to do with the for loop at the bottom of my code that checks if an matching sourceID is known and then uses that one if it is. I get the feeling that section is causing the issue, but can't figure out how/why. Any great advice?


Code:
-- BUTTON CODE

local button = CreateFrame("Button", "ClownSuitButton", WardrobeTransmogFrame.Inset,"UIPanelButtonTemplate")		-- Randomize All Button
	button:SetWidth(120)
	button:SetHeight(25)
	button:SetPoint("BOTTOMLEFT",450,0)
	button:RegisterForClicks("AnyUp")
	button:SetText("Clown Suit")
	button:SetScript("OnClick", function() equipClownSuit() end)
	button:SetFrameLevel(button:GetFrameLevel() + 1)

local button = CreateFrame("Button", "ClearClownSuitButton", WardrobeTransmogFrame.Inset,"UIPanelButtonTemplate")	-- Clear All Button
	button:SetWidth(120)
	button:SetHeight(25)
	button:SetPoint("BOTTOMLEFT",595,0)
	button:RegisterForClicks("AnyUp")
	button:SetText("Clear Pending")
	button:SetScript("OnClick", function() C_Transmog.ClearPending() end)
	button:SetFrameLevel(button:GetFrameLevel() + 1)

local button = CreateFrame("Button", "HelmButton", WardrobeTransmogFrame.Inset,"UIPanelButtonTemplate")			-- Helm Button
	button:SetWidth(25)
	button:SetHeight(25)
	button:SetPoint("BOTTOMLEFT",40,415)
	button:RegisterForClicks("AnyUp")
	button:SetText("+")
	button:SetScript("OnClick", function() setSlotToClown(1,1) end)
	button:SetFrameLevel(button:GetFrameLevel() + 1)

local button = CreateFrame("Button", "ShoulderButton", WardrobeTransmogFrame.Inset,"UIPanelButtonTemplate")		-- Shoulder Button
	button:SetWidth(25)
	button:SetHeight(25)
	button:SetPoint("BOTTOMLEFT",40,365)
	button:RegisterForClicks("AnyUp")
	button:SetText("+")
	button:SetScript("OnClick", function() setSlotToClown(2,3) end)
	button:SetFrameLevel(button:GetFrameLevel() + 1)

--      Build rest of buttons once shoulder code is working


-- RANDOMIZE CODE FOR EVERYTHING

function equipClownSuit()
	setSlotToClown(1,1)  -- Helm
	setSlotToClown(2,3)  -- Shoulder
	setSlotToClown(4,5)  -- Chest
	setSlotToClown(9,6)  -- Waist
	setSlotToClown(10,7) -- Legs
	setSlotToClown(11,8) -- Feet
	setSlotToClown(7,9)  -- Wrist
	setSlotToClown(8,10) -- Hands
	setSlotToClown(3,15) -- Back
	setSlotToClown(6,19) -- Tabard
end


-- RANDOMIZE CODE FOR INDIVIDUAL SLOTS

function setSlotToClown(clownSlotID,mogSlotID)
	C_TransmogCollection.ClearSearch() 									-- empties out the search trash to ensure we get a full list [working]
	local knownMogCount = C_TransmogCollection.GetCategoryCollectedCount(clownSlotID) 			-- Gets a count of how many visuals are known [working]
	local randomArmorToUse = random(0,knownMogCount) 							-- chooses a random number to grab a random armor [working]
	local listOfArmors = C_TransmogCollection.GetCategoryAppearances(clownSlotID) 				-- Creates a table of appearences (.visualID)
	local tempArmor = C_TransmogCollection.GetAppearanceSources(listOfArmors[randomArmorToUse].visualID) 	-- Gets the .sourceID table of the random armor
	local visualIdToUse 											-- Searches through the appearances until a known one is found
	for i, source in pairs(tempArmor) do
		if source.isCollected then
			visualIdToUse = i									-- then sets the visualIdToUse to a known sourceID
			break
		end
	end
	C_Transmog.SetPending(mogSlotID, LE_TRANSMOG_TYPE_APPEARANCE, tempArmor[visualIdToUse].sourceID)	-- Sets pending armor slot item to a working sourceID
end
  Reply With Quote
08-08-16, 04:32 AM   #9
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Not sure. One possible error could be that your known appearances aren't necessarily the knownMogCount first ones in the listOfArmors. I would say that's likely. Other than that I can only recommend debugging the values passed to SetPending, then you could manually verify that it's getting valid arguments.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-08-16, 06:41 AM   #10
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
Do you know if there's a command I can use to select a certain slot in the transmog wardrobe interface, replicating the action of clicking on the slot I want to display known mogs for?

I'm thinking if I append this to the start of the setSlotToClown function it might resolve the issue.
  Reply With Quote
08-08-16, 09:24 AM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by greengoo View Post
Do you know if there's a command I can use to select a certain slot in the transmog wardrobe interface, replicating the action of clicking on the slot I want to display known mogs for?
When in doubt, look at the default UI's own code. I don't know offhand which file that would be in. Use /fstack in-game to find the name of the frame, then search for it in the FrameXML code.

Note that you should search for a parent/container frame like PaperDollFrame, not a numbered child frame like PaperDollFrameItemSlot42, since those frames are often created in ways that mean their final name doesn't appear literally in the code.

Once you find the frame, just look to see what happens in its OnClick handler.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-08-16, 09:35 AM   #12
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
One problem with that is that there exists only those 15 or so frames to click that you see at any one time. There is not a frame for each appearance. So to "click" an item that isn't on the current page would require some additional hacks. Not sure if there is a less annoying way.

I would not recommend depending on the UI either way. It's better to work as close to the API as possible. You could create a new table where you include all collected appearances and then pick randomly from that.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-08-16, 09:42 AM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Lombra View Post
I would not recommend depending on the UI either way. It's better to work as close to the API as possible.
Right. I wasn't suggesting actually interacting with the UI, just looking at the UI code to find out which API functions you need to call.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-08-16, 09:56 AM   #14
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Yeah, should have quoted. That was not directed at you. Didn't refresh before posting!
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-08-16, 01:32 PM   #15
greengoo
A Murloc Raider
Join Date: Aug 2016
Posts: 7
Thanks for the ideas guys. I'll look into creating tables rather than the direction I'm using now. Hopefully that will resolve things.

I really wish I understood what was causing my current method to interfere if that slot isn't the active one. It SHOULD work as is in my mind. The check to ensure it's using a known source ID works if it's the active slot, but I can't for the life of me find out what causes the interference when it's not selected. It's bothering me.

I'll keep at it... Thanks!
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Transmog/Wardrobe LUA function help needed


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