function Sort()
--If the bag function is enabled then close the sortbag before sorting and open it again when finished. Stops lots of errors.
if SortBag~=nil then
if SortBag:IsVisible() then Turbine.Shell.WriteLine("Sortbag window closed on sorting. Open again after sort.") SortBag:Close() closedsortbag=true end
end
--An attempt to make as many variables local to this proc as possible. May avoid the crash? Either way it "feels" right to have as much data disappear as possible.
local VirtPack
local item
local Category
local CategoryText
local CatWeight
local FirstStart
local Name
local Quality
local QualWeight
local Slot
local Start
Timer=Turbine.UI.Control()
function Timer:Start()
Turbine.Shell.WriteLine("<rgb=#888888>Sort Started")
FirstStart= Turbine.Engine.GetGameTime()
VirtPack=analysepack()
Slot=1
Start= Turbine.Engine.GetGameTime()
Timer:SetWantsUpdates(true)
end
function Timer:Update()
local Time = Turbine.Engine.GetGameTime()
local elapsed = Time - Start
if Slot>size then
Timer:SetWantsUpdates(false)
--If sortbag is loaded and the window was open before sorting, then open it again.
if SortBag~=nil then
if closedsortbag then closedsortbag=nil openbag() end
end
Timer=nil
Turbine.Shell.WriteLine("<rgb=#888888>Sort finished after "..Time-FirstStart.." seconds.")
return
end
--Get the name of the target item
target=VirtPack[Slot].Name
--Get item in current slot
item=backpack:GetItem(Slot)
--Get the name of the item in the current slot. If empty return that name as "zEmpty"
if item~=nil then Name=item:GetName() else Name="zEmpty" end
--Turbine.Shell.WriteLine("<rgb=#888888>Slot "..Slot.." should contain "..target.." but contains ".. Name)
--If the Name of the current item is equal to the target name, move on.
if Name==target then Slot=Slot+1 return end
if elapsed>0.2 then
--Search for the item in the rest of the pack.
for i=Slot+1,size do
item=backpack:GetItem(i)
if item~=nil then item=item:GetName() else item="zEmpty" end
if item==target then
swop(i,Slot)
Start= Turbine.Engine.GetGameTime()
return
end
end
Turbine.Shell.WriteLine("<rgb=#888888>Should never get here! Error in Update function. Did your inventory change during the sort? Restarting!")
Timer:SetWantsUpdates(false)
Timer:Start()
end
end
function swop(i,j)
if backpack:GetItem(j)==backpack:GetItem(i) then return end
item=backpack:GetItem(j)
if item~=nil then
backpack:PerformItemDrop(item,i, false)
return
end
item=backpack:GetItem(i)
if item~=nil then
backpack:PerformItemDrop(item,j, false)
return
end
Turbine.Shell.WriteLine("<rgb=#888888>Should never be seen. Error in Swop function.")
Timer:SetWantsUpdates(false)
Timer:Start()
end
Timer:Start()
end
function weight(i)
--Calculate the weight
local Weight = 0
item = backpack:GetItem(i)
if item == nil then
--Empty slots have no name, quality, category etc
Category=0
Quality=0
else
Category=item:GetCategory()
Quality=item:GetQuality()
if Quality==nil then Quality=0 end
end
CategoryText=ItemCategory[Category]
if CategoryText~=nil then
CatWeight=value[CategoryText] --First scan the CategoryText using the value table
else
--This item has not been given a category number by turbine - it is missing from the category text list.
Turbine.Shell.WriteLine("<rgb=#888888>"..item:GetName().." has not been given category text by Turbine. Dammit. It's number is "..Category.." Please inform MrJackdaw!")
end
QualWeight=Quality
Weight=CatWeight*100+QualWeight
if item==nil then Weight = 99999 end
return Weight
end
function strip(str)
--Strip numbers first 7 characters to make the sort more logical
local left=string.sub(str, 1, 7)
local right=string.sub(str, 8)
left=string.gsub(left,"[^%a]","")
str= left .. right
--Strip all spaces now!
str=string.gsub(str,"[%s]","")
return str
end
function analysepack()
local VirtPack={}
for i=1,size do
VirtPack[i]={}
VirtPack[i].id=i
item = backpack:GetItem(i)
if item~=nil then
--Data that may be useful...
VirtPack[i].Name=item:GetName()
VirtPack[i].Group=ItemGroup[ItemCategory[item:GetCategory()]]
else
VirtPack[i].Name="zEmpty"
VirtPack[i].Group=0
end
VirtPack[i].Weight=weight(i)
end
--Sort VirtPack. If the weight of two items is the same compare the Names, after removing some characters. This way "2 Morale Potions" will get sorted with "Morale Potions"
table.sort(VirtPack, function (a,b)
if a.Weight == b.Weight then
--return a.Name < b.Name
if revorder then return strip(a.Name)> strip(b.Name) else return strip(a.Name)< strip(b.Name) end
else
if revorder then return (a.Weight > b.Weight) else return (a.Weight < b.Weight) end
end
end)
return VirtPack
end