1. Post #1
    LaughingLeader's Avatar
    July 2011
    19 Posts
    I'm having a bit of trouble getting a table (in Tiramisu), filled with item data, to sort by it's category (in alphabetical order). I'm still fairly new to LUA and programming in general, so I'm not sure if I'm going about it the right way.

    The snippet that builds the business menu item data looks like this:


    business.lua


    CAKE.Business = {}
    
    
    --Copies all buyable items on the CAKE.Business table.
    function CAKE.BuildItemGroups()
    	local tbl = {}
    	for k,v in pairs(CAKE.ItemData) do
    		if !CAKE.Business[v.ItemGroup] then CAKE.Business[v.ItemGroup] = {} end
    		if v.Purchaseable then
    			tbl = {}
    			tbl.Class = v.Class
    			tbl.Model = v.Model
    			tbl.Name = v.Name
    			tbl.Description = v.Description .. "\nPrice: " .. v.Price
    			tbl.Price = v.Price
    			tbl.category = v.category
    			tbl.IconM = v.IconM
    			
    			--Category Sort
    			table.sort(tbl, function(a,b) 
    				return a.category > b.category 
    			end)
    			
    			--Test the results
    			 for k,v in pairs(tbl) do 
    			 print(k, v) 
    			 end
    			
    			table.insert(CAKE.Business[v.ItemGroup], tbl)
    		end
    	end
    end
    


    I've tried sorting the "tbl" table by category, and even the CAKE.Business menu by category, but both don't seem to sort when I do that. I haven't been getting any errors, but the item order doesn't go alphabetical. I've also double-checked to make sure the category key is working, and it is. It even shows up on the item tooltip via this:


    cl_inventory.lua
    --Sets an item to be used on the inventory slot. The item thing is a table, not a string. Amount defaults to 1.
    function PANEL:SetItem( item, amount )
    	self.Item = item
    	
    	if !self.Icon then
    		self.Icon = vgui.Create( "InventorySlot_Icon", self )
    		self:SetIconSize( self.IconSize )
    	end
    	-- Item tooltip. Added item.category.
    	if item.Description != "" then self:SetToolTip( "[" .. item.category .. "]" .. "\n" .. item.Name .. "\n" .. item.Description )
    	else self:SetToolTip( "[" .. item.category .. "]" .. "\n" .. item.Name ) end
    	-- Changes the Icon model to the "IconM" field if valid. 
    	if item.IconM == "" then self.Icon:SetModel( item.Model )
    	else self.Icon:SetModel( item.IconM ) end
    	
    	self:SetAmount( amount or 1 )
    	self:OnUseItem( item, amount )
    end
    


    The business menu actually builds the icons in this little snippet of code:


    cl_business.lua
    local icontable = {}
    
    
    for k, item in pairs( BusinessTable[buygroup] ) do
    	icontable[k] = vgui.Create( "InventorySlot" )
    	icontable[k]:SetIconSize( 48 )
    	icontable[k]:SetItem( item )				
    	icontable[k]:DisableDrag()
    	icontable[k].OnMousePressed = function()
    		icontable[k]:OpenMenu()
    	end
    	icontable[k].OnMouseReleased = function() end
    	icontable[k].OpenMenu = function()
    		local ContextMenu = DermaMenu()
    		ContextMenu:AddOption("Buy", function() LocalPlayer():ConCommand("rp_buyitem " .. icontable[k]:GetItem().Class ) end)
    		ContextMenu:Open()
    	end
    	icontable[k].PaintOver = function()
    		surface.SetTextColor(Color(255,255,255,255));
    		surface.SetFont("TirimisuTabsFont");
    		surface.SetTextPos( icontable[k]:GetWide() - 20, icontable[k]:GetTall() - 14);
    		surface.DrawText( icontable[k]:GetItem().Price or "0" )
    	end		
    	grid:AddItem( icontable[k] )
    		end										
    	end
    end
    


    So, I'm not sure if I've been going about this the right way, but I figured that sorting the table in the business.lua file would work, as then the code pulls that data and builds everything else. It doesn't seem to be working though, as the print output to the console isn't in alphabetical order (by category). It'll show zipties as first (category: Miscellaneous), then an Alcohol item, then some Weaponry, followed by random mixtures of other items. Also, any changes to how the sorting function compares the a.category and b.category just shifts the items around in a weird way.


    Any ideas on how to get this to work would be appreciated.

  2. Post #2
    skullorz's Avatar
    May 2009
    930 Posts
    G.SortedPairs

    Sorts through a table's keys from lowest to highest, starting with numbers.

    G.SortedPairsByValue

    This goes by value of the key.

    G.SortedPairsByMemberValue

    This goes by member of a table. Syntax is SortedPairsByMemberValue(table,member)

  3. Post #3
    LaughingLeader's Avatar
    July 2011
    19 Posts
    Unfortunately, that's giving me an error:

    			for k, v in SortedPairsByMemberValue(tbl, "category") do
    			print(k, v.category)
    			end
    

     Hook 'TiramisuBuildItemGroups' Failed: [lua\includes\extensions\table.lua:478] attempt to index local 'v' (a string value)

    Here's the hook (it just calls the CAKE.BuildItemGroups() function I've been messing with):

    hook.Add( "InitPostEntity", "TiramisuBuildItemGroups", function() 
    	CAKE.BuildItemGroups()
    end)

    Line 478 of table.lua is v.__key = k in this:

    
    *---------------------------------------------------------
       Name: table.ClearKeys( table, bSaveKey )
       Desc: Clears the keys, converting to a numbered format
    ---------------------------------------------------------*/
    function table.ClearKeys( Table, bSaveKey )
    
    	local OutTable = {}
    	
    	for k, v in pairs( Table ) do
    		if ( bSaveKey ) then
    			v.__key = k
    		end
    		table.insert( OutTable, v )	
    	end
    	
    	return OutTable
    
    end
    

    SortedPairsByMemberValue calls table.ClearKeys:

    /*---------------------------------------------------------
       A Pairs function
    
    		Sorted by Member Value (All table entries must be a table!)
    		
    ---------------------------------------------------------*/
    function SortedPairsByMemberValue( pTable, pValueName, Desc )
    
    	Desc = Desc or false
    	
    	local pSortedTable = table.ClearKeys( pTable, true )
    	
    	table.SortByMember( pSortedTable, pValueName, !Desc )
    	
    	local SortedIndex = {}
    	for k, v in ipairs( pSortedTable ) do
    		table.insert( SortedIndex, v.__key )
    	end
    	
    	pTable.__SortedIndex = SortedIndex
    
    	return fnPairsSorted, pTable, nil
    	
    end
    

    Maybe I shouldn't bother with trying to organize the table right here, but rather when the function generates the icons?