WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Inventory Sorting (https://www.wowinterface.com/forums/showthread.php?t=57734)

loff93 12-14-19 08:45 AM

Inventory Sorting
 
Hey,

would like to test the idea of sorting items in bag depending on vendor price.
Any tips?

I think I know a way to loop through inventory, but I do not know how to swap slots in bag.

I'm a total newbie to XML/LUA/WoW, but can I for example put all items in a List and sort the list depending on Vendor price, before I put item out in the correct order? Item will swap order in bag while that is being done, so I don't know how that would work either

Help or link to APIs that can be helpful is appreciated :)

SDPhantom 12-14-19 02:26 PM

You might want to check out PickupContainerItem().

You'll have to apply the sort in multiple stages since the items will become "locked" once you attempt to swap them. The swapping itself doesn't actually occur until the server responds. When doing each pass, you can keep track which slots you've put into a locked state and work on the others simultaneously. This'll make the overall process quicker as waiting for the server to catch up can consume a lot of time.

loff93 12-14-19 03:44 PM

Quote:

Originally Posted by SDPhantom (Post 334780)
You might want to check out PickupContainerItem().

You'll have to apply the sort in multiple stages since the items will become "locked" once you attempt to swap them. The swapping itself doesn't actually occur until the server responds. When doing each pass, you can keep track which slots you've put into a locked state and work on the others simultaneously. This'll make the overall process quicker as waiting for the server to catch up can consume a lot of time.

oww I see! Awesome - Thanks for the info :)

loff93 12-15-19 05:33 AM

Hello again!
I tried a lot of different things. I got some help from people on discord and this is my current result.
It doesn't work 100%. I believe the issue is that slots ain't updated if they are moved, so they might try to move even if they are at the correct spot, or trade spot with a item that is at the correct spot.

Example of issue:
First Slot A updates:
Slot A <-> Slot B

Then its Slot B's turn
Slot B <-> Slot A

Any tips on how to sort this better to avoid this kind of behavior?

- Couple other issues I haven't done much about:
Currently its only for main bag.
What if a item swap with another and they merge? Will that break something

Code:

local AllItems = {}
local waitTable = {}

local function PrintAll() -- Debugging only, Ignore this
        print('------')
    for i = table.getn(AllItems), 1, -1
    do
        print(AllItems[i].itemName, AllItems[i].itemSellPrice)
        end
        print('------')
end

local function GetAllItemsFromBag(Insert)
        -- for slot=0, NUM_BAG_SLOTS do
                for index=1, GetContainerNumSlots(0) do
                        local item = GetContainerItemID(0, index)
                        if(item) then
                                --print(item)
                                local _, _, _, _, _, _, _, _, _, itemID = GetContainerItemInfo(0, index)
                                if(itemID ~= nil) then
                                        --print(itemID)
                                        local itemName, _, _, _, _, _, _, _, _, _, itemSellPrice = GetItemInfo(itemID)
                                        table.insert(Insert, {index = index, itemID = itemID, itemSellPrice = itemSellPrice, itemName = itemName})
                                end
                        end
                end
        -- end
       
end

local function SaferSwapItems(bag1, bag2, slot1, slot2)
    ClearCursor()

        print(slot1, 'To',  slot2)
        local _, _, locked1 = GetContainerItemInfo(bag1, slot1)
        local _, _, locked2 = GetContainerItemInfo(bag2, slot2)

        if(locked1 or locked2) then
                print(bag1, bag2, slot1, slot2)
                table.insert(waitTable, {bag1 = bag1, bag2 = bag2, slot1 = slot1, slot2 = slot2})
        else
                --print("Swapping bag", bag1, "slot", slot1, "......for bag", bag2, "slot", slot2)
                PickupContainerItem(bag1, slot1)
                PickupContainerItem(bag2, slot2)
        end
       
end


local function SortBag()
                local bagNr = 0
                for i = table.getn(AllItems), 1, -1 do
                        local currentTable = AllItems[i]
                        print(currentTable.itemName , 'CurSlot', currentTable.index ,'TargetSlot', i)
                        SaferSwapItems(0,0, currentTable.index, i)
                end
end


local frame = CreateFrame("FRAME", "FooAddonFrame");

local button
local ntex
local htex
local ptex


