From f2084d93218a892973ceba8a4fa41fb1127729a4 Mon Sep 17 00:00:00 2001 From: AlmTech Software Date: Wed, 1 Jan 2020 21:25:31 +0100 Subject: [PATCH] Added item dropping, using, equiping (CLIENT) --- gamemode/engine/core/client/cl_fonts.lua | 18 ++ .../engine/derma/lib/cl_menu_iteminfo.lua | 261 +++++++++++++++++- gamemode/engine/derma/lib/cl_menu_theme.lua | 24 +- gamemode/engine/derma/menus/menu_charinfo.lua | 52 +++- gamemode/engine/lib/server/sv_inventory.lua | 2 +- gamemode/settings/sh_items.lua | 2 +- 6 files changed, 341 insertions(+), 18 deletions(-) diff --git a/gamemode/engine/core/client/cl_fonts.lua b/gamemode/engine/core/client/cl_fonts.lua index 31d3e55..69cab84 100644 --- a/gamemode/engine/core/client/cl_fonts.lua +++ b/gamemode/engine/core/client/cl_fonts.lua @@ -113,4 +113,22 @@ surface.CreateFont( "q_item_amount", { font = "Cambria Bold", size = 22 * Quantum.Client.ResolutionScale, antialias = true +}) + +surface.CreateFont( "q_item_option_button", { + font = "Cambria", + size = 24 * Quantum.Client.ResolutionScale, + antialias = true +}) + +surface.CreateFont( "q_item_option_dropbutton", { + font = "Cambria", + size = 28 * Quantum.Client.ResolutionScale, + antialias = true +}) + +surface.CreateFont( "q_item_option_dropval", { + font = "Cambria", + size = 40 * Quantum.Client.ResolutionScale, + antialias = true }) \ No newline at end of file diff --git a/gamemode/engine/derma/lib/cl_menu_iteminfo.lua b/gamemode/engine/derma/lib/cl_menu_iteminfo.lua index 412e9aa..2ddc2cf 100644 --- a/gamemode/engine/derma/lib/cl_menu_iteminfo.lua +++ b/gamemode/engine/derma/lib/cl_menu_iteminfo.lua @@ -13,6 +13,252 @@ local padding_s = math.Round( 4 * scale ) local theme = Quantum.Client.Menu.GetAPI( "theme" ) +local function resizePanel( p ) + p:SizeToChildren( true, true ) + p.w, p.h = p:GetSize() + p:SetSize( p.w + padding_s, p.h + padding_s ) + p.w, p.h = p:GetSize() + return p.w, p.h +end + +function iteminfo.dropamount( p, page, itemPanel ) + local index = p.index + local item = p.item + local amountInSlot = p.amount + + local dropAmount = 0 + + local back = vgui.Create( "DPanel", page ) + back:SetSize( page:GetSize() ) + back.w, back.h = back:GetSize() + back.Paint = function( self ) theme.renderblur( self, 4, 8 ) end + + local dp = vgui.Create( "DPanel", back ) + dp:SetSize( 300 * scale, 120 * scale ) + dp.w, dp.h = dp:GetSize() + dp:SetPos( back.w/2 - dp.w/2, back.h/2 - dp.h/2 ) + dp.Paint = function( self ) theme.sharpblurpanel( self ) end ---- DROP NET HERE ---- + + local spacing = padding*4 + + local amountEntry = vgui.Create( "DNumberWang", dp ) + amountEntry:SetValue( amountInSlot ) + amountEntry:SetFont( "q_item_option_dropval" ) + amountEntry:SetTextColor( Color( 255, 255, 255, 255 ) ) + amountEntry:SizeToContents() + amountEntry.w, amountEntry.h = amountEntry:GetSize() + amountEntry:SetSize( amountEntry.w + padding, amountEntry.h + padding ) + amountEntry.w, amountEntry.h = amountEntry:GetSize() + amountEntry:SetContentAlignment( 5 ) + + amountEntry:SetPos( dp.w/2 - amountEntry.w/2, dp.h/2 - amountEntry.h/2 ) + amountEntry.Paint = function( self ) + self:DrawTextEntryText( Color( 255, 255, 255, 255 ), Color( 200, 200, 200, 255 ), Color( 150, 150, 150, 255 ) ) + theme.borderpanel( self, Color( 150, 150, 150, 190 ) ) + end + + amountEntry:SetMax( amount ) + amountEntry:SetMin( 1 ) + amountEntry:SetDecimals( 0 ) + + local drop = vgui.Create( "DButton", dp ) + drop:SetText( "Drop" ) + drop:SetFont( "q_item_option_dropbutton" ) + drop:SizeToContents() + drop.w, drop.h = drop:GetSize() + drop:SetPos( spacing, dp.h - drop.h - padding ) + drop.x, drop.y = drop:GetPos() + + drop.Paint = function( self ) theme.iteminfobutton( self ) end + drop.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + back:Remove() + + dropAmount = math.Clamp( amountEntry:GetValue(), 1, amountInSlot ) + + if( dropAmount >= item.stack && itemPanel != nil ) then + itemPanel.RemoveItem() + else + itemPanel.SetItemAmount( amountInSlot - dropAmount ) + end + + ---- DROP NET HERE ---- + + end + + local cancel = vgui.Create( "DButton", dp ) + cancel:SetText( "Cancel" ) + cancel:SetFont( "q_item_option_dropbutton" ) + cancel:SizeToContents() + cancel.w, cancel.h = cancel:GetSize() + cancel:SetPos( dp.w - cancel.w - spacing, dp.h - cancel.h - padding ) + cancel.x, cancel.y = cancel:GetPos() + + cancel.Paint = function( self ) theme.iteminfobutton( self ) end + cancel.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + back:Remove() + end + +end + +function iteminfo.giveoptions( p, page ) + + local itemPanel = p:GetParent() + local index = itemPanel.index + local item = itemPanel.item + local amount = item.amount + local parWidth, parHeight = itemPanel:GetSize() + + local options = vgui.Create( "DPanel", page ) + options:SetSize( 100 * scale, 80 * scale ) + options.w, options.h = options:GetSize() + + options.item = item + options.amount = amount + options.index = index + + options:SetVisible( false ) + options.Paint = function( self ) + theme.iteminfopanel( self ) + end + options.Open = function() + page.showtooltips = false + if( page.shownOption != nil ) then + page.shownOption:SetVisible( false ) + page.shownOption:SetPos( 0, 0 ) + end + page.shownOption = options + options.w, options.h = resizePanel( options ) -- resize itself so everything fits + options:SetVisible( true ) + options:SetPos( gui.MouseX() - options.w/2, gui.MouseY() - ( options.h + padding ) ) + end + options.Close = function() + if( page.shownOption == options ) then + page.shownOption = nil + page.showtooltips = true + options:SetVisible( false ) + options:SetPos( 0, 0 ) + elseif( page.shownOption != nil ) then + page.shownOption.Close() + end + end + ---- all of the option panels ---- + local xbasepos, ybasepos = padding_s, padding_s -- everything needs to be a bit to the side on both axises + + local ypos = ybasepos + local yspacing = padding/4 + + local op = {} + + ---- Allways create the title for the item ---- + op.title = vgui.Create( "DLabel", options ) + op.title:SetText( item.name || "ERROR name=nil" ) + op.title:SetTextColor( theme.color.setalpha( item.rarity.color || Color( 255, 255, 255, 255 ), 255 ) ) + op.title:SetFont( "q_tooltip_title" ) + op.title:SizeToContents() + op.title.w, op.title.h = op.title:GetSize() + op.title:SetPos( xbasepos, ypos ) + op.title.x, op.title.y = op.title:GetPos() + + ypos = ypos + op.title.h + yspacing -- do the spacing thing + + if( item.equipable ) then -- Equip + + op.equip = vgui.Create( "DButton", options ) + op.equip:SetText( "Equip" ) + op.equip:SetFont( "q_item_option_button" ) + op.equip:SizeToContents() + op.equip.w, op.equip.h = op.equip:GetSize() + op.equip:SetPos( xbasepos, ypos ) + op.equip.x, op.equip.y = op.equip:GetPos() + op.equip.Paint = function( self ) + theme.iteminfobutton( self ) + end + op.equip.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + options.Close() + + ---- EQUIP NET HERE ---- + end + ypos = ypos + op.equip.h + yspacing + + elseif( item.usefunction != nil ) then + + op.use = vgui.Create( "DButton", options ) + op.use:SetText( "Use Item" ) + op.use:SetFont( "q_item_option_button" ) + op.use:SizeToContents() + op.use.w, op.use.h = op.use:GetSize() + op.use:SetPos( xbasepos, ypos ) + op.use.x, op.use.y = op.use:GetPos() + op.use.Paint = function( self ) + theme.iteminfobutton( self ) + end + op.use.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + + p:GetParent().RemoveItem() + + options.Close() + + ---- USE NET HERE ---- + end + ypos = ypos + op.use.h + yspacing + + elseif( !item.soulbound ) then -- Drop + op.drop = vgui.Create( "DButton", options ) + op.drop:SetText( "Drop" ) + op.drop:SetFont( "q_item_option_button" ) + op.drop:SizeToContents() + op.drop.w, op.drop.h = op.drop:GetSize() + op.drop:SetPos( xbasepos, ypos ) + op.drop.x, op.drop.y = op.drop:GetPos() + op.drop.Paint = function( self ) + theme.iteminfobutton( self ) + end + op.drop.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + options.Close() + + if( amount > 1 ) then + iteminfo.dropamount( options, page, itemPanel ) + else + p:GetParent().RemoveItem() + ---- DROP NET HERE ---- + + end + end + ypos = ypos + op.drop.h + yspacing + + end + + op.close = vgui.Create( "DButton", options ) + op.close:SetText( "Cancel" ) + op.close:SetFont( "q_item_option_button" ) + op.close:SizeToContents() + op.close.w, op.close.h = op.close:GetSize() + op.close:SetPos( xbasepos, ypos ) + op.close.x, op.close.y = op.close:GetPos() + op.close.Paint = function( self ) + theme.iteminfobutton( self ) + end + op.close.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + options.Close() + end + + -- center all of the option panels -- + options.w, options.h = resizePanel( options ) + for i, optionPanel in pairs( op ) do + print( optionPanel ) + optionPanel:SetPos( options.w/2 - optionPanel.w/2, optionPanel.y ) + end + options.w, options.h = resizePanel( options ) + return options + +end + function iteminfo.givetooltip( p, page ) local item = p:GetParent().item local parWidth, parHeight = p:GetParent():GetSize() @@ -24,7 +270,15 @@ function iteminfo.givetooltip( p, page ) tooltip.item = item tooltip:SetVisible( false ) tooltip.Paint = function( self ) - theme.itemtooltip( self, item ) + theme.iteminfopanel( self ) + end + + tooltip.Think = function( self ) -- prevents tooltip from showing when a item is showing its options + if( page.showtooltips != nil ) then + self:SetVisible( page.showtooltips ) + else + self:SetVisible( true ) + end end function tooltip:CreateInfo() @@ -70,10 +324,7 @@ function iteminfo.givetooltip( p, page ) end -- Correct the tooltips size so its content fits inside of it - self:SizeToChildren( true, true ) - self.w, self.h = self:GetSize() - self:SetSize( self.w + padding_s, self.h + padding_s ) - self.w, self.h = self:GetSize() + resizePanel( self ) end p.ItemTooltipPanel = tooltip -- set the tooltip diff --git a/gamemode/engine/derma/lib/cl_menu_theme.lua b/gamemode/engine/derma/lib/cl_menu_theme.lua index 041825c..f36fd7e 100644 --- a/gamemode/engine/derma/lib/cl_menu_theme.lua +++ b/gamemode/engine/derma/lib/cl_menu_theme.lua @@ -137,9 +137,14 @@ end function theme.itempanel( p, rarecolor ) local w, h = p:GetSize() - local icon = p.icon || p + local icon + if( p.icon == nil || !p.icon:IsValid() || !p.icon:IsVisible() ) then + icon = p + else + icon = p.icon + end - surface.SetDrawColor( rarecolor || Color( 0, 0, 0, 120 ) ) + surface.SetDrawColor( theme.color.setalpha( rarecolor || Color( 0, 0, 0, 120 ), 150 ) ) surface.DrawRect( 0, 0, w, h ) if( icon:IsHovered() ) then @@ -149,17 +154,28 @@ function theme.itempanel( p, rarecolor ) end end -function theme.itemtooltip( p, item ) +function theme.iteminfopanel( p ) local w, h = p:GetSize() theme.renderblur( p, 4, 5 ) - surface.SetDrawColor( Color( 20, 20, 20, 190 ) ) + surface.SetDrawColor( Color( 20, 20, 20, 220 ) ) surface.DrawRect( 0, 0, w, h ) theme.borderpanel( p, Color( 205, 205, 205, 200 ) ) end +function theme.iteminfobutton( b, txtClr ) + local w, h = b:GetSize() + txtClr = txtClr || Color( 255, 255, 255, 255 ) + + if( !b:IsHovered() ) then + b:SetTextColor( txtClr ) + else + b:SetTextColor( Color( 116, 185, 255, 255 ) ) + end +end + ---- Color Manipulation ---- theme.color = {} diff --git a/gamemode/engine/derma/menus/menu_charinfo.lua b/gamemode/engine/derma/menus/menu_charinfo.lua index c9e524a..11f926a 100644 --- a/gamemode/engine/derma/menus/menu_charinfo.lua +++ b/gamemode/engine/derma/menus/menu_charinfo.lua @@ -17,6 +17,17 @@ local padding = 10 * resScale local padding_s = 4 * resScale local errorMdl = "models/player.mdl" +local function createItemAmountLabel( icon, item ) + icon.amountpanel = vgui.Create( "DLabel", icon ) + icon.amountpanel:SetText( tostring( item.amount ) ) + icon.amountpanel:SetTextColor( Color( 205, 205, 205, 255 ) ) + icon.amountpanel:SetFont( "q_item_amount" ) + icon.amountpanel:SizeToContents() + icon.amountpanel.w, icon.amountpanel.h = icon.amountpanel:GetSize() + icon.amountpanel:SetPos( ( icon.w - icon.amountpanel.w ) - padding_s, icon.h - icon.amountpanel.h ) + return icon.amountpanel +end + function menu.open( dt ) local items = dt.cont.items @@ -152,6 +163,31 @@ function menu.open( dt ) theme.itempanel( self, self.itemcolor ) end + itempanels[ii].RemoveItem = function() + itempanels[ii].itemcolor = nil + if( itempanels[ii].icon:IsValid() ) then itempanels[ii].icon:SetVisible( false ) end + end + + itempanels[ii].SetItemAmount = function( amount ) + if( amount < 1 ) then itempanels[ii].RemoveItem() return end + itempanels[ii].item.amount = amount + + if( itempanels[ii].icon != nil ) then + if( IsValid( itempanels[ii].icon.amountpanel ) ) then + itempanels[ii].icon.amountpanel:Remove() + end + if( itempanels[ii].item.amount > 1 ) then + itempanels[ii].icon.amountpanel = createItemAmountLabel( itempanels[ii].icon, itempanels[ii].item ) + end + + ---- Create new options panel for it ---- + if( IsValid( itempanels[ii].icon.options ) ) then + itempanels[ii].icon.options:Remove() + itempanels[ii].icon.options = iteminfo.giveoptions( itempanels[ii].icon, f, itempanels[ii].item.amount ) + end + end + end + ---- Create the model icon for the item panel ---- if( itempanels[ii].item != nil && itempanels[ii].item.model != nil ) then itempanels[ii].icon = vgui.Create( "DModelPanel", itempanels[ii] ) @@ -176,13 +212,7 @@ function menu.open( dt ) ---- Amount Text ---- if( itempanels[ii].item.amount > 1 ) then - itempanels[ii].icon.amountpanel = vgui.Create( "DLabel", itempanels[ii].icon ) - itempanels[ii].icon.amountpanel:SetText( tostring( itempanels[ii].item.amount ) ) - itempanels[ii].icon.amountpanel:SetTextColor( Color( 205, 205, 205, 255 ) ) - itempanels[ii].icon.amountpanel:SetFont( "q_item_amount" ) - itempanels[ii].icon.amountpanel:SizeToContents() - itempanels[ii].icon.amountpanel.w, itempanels[ii].icon.amountpanel.h = itempanels[ii].icon.amountpanel:GetSize() - itempanels[ii].icon.amountpanel:SetPos( ( itempanels[ii].icon.w - itempanels[ii].icon.amountpanel.w ) - padding_s, itempanels[ii].icon.h - itempanels[ii].icon.amountpanel.h ) + itempanels[ii].icon.amountpanel = createItemAmountLabel( itempanels[ii].icon, itempanels[ii].item ) end ---- Tooltip ---- @@ -190,6 +220,14 @@ function menu.open( dt ) itempanels[ii].icon.tooltip:CreateInfo() -- create the labels for the tooltip & such ---- + ---- Click Options ---- + itempanels[ii].icon.options = iteminfo.giveoptions( itempanels[ii].icon, f, itempanels[ii].item.amount ) + + itempanels[ii].icon.DoClick = function( self ) + surface.PlaySound( "UI/buttonclick.wav" ) + self.options.Open() + end + end diff --git a/gamemode/engine/lib/server/sv_inventory.lua b/gamemode/engine/lib/server/sv_inventory.lua index 1f7f2ae..9fd540c 100644 --- a/gamemode/engine/lib/server/sv_inventory.lua +++ b/gamemode/engine/lib/server/sv_inventory.lua @@ -173,7 +173,7 @@ function Quantum.Server.Inventory.GiveItem( pl, itemid, amount ) -- Quantum.Serv if( #inv + 1 <= Quantum.Inventory.Width * Quantum.Inventory.Height || Quantum.Server.Inventory.FindStackable( char, item ) != nil ) then sortItem( char, itemid, amount ) - Quantum.Debug( "Gave " .. char.name .. " " .. amount .. "x [" .. item.name .. "]" ) + -- Quantum.Debug( "Gave " .. char.name .. " " .. amount .. "x [" .. item.name .. "]" ) -- Send net message to client about item update -- ############################################ -- ############################################ diff --git a/gamemode/settings/sh_items.lua b/gamemode/settings/sh_items.lua index bb1850f..d63e4d1 100644 --- a/gamemode/settings/sh_items.lua +++ b/gamemode/settings/sh_items.lua @@ -7,7 +7,7 @@ Quantum.Item.Create( "test", { name = "Test Item", - desc = "This is a test item!", + desc = "This is a test item!\nDoes not stack.", model = "models/props_phx/gears/bevel12.mdl", soulbound = true, equipable = false,