--Needs a tidy!
--Check the bag datais valid.
if SB==nil then SB={} end
if SB.x==nil then SB.x=100 end --}
if SB.y==nil then SB.y=100 end --}Position
if SB.icx==nil then SB.icx=4 end --]
if SB.icy==nil then SB.icy=3 end --]Size, in icons
if SB.override==nil then SB.override=false end --Override default bags?
if SB.labelwidth==nil then SB.labelwidth=80 end --Width of the text label for the group.
if SB.font==nil then SB.font="TrajanPro14" end --Label font
if SB.ShowItem==nil then SB.ShowItem=true end --un-hide a group when an item is looted in it?
--font size
SB.fontsize=string.sub(SB.font,-2)
if SB.fontsize=="ed" then SB.fontsize=13-1 else SB.fontsize=tonumber(SB.fontsize)-1 end
--Frame padding
pad={top=30,side=15,bottom=10}
--Calculate width and maximum height for the bag.
SB.width=SB.labelwidth+36*SB.icx+2*pad.side
SB.maxheight=Turbine.UI.Display.GetHeight()
--Functions
--Set the sizes of all the areas of the bag.
function SortBagSetSize()
SortBag.ListBox:SetSize( SB.labelwidth+SB.icx*36, SortBag:GetHeight()-(pad.top+pad.bottom)+1)
SortBag.ScrollBar:SetPosition(SB.labelwidth+SB.icx*36+10,pad.top+5)
SortBag.ScrollBar:SetHeight(SortBag:GetHeight()-(pad.top+pad.bottom)-10)
SortBag.Resize:SetPosition(SB.width-10,pad.top+10)
SortBag.Resize:SetSize(10,SortBag:GetHeight()-2*pad.top-10)
SortBag.ResizeBack:SetSize(10,SortBag:GetHeight()-pad.top-pad.bottom)
Search.label:SetSize(SB.labelwidth,SB.fontsize)
end
--Adjust the sizes of the GroupBoxes.
function SetGroupBoxSize()
if GroupBox==nil then return end
local height=0
for j=0,#Groups do
--Adjust GroupBox Widths
GroupBox[j]:SetMaxItemsPerLine(SB.icx)
GroupBox[j]:SetWidth(SB.icx*36)
--Hide the slot, or adjust its height
if Groups[j].hide then
GroupBox[j]:SetHeight(0)
GroupBox[j].label:SetBackColor(Turbine.UI.Color( 1,0.4,0,0 ))
else
GroupBox[j]:SetHeight( math.ceil(GroupBox[j]:GetItemCount()/SB.icx)*36)
GroupBox[j].label:SetBackColor(Turbine.UI.Color( 1,0,0,0.4 ))
end
--Adjust Label Width,Height
GroupBox[j].label:SetWidth(SB.labelwidth)
if GroupBox[j]:GetItemCount()>0 then
GroupBox[j].label:SetHeight(SB.fontsize)
else
GroupBox[j].label:SetHeight(0)
end
--Add to the height variable
height=height+math.max(GroupBox[j]:GetHeight(),GroupBox[j].label:GetHeight())
end
if height>SB.maxheight-(pad.top+pad.bottom) then height=SB.maxheight-(pad.top+pad.bottom) end
--Resize the window to fit the new height NOTE: The SB.fontsize is to accomodate the "search" box
SortBag:SetHeight(height+pad.top+pad.bottom+SB.fontsize)
--Change the title to show how many empty slots are left
SortBag:SetText(GroupBox[0]:GetItemCount().." empty slots left")
end
--Search function now added to the bag!
Search={}
Search.label=Turbine.UI.Label()
Search.label:SetBackColor( Turbine.UI.Color( 1,0.1,0.1,0.1 ) )
Search.label:SetMultiline(true)
Search.label:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter )
Search.label:SetMouseVisible (true)
Search.label:SetSize(SB.labelwidth,SB.fontsize)
Search.Textbox=Turbine.UI.TextBox()
Search.Textbox:SetSize(200,SB.fontsize)
--When focus is gained turn updating on so that the plugin will scan the text entered.
Search.Textbox.FocusGained=function()
Search.Textbox:SetWantsUpdates(true)
SearchString=Search.Textbox:GetText()
end
Search.Textbox.FocusLost=function()
Search.Textbox:SetWantsUpdates(false)
end
Search.Textbox.Update = function()
SearchBag()
end
function SearchBag()
if SearchString ~= Search.Textbox:GetText() then
SearchString = Search.Textbox:GetText()
--remove odd characters
txt1=string.lower(SearchString)
for i=1,size do
local item = backpack:GetItem(i)
if item~=nil then
local txt2=string.lower(item:GetName())
if string.find(txt2,txt1) then
BackpackSlots[i]:SetVisible(true)
else
BackpackSlots[i]:SetVisible(false)
end
end
end
end
end
--populate the bag.
function populatebag()
SortBag.ListBox:ClearItems()
--Add the search section. Fonts applied here too.
SortBag.ListBox:AddItem(Search.label)
SortBag.ListBox:AddItem(Search.Textbox)
Search.Textbox:SetFont(Turbine.UI.Lotro.Font[SB.font])
Search.label:SetFont(Turbine.UI.Lotro.Font[SB.font])
Search.label:SetText( "Search" )
GroupBox={}
BackpackSlots=nil
BackpackSlots={}
--Check for font size errors
if SB.labelwidth<SB.fontsize then SB.labelwidth=SB.fontsize end
--Build VirtPack
VirtPack=analysepack()
---Build a box for this group of items. Box 0 is for empty slots.
for i=0,#Groups do
GroupBox[i] = Turbine.UI.ListBox()
GroupBox[i]:SetOrientation( Turbine.UI.Orientation.Horizontal )
GroupBox[i]:SetAllowDrop( true )
GroupBox[i].DragDrop = function( sender, args )
--Empty slots allow drag-drop. Hopefully!
local shortcut = args.DragDropInfo:GetShortcut();
if ( shortcut ~= nil ) then
local item = GroupBox[i]:GetItemAt( args.X, args.Y );
local index
if item==nil then index=1 else index= item.id end
backpack:PerformShortcutDrop( shortcut, index, Turbine.UI.Control.IsShiftKeyDown() )
end
end
end
--Build the backpack Slots.
for i=1,size do
item = backpack:GetItem(i)
if item~=nil then AddCallback(item, "QuantityChanged", BagQuantityChanged) end
BackpackSlots[i]=Turbine.UI.Lotro.ItemControl( item )
BackpackSlots[i].id=i --so it can be passed for item swopping.
BackpackSlots[i]:SetBackground( "JackdawPlugins/SortPack/Back.tga" )
BackpackSlots[i]:SetBlendMode( Turbine.UI.BlendMode.Overlay )
end
--Move the items into the boxes
for i=1,#VirtPack do
--if i<10 then Turbine.Shell.WriteLine(VirtPack[i].id) end --Re-enable if the "not sorting correctly" bug rears its head again.
BackpackSlots[VirtPack[i].id].Group=VirtPack[i].Group
GroupBox[VirtPack[i].Group]:AddItem(BackpackSlots[VirtPack[i].id])
end
--Add the groups to the backpack
for j=0,#Groups do
--Build a label
GroupBox[j].label=Turbine.UI.Label()
GroupBox[j].label:SetBackColor( Turbine.UI.Color( 1,0,0,0.4 ) )
GroupBox[j].label:SetFont(Turbine.UI.Lotro.Font[SB.font])
GroupBox[j].label:SetMultiline(true)
GroupBox[j].label:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter )
GroupBox[j].label:SetText( Groups[j].Name )
GroupBox[j].label:SetMouseVisible (true)
GroupBox[j].label:SetSize(SB.labelwidth,0)--Initially of height 0
GroupBox[j].label.label=true
if j~=0 then
--Add the label and GroupBox, but not for empty slots
SortBag.ListBox:AddItem(GroupBox[j].label)
SortBag.ListBox:AddItem(GroupBox[j])
end
--Click events for the labels.
GroupBox[j].label.MouseClick=function(sender,args)
if ( args.Button == Turbine.UI.MouseButton.Left ) then
--Left Clicking the label collapses this group
Groups[j].hide=not(Groups[j].hide)
else
--Right clicking either collapses all groups, if this one is shown, or opens all groups if not.
Groups[j].hide=not(Groups[j].hide)
for i=0,#Groups do
Groups[i].hide=Groups[j].hide
end
end
SetGroupBoxSize()
end
end
--Empty Slots group added last.
SortBag.ListBox:AddItem(GroupBox[0].label)
SortBag.ListBox:AddItem(GroupBox[0])
--Function refresh the heights of the group boxes
SetGroupBoxSize()
end
--Show the backpack
function openbag()
--Clear out any previous search
Search.Textbox:SetText("")
SearchString=""
for i=1,size do BackpackSlots[i]:SetVisible(true) end
--Show the bag!
SortBag:SetVisible(true)
end
--Events here replace the default bags with this one.
function SBOverride()
if SB.override then SortBag:SetWantsKeyEvents( true );
SortBag.KeyDown = function( sender, args )
if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
SortBag:Close()
end
if ( args.Action == Turbine.UI.Lotro.Action.ToggleBags or
args.Action == Turbine.UI.Lotro.Action.ToggleBag1 or
args.Action == Turbine.UI.Lotro.Action.ToggleBag2 or
args.Action == Turbine.UI.Lotro.Action.ToggleBag3 or
args.Action == Turbine.UI.Lotro.Action.ToggleBag4 or
args.Action == Turbine.UI.Lotro.Action.ToggleBag5 )
then
if SortBag:IsVisible() then
SortBag:Close()
else
openbag()
end
end
end
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack1, false )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack2, false )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack3, false )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack4, false )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack5, false )
else
SortBag:SetWantsKeyEvents( false )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack1, true )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack2, true )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack3, true )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack4, true )
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack5, true )
end
end
--Next three items update the bag if items are added or removed.
BagAdd=function( sender, args )
--Turbine.Shell.WriteLine("BagAdd "..args.Index..args.Item:GetName())
--args.Index = Bag slot
--args.Item = Item object
--Remove the slot from the group it is in.
for i=0,#Groups do
if GroupBox[i]:ContainsItem(BackpackSlots[args.Index]) then GroupBox[i]:RemoveItem(BackpackSlots[args.Index]) end
end
--Determine which group it belongs to
local destination=ItemGroup[ItemCategory[args.Item:GetCat()]]
if destination==nil then destination=0 end
--Insert the item in that group
BackpackSlots[args.Index]:SetItem(args.Item)
BackpackSlots[args.Index].Group=destination
GroupBox[destination]:InsertItem(position,BackpackSlots[args.Index])
if destination~=0 then
--Remove every item from that groupbox one at a time and resort them.
local temp={}
--cycle through the elements checking for weights
for i=GroupBox[destination]:GetItemCount(),1,-1 do
temp[i]=GroupBox[destination]:GetItem(i)
temp[i].Weight=weight(temp[i].id)
temp[i].Name=GroupBox[destination]:GetItem(i):GetItem():GetName()
end
--Remove all the items
GroupBox[destination]:ClearItems()
--Sort the items according to weight (ignoring alpha. I am happy with this compromise)
table.sort(temp, function (a,b)
if a.Weight == b.Weight then
--return a.Name < b.Name
--return strip(a.Name)< strip(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)
--Put the items in the group
for i=1,#temp do
GroupBox[destination]:AddItem(temp[i])
end
end
--Refresh heights
SetGroupBoxSize()
--Add the quantity changed event
AddCallback(args.Item, "QuantityChanged", BagQuantityChanged)
unhide(args.Item)
end
BagRemove=function( sender, args )
--Turbine.Shell.WriteLine("BagRemove "..args.Index)
--Note: this is sometimes called when looting *and no item is removed* causing the "empty slot" bug. Annoying, and not my fault!
--Also called if a stack is merged.
--args.Index = Bag slot
--Remove the quantity changed callback
item = backpack:GetItem(args.Index)
RemoveCallback(item, "QuantityChanged", BagQuantityChanged)
--Remove item from group
GroupBox[BackpackSlots[args.Index].Group]:RemoveItem(BackpackSlots[args.Index])
--Make the item for that slot nil
BackpackSlots[args.Index]:SetItem(nil)
BackpackSlots[args.Index].Group=0
--Add it to empty slots.
GroupBox[0]:AddItem(BackpackSlots[args.Index])
--Refesh Heights
SetGroupBoxSize()
end
BagMove=function( sender, args )
--15/12/11 This has changed completely! The notes below are now false.
--Turbine.Shell.WriteLine("BagMove Old Index"..args.OldIndex.." New Index "..args.NewIndex)
--[[
1) If an item has just been moved to an empty slot then just this fires.
2) If an item has been swopped with another; Say A in slot n1 with B in slot n2
ItemRemoved fires on slot n1
ItemMoved fires with B from n2 to n1
ItemAdded fires on slot n2 with item A
Essentially, item A (the moved item) gets held "in hand" making the target slot empty.
Recently I have come to the belief that it is this that causes the bug, and not ItemRemoved.
]]
--args.Item =Item object of the item that has been moved.
--args.NewIndex =Target Slot
--args.OldIndex =Destination Slot
BackpackSlots[args.NewIndex],BackpackSlots[args.OldIndex]=BackpackSlots[args.OldIndex],BackpackSlots[args.NewIndex]
--Refresh heights
SetGroupBoxSize()
end
BagQuantityChanged=function(sender,args)
unhide(sender)
end
function unhide(item)
if not(SB.ShowItem) then return end
local destination=ItemGroup[ItemCategory[item:GetCat()]]
--Turbine.Shell.WriteLine(item:GetName().." "..destination.." "..Groups[destination].Name)
if destination==nil then destination=0 end
--Un-Hide this group
if Groups[destination].hide then
Groups[destination].hide=false
SetGroupBoxSize()
end
end
AddCallback(backpack, "ItemAdded", BagAdd)
AddCallback(backpack, "ItemRemoved", BagRemove)
AddCallback(backpack, "ItemMoved", BagMove)
--Main Structure; Create the window to hold the backpack slots and populate it.
SortBag = Turbine.UI.Lotro.Window()
SortBag:SetPosition( SB.x,SB.y )
SortBag:SetText("SortBag")
SortBag.ListBox = Turbine.UI.ListBox()
SortBag.ListBox:SetParent( SortBag )
SortBag.ListBox:SetPosition( pad.side, pad.top )
SortBag.ListBox:SetMaxItemsPerLine(2)
SortBag.ListBox:SetOrientation( Turbine.UI.Orientation.Horizontal )
SortBag.ScrollBar=Turbine.UI.Lotro.ScrollBar()
SortBag.ScrollBar:SetOrientation( Turbine.UI.Orientation.Vertical )
SortBag.ListBox:SetVerticalScrollBar( SortBag.ScrollBar )
SortBag.ScrollBar:SetParent(SortBag)
SortBag.ScrollBar:SetPosition(SB.labelwidth+SB.icx*36+10,pad.top+5)
SortBag.ScrollBar:SetWidth(10)
--Remove this control when Turbine fix the backpack bug. again.
SortBag.Control=Turbine.UI.Control()
SortBag.Control:SetParent(SortBag)
SortBag.Control:SetMouseVisible(true)
SortBag.Control:SetBackground(0x41007e26)
SortBag.Control:SetSize(16,16)
SortBag.Control:SetPosition(pad.side-15,pad.top-15)
SortBag.Control.MouseClick=function()
--This was, originally, in Button.lua. And is better there imho.
local contextMenu = Turbine.UI.ContextMenu()
contextMenu.items = contextMenu:GetItems()
local option2=Turbine.UI.MenuItem("Re-stack the items - WARNING! EXPERIMENTAL!",true)
option2.Click = function () import "JackdawPlugins.SortPack.Stack" Turbine.Shell.WriteLine("<rgb=#888888>Starting stack") Stack() end
local option3=Turbine.UI.MenuItem("Override default bags",true,SB.override)
option3.Click = function () SB.override=not(SB.override) SBOverride() end
local option4=Turbine.UI.MenuItem("Open the sort order panel",true)
option4.Click = function () import"JackdawPlugins.SortPack.ListOption" ShowListOption() end
local option6=Turbine.UI.MenuItem("Create/Edit custom Categories",true)
option6.Click = function () import"JackdawPlugins.SortPack.CustomOption" ShowCustomOption() end
local option7=Turbine.UI.MenuItem("Show a group on item gain.",true,SB.ShowItem)
option7.Click = function () SB.ShowItem=not(SB.ShowItem) end
local option5 = Turbine.UI.MenuItem("Select SortBag label font;")
contextMenu.SubMenuItems = option5:GetItems()
local suboption5={}
local font={}
j=1
for i in pairs(Turbine.UI.Lotro.Font) do
font[j]=i
j=j+1
end
table.sort(font, function (a,b)
return (a < b)
end)
for i=1,#font do
suboption5[i] = Turbine.UI.MenuItem(font[i],true,font[i]==SB.font)
suboption5[i].Click = function ()
SB.font=font[i]
SB.fontsize=string.sub(SB.font,-2)
if SB.fontsize=="ed" then SB.fontsize=13-1 else SB.fontsize=tonumber(SB.fontsize)-1 end
populatebag()
end
contextMenu.SubMenuItems:Add(suboption5[i])
end
contextMenu.items:Add(option2)
contextMenu.items:Add(option5)
contextMenu.items:Add(option3)
contextMenu.items:Add(option7)
contextMenu.items:Add(option4)
contextMenu.items:Add(option6)
contextMenu:ShowMenu()
end
SortBag.Resize=Turbine.UI.Control()
SortBag.Resize:SetParent(SortBag)
SortBag.Resize:SetZOrder(99)
SortBag.ResizeBack=Turbine.UI.Control()
SortBag.ResizeBack:SetParent(SortBag.Resize)
SortBag.ResizeBack:SetBackColor(Turbine.UI.Color(0.7,0.3,0.3,1))
SortBag.ResizeBack:SetVisible(false)
SortBag.ResizeBack:SetMouseVisible(false)
SortBag.Resize.MouseEnter=function() SortBag.ResizeBack:SetVisible(true) end
SortBag.Resize.MouseLeave=function() SortBag.ResizeBack:SetVisible(false) end
SortBag.Resize.MouseDown=function ()
draggingr=true
end
SortBag.Resize.MouseUp=function ()
draggingr=false
end
SortBag.Resize.MouseMove=function(sender,args)
if draggingr then
local oldwidth=SB.width
SB.width,dummy=SortBag:GetMousePosition()
if SortBag:IsAltKeyDown() then
SB.labelwidth=SB.width-oldwidth+SB.labelwidth
if SB.labelwidth<SB.fontsize then SB.labelwidth=SB.fontsize end
else
SB.icx=math.floor((SB.width-2*pad.side-SB.labelwidth)/36)
SB.icy=math.floor((SB.maxheight-(pad.top+pad.bottom))/36)
if SB.icx<3 then SB.icx=3 end
if SB.icy<1 then SB.icy=1 end
end
SB.width=36*SB.icx+2*pad.side+SB.labelwidth
SortBag:SetSize(SB.width,SB.maxheight)
end
end
SortBag.SizeChanged=function()
SortBagSetSize()
SetGroupBoxSize()
--Now, if the size of the bag would take the bottom of the bag off the screen, then re-position it.
local x,y=SortBag:GetPosition()
if y+SortBag:GetHeight()>SB.maxheight then y=SB.maxheight-SortBag:GetHeight() end
SortBag:SetPosition(x,y)
end
SortBag:SetSize(SB.width,SB.maxheight)
SortBag.PositionChanged=function()
local x,y=SortBag:GetPosition()
if x<0 then x=0 end
if y<0 then y=0 end
SortBag:SetPosition(x,y)
SB.x,SB.y=x,y
end
populatebag()
SBOverride()