local function ADDON_LOADED()
        button = CreateFrame("Button", nil, UIParent)
        button:SetPoint("CENTER")
        button:SetWidth(100)
        button:SetHeight(25)

        button:SetText("Sort")
        button:SetNormalFontObject("GameFontNormal")

        ntex = button:CreateTexture()
        ntex:SetTexture("Interface/Buttons/UI-Panel-Button-Up")
        ntex:SetTexCoord(0, 0.625, 0, 0.6875)
        ntex:SetAllPoints()       
        button:SetNormalTexture(ntex)

        htex = button:CreateTexture()
        htex:SetTexture("Interface/Buttons/UI-Panel-Button-Highlight")
        htex:SetTexCoord(0, 0.625, 0, 0.6875)
        htex:SetAllPoints()
        button:SetHighlightTexture(htex)

        ptex = button:CreateTexture()
        ptex:SetTexture("Interface/Buttons/UI-Panel-Button-Down")
        ptex:SetTexCoord(0, 0.625, 0, 0.6875)
        ptex:SetAllPoints()
        button:SetPushedTexture(ptex)

        button:SetScript("OnClick", function()
               
                AllItems = {}
                GetAllItemsFromBag(AllItems)
                table.sort(AllItems, function(i, k)
                        return i.itemSellPrice > k.itemSellPrice
                end)
                SortBag()       

        end)
end



local function ITEM_LOCK_CHANGED(self, event, ...)
        if table.getn(waitTable) > 0 then
                local currentTable = waitTable[1]
                C_Timer.After(0.5, function() SaferSwapItems(currentTable.bag1, currentTable.bag2, currentTable.slot1, currentTable.slot2) end)
                waitTable = table.remove(waitTable, 1)
        end
end


local Events = {
        ["ADDON_LOADED"] = ADDON_LOADED,
        ["ITEM_LOCK_CHANGED"] = ITEM_LOCK_CHANGED
}

local function eventHandler(self, event, ...)
        if(Events[event]) then
                Events[event](...)
        end
end

frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("ITEM_LOCK_CHANGED");
frame:SetScript("OnEvent", eventHandler);


SDPhantom 12-15-19 11:31 PM

ITEM_LOCK_CHANGED fires when the lock state changes. BAG_UPDATE_DELAYED is what fires when items are added/deleted/moved in the bags.

loff93 12-16-19 08:47 AM

Quote:

Originally Posted by SDPhantom (Post 334785)
ITEM_LOCK_CHANGED fires when the lock state changes. BAG_UPDATE_DELAYED is what fires when items are added/deleted/moved in the bags.

ahh, good to know, thanks :)

the swapping script is not working correctly thought and I'm not sure how I'm gonna fix this.
Example: I have to click multiple times for items to get to the correct spot at times, and sometime it just won't help. I know why this happens, but I don't know how to get around it yet.
Trying to think of ways to swap them around, but I'm so new to Lua/WoW it's hard to think of something
Will update if I find a solution

*UPDATE*

This work as far as I can tell. Is it pretty? Not at all
Tips to improve is appreciated.

Code:

local AllItems = {}
local waitTable = {}

local function PrintAll() -- Debugging only, Ignore this
        print('------')
    for i = table.getn(AllItems), 1, -1
    do
        print(AllItems[i].itemName, AllItems[i].itemSellPrice)
        end
        print('------')
end

local function GetAllItemsFromBag()
        for bagnr = 0, NUM_BAG_SLOTS do
                for slotnr=1, GetContainerNumSlots(bagnr) do
                        local item = GetContainerItemID(bagnr, slotnr)
                        if(item) then
                                --print(item)
                                local _, _, _, _, _, _, _, _, _, itemID = GetContainerItemInfo(bagnr, slotnr)
                                --if(itemID ~= nil) then
                                        --print(itemID)
                                        local itemName, _, _, _, _, _, _, _, _, _, itemSellPrice = GetItemInfo(itemID)
                                        table.insert(AllItems, {index = slotnr, itemID = itemID, itemSellPrice = itemSellPrice, itemName = itemName, targetSlot = 0, targetBag = 0})
                                        --print(itemName, index)
                                --end
                        end
                end
        end
end

local function GetSlotNr(bagnr, item)
        for index=1, GetContainerNumSlots(bagnr) do
                local _, _, _, _, _, _, _, _, _, itemID = GetContainerItemInfo(bagnr, index)
                        if(item.itemID == itemID) then
                                return index;
                end
        end
end

local function GetBagNr(theItem)
        for bagnr = 0, NUM_BAG_SLOTS do
                for slotnr=1, GetContainerNumSlots(bagnr) do
                        local item = GetContainerItemID(bagnr, slotnr)
                        if(item) then
                                local _, _, _, _, _, _, _, _, _, itemID = GetContainerItemInfo(bagnr, slotnr)
                                if(theItem.itemID == itemID) then
                                        return bagnr
                                end
                        end
                end
        end
end

local function SaferSwapItems(item)
        ClearCursor()
        local bag1 = GetBagNr(item);
        local bag2 = item.targetBag;
        local slot1 = GetSlotNr(bag1, item)
        local slot2 = item.targetSlot
        if(item.itemID == 11584) then
                print(bag1, bag2, slot1, slot2)
                print(item.itemName,': Move From Bag',bag1,'Slot' , slot1, 'To Bag',bag2, 'Slot', slot2)
        end
        local _, _, locked1 = GetContainerItemInfo(bag1, slot1)
        local _, _, locked2 = GetContainerItemInfo(bag2, slot2)

        if(locked1 or locked2) then
                table.insert(waitTable, {itemID = item.itemID, itemName = item.itemName, targetSlot = item.targetSlot, targetBag = item.targetBag})
        else
                PickupContainerItem(bag1, slot1)
                PickupContainerItem(bag2, slot2)
        end
       
end

local function SortBag()
                local bagNr = 0
                for i = 1, table.getn(AllItems) do
                        local currentItem = AllItems[i]
                        SaferSwapItems(currentItem)
                end
end

local function GetSlotInBag(index)
        local currentTotalSlot = 0
        for bagnr = 0, NUM_BAG_SLOTS do
                for slotnr = 1, GetContainerNumSlots(bagnr) do
                        currentTotalSlot = currentTotalSlot + 1
                        if(index == currentTotalSlot) then
                                return slotnr
                        end
                end
        end
end

local function SetTargetSlot()
        for i = 1, table.getn(AllItems) do
                local currentItem = AllItems[i]
                currentItem.targetSlot = GetSlotInBag(i)
                print(currentItem.targetSlot)
        end
end



local function GetBag(index)
        local currentTotalSlot = 0
        for bagnr = 0, NUM_BAG_SLOTS do
                for slotnr = 1, GetContainerNumSlots(bagnr) do
                        currentTotalSlot = currentTotalSlot + 1
                        if(index == currentTotalSlot) then
                                return bagnr
                        end
                end
        end
end

local function SetTargetBag()
        for i = 1, table.getn(AllItems) do
                AllItems[i].targetBag = GetBag(i)
                --print(AllItems[i].itemName,'bag:', AllItems[i].targetBag)
        end
end

local function BAG_UPDATE_DELAYED(self, event, ...)
        if table.getn(waitTable) > 0 then
                local currentItem = waitTable[1]
                C_Timer.After(0.2, function() SaferSwapItems(currentItem) end)
                waitTable = table.remove(waitTable, 1)
        end
end

local frame = CreateFrame("FRAME", "FooAddonFrame");

local button
local ntex
local htex
local ptex


local function ADDON_LOADED()
        button = CreateFrame("Button", nil, UIParent)
        button:SetPoint("CENTER")
        button:SetWidth(100)
        button:SetHeight(25)

        button:SetText("Sort")
        button:SetNormalFontObject("GameFontNormal")

        ntex = button:CreateTexture()
        ntex:SetTexture("Interface/Buttons/UI-Panel-Button-Up")
        ntex:SetTexCoord(0, 0.625, 0, 0.6875)
        ntex:SetAllPoints()       
        button:SetNormalTexture(ntex)

        htex = button:CreateTexture()
        htex:SetTexture("Interface/Buttons/UI-Panel-Button-Highlight")
        htex:SetTexCoord(0, 0.625, 0, 0.6875)
        htex:SetAllPoints()
        button:SetHighlightTexture(htex)

        ptex = button:CreateTexture()
        ptex:SetTexture("Interface/Buttons/UI-Panel-Button-Down")
        ptex:SetTexCoord(0, 0.625, 0, 0.6875)
        ptex:SetAllPoints()
        button:SetPushedTexture(ptex)

        button:SetScript("OnClick", function()
               
                AllItems = {}
                GetAllItemsFromBag()
                table.sort(AllItems, function(i, k)
                        return i.itemSellPrice > k.itemSellPrice
                end)
                SetTargetBag()
                SetTargetSlot()
                --PrintAll()
                SortBag()       

        end)
end

local Events = {
        ["ADDON_LOADED"] = ADDON_LOADED,
        ["BAG_UPDATE_DELAYED"] = BAG_UPDATE_DELAYED
}

local function eventHandler(self, event, ...)
        if(Events[event]) then
                Events[event](...)
        end
end

frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("BAG_UPDATE_DELAYED");
frame:SetScript("OnEvent", eventHandler);

*Update*
Everything works, but 1 issue is that if I have multiple of the same items it and calculcate total price of itemcount * sellprice, it doesn't care what stack the orders are in


All times are GMT -6. The time now is 02:18 PM.

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