WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Transmog/Wardrobe LUA function help needed (https://www.wowinterface.com/forums/showthread.php?t=54135)

greengoo 08-05-16 04:13 PM

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!!!

Lombra 08-05-16 07:31 PM

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).

greengoo 08-05-16 07:49 PM

Quote:

Originally Posted by Lombra (Post 317520)
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.

Lombra 08-05-16 08:13 PM

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.

greengoo 08-05-16 08:29 PM

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


Lombra 08-06-16 05:04 AM

You have to use the source ID. Item ID won't work.

greengoo 08-07-16 10:50 PM

Quote:

Originally Posted by Lombra (Post 317535)
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 :)

greengoo 08-07-16 11:58 PM

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


Lombra 08-08-16 04:32 AM

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.

greengoo 08-08-16 06:41 AM

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.

Phanx 08-08-16 09:24 AM

Quote:

Originally Posted by greengoo (Post 317627)
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.

Lombra 08-08-16 09:35 AM

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.

Phanx 08-08-16 09:42 AM

Quote:

Originally Posted by Lombra (Post 317646)
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.

Lombra 08-08-16 09:56 AM

Yeah, should have quoted. That was not directed at you. Didn't refresh before posting!

greengoo 08-08-16 01:32 PM

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!


All times are GMT -6. The time now is 12:39 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI