Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local PANEL = vgui.Register("items.Trading", {}, "DFrame")
- function PANEL:Init()
- self.sheet = vgui.Create("DPropertySheet", self)
- self.trading = vgui.Create("DPanel", self)
- local trading = self.trading
- trading.divider = vgui.Create("DHorizontalDivider", trading)
- trading.left = {}
- trading.left.items = {}
- trading.right = {}
- trading.right.items = {}
- trading:SetPaintBackground(false)
- -- RunConsoleCommand("gm_clearfonts")
- surface.CreateFont("Arial Black", 25, 300, true, false, "ItemsNameLabel", true, true)
- for key, side in pairs({trading.left, trading.right}) do
- side.list = vgui.Create("DPanelList")
- side.list:EnableHorizontal(false)
- side.list:EnableVerticalScrollbar(true)
- side.list:SetSpacing(0)
- side.name = vgui.Create("DLabel", side.list)
- side.name:SetFont("ItemsNameLabel")
- side.name:SetText(key)
- side.name:NoClipping(true)
- side.name:SetTextColor(Color(255,255,255))
- side.name:SizeToContents()
- side.name:SetZPos(1)
- side.coins = vgui.Create("DNumberWang", trading)
- side.coins:SetDecimals(0)
- side.coins:NoClipping(true)
- side.coins:SetZPos(2)
- side.coins:SetWide(100)
- side.coins:SetMax(LocalPlayer():GetCoins())
- side.coinslabel = vgui.Create("DLabel", trading)
- side.coinslabel:SetText("Coins")
- side.coinslabel:SetFont("ChatFont")
- side.coinslabel:SetTextColor(Color(255,255,255))
- side.coinslabel:SizeToContents()
- side.coins.TextEntry.OnCursorEntered = function()
- self:SetKeyboardInputEnabled(true)
- self:MakePopup()
- end
- side.coins.TextEntry.OnCursorExited = function()
- self:SetKeyboardInputEnabled(false)
- self:KillFocus()
- end
- function side.list:Paint()
- DPanelList.Paint(self)
- surface.SetDrawColor( 150, 150, 150, 255 )
- surface.DrawOutlinedRect( 0, 0, self:GetWide(), self:GetTall() )
- end
- end
- trading.left.coins.OnNewChange = function(_ ,value) -- Does this have an argument?
- timer.Create("SendCoinsUpdate", 0.25, 1, function()
- RunConsoleCommand("items_trade", LocalPlayer():EntIndex(), "coins", value)
- end)
- end
- --[[trading.left.coins.TextEntry.OnEnter = function() -- This one :C
- timer.Create("SendCoinsUpdate", 0.5, 1, function()
- RunConsoleCommand("items_trade", LocalPlayer():EntIndex(), "coins", trading.left.coins.TextEntry:GetValue())
- end)
- end]]
- local oldValue = tonumber(trading.left.coins:GetValue()) or 0
- hook.Add("Think", "items.Trading.Think", function()
- if not ValidPanel(self) then
- hook.Remove("Think", "items.Trading.Think")
- return
- end
- local n = tonumber(trading.left.coins:GetValue()) or 0
- if n ~= oldValue then
- local c = math.Clamp(n, 0, LocalPlayer():GetCoins())
- if c ~= n then
- trading.left.coins:SetValue(c)
- n = c
- end
- trading.left.coins:OnNewChange(n)
- oldValue = n
- end
- end)
- trading.right.coins.Wanger.OnMousePressed = function() end
- trading.right.coins.TextEntry:SetEditable(false)
- trading.divider:SetLeft(trading.left.list)
- trading.divider:SetRight(trading.right.list)
- trading.divider.StartGrab = function() end
- trading.trade = vgui.Create("DButton", trading)
- trading.trade:SetText("Trade")
- trading.trade:SetSize(130, 30)
- trading.trade.DoClick = function()
- RunConsoleCommand("items_trade", LocalPlayer():EntIndex(), "finished")
- --self:Close()
- end
- trading.decline = vgui.Create("DButton", trading)
- trading.decline:SetText("Cancel")
- trading.decline:SetSize(130, 30)
- trading.decline.DoClick = function()
- RunConsoleCommand("items_trade", LocalPlayer():EntIndex(), "cancel")
- self:Close()
- end
- self.sheet:AddSheet("Trading", trading, "gui/silkicons/arrow_refresh", false, false, "Trading")
- self.inventory = vgui.Create("DPanelList", self)
- local inventory = self.inventory
- inventory:EnableHorizontal(false)
- inventory:EnableVerticalScrollbar(true)
- inventory:SetSpacing(5)
- inventory.items = {}
- self.sheet:AddSheet("Inventory", inventory, "gui/silkicons/folder_go", false, false, "Inventory")
- self:SetTitle("Trade")
- self:SetSize(ScrW()/1.5,500)
- self:Center()
- self:AlignTop(50)
- self:ShowCloseButton(false)
- self:SetSizable(true)
- self:UpdateInventory()
- self:SetLeftName(LocalPlayer():Nick())
- end
- function PANEL:Think()
- gui.EnableScreenClicker(true)
- end
- AccessorFunc(PANEL, "trader", "Trader")
- function PANEL:UpdateInventory()
- self.inventory:Clear()
- local inventory = LocalPlayer():GetInventory()
- for class, table in pairs(inventory) do
- if class ~= "" then
- if not table.data then table.data = items.GetItemDataFromClass(class) end
- if table.data then
- local item = vgui.Create("items.ItemPanel", self)
- local text = items.GetInventoryInfo(class)
- item:SetCount(table.count)
- item:SetItemInfo(items.Get(class).WorldModel or blank, text.name, text.info)
- item:SetMenu(function()
- local menu = DermaMenu()
- menu:MakePopup()
- menu:SetPos(gui.MousePos())
- menu:AddOption("Add", function()
- self:AddLeftItem(item, class)
- RunConsoleCommand("items_trade", LocalPlayer():EntIndex(), "addition", class, 1)
- end)
- end)
- self.inventory:AddItem(item)
- self.inventory.items[class] = table.count
- end
- end
- end
- end
- function PANEL:SetLeftName(name)
- local panel = self.trading.left.name
- panel:SetText(name)
- panel:SizeToContents()
- end
- function PANEL:SetRightName(name)
- local panel = self.trading.right.name
- panel:SetText(name)
- panel:SizeToContents()
- end
- function PANEL:AddLeftItem(item, class)
- local left = self.trading.left
- local oldpanel = IsValid(left.items[class]) and left.items[class]
- local panel = oldpanel or vgui.Create("items.ItemPanel")
- panel:SetCount(panel:GetCount()+1)
- left.items[class] = panel
- local model = items.Get(class).WorldModel
- local info = items.GetInventoryInfo(class)
- panel:SetItemInfo(model, info.name, info.info)
- self.inventory.items[class] = self.inventory.items[class] - 1
- item:SetCount(self.inventory.items[class])
- if self.inventory.items[class] < 1 then
- self.inventory:RemoveItem(item)
- end
- panel:SetMenu(function()
- local menu = DermaMenu()
- menu:MakePopup()
- menu:SetPos(gui.MousePos())
- menu:AddOption("Remove", function()
- RunConsoleCommand("items_trade", self:GetTrader():EntIndex(), "addition", class, -1)
- left.items[class]:SetCount(left.items[class]:GetCount() - 1)
- if left.items[class] and left.items[class]:GetCount() < 1 then
- panel:Remove()
- self:UpdateInventory()
- local width = left.list:GetWide()
- left.list:SetWide(width+1)
- left.list:SetWide(width) -- dammit
- end
- end)
- end)
- if not oldpanel then left.list:AddItem(panel) end
- end
- function PANEL:SetRightItem(class, count)
- local right = self.trading.right
- local oldpanel = IsValid(right.items[class]) and right.items[class]
- if oldpanel and count < 1 then oldpanel:Remove() return end
- if count < 1 then return end
- local panel = oldpanel or vgui.Create("items.ItemPanel")
- panel:SetCount(count)
- local item = items.Get(class)
- panel:SetItemInfo(item.WorldModel or blank, item.Inventory.name, item.Inventory.info)
- right.items[class] = panel
- if not oldpanel then right.list:AddItem(panel) end
- end
- function PANEL:Close()
- gui.EnableScreenClicker(false)
- self:Remove()
- end
- function PANEL:PerformLayout()
- derma.SkinHook( "Layout", "Frame", self )
- local trading = self.trading
- self.sheet:StretchToParent(5,25,5,5)
- trading:StretchToParent(5,5,5,5)
- trading.divider:StretchToParent(5,35,5,100)
- local center = trading.divider:GetWide()/2-4
- trading.divider:SetLeftWidth(center)
- trading.trade:AlignLeft(8)
- trading.trade:AlignBottom(25)
- trading.decline:MoveRightOf(trading.trade, 5)
- trading.decline:AlignBottom(25)
- local left = trading.left
- left.coins:AlignLeft(8)
- left.coins:AlignBottom(70)
- left.coinslabel:CopyPos(left.coins)
- left.coinslabel:MoveRightOf(left.coins, 5)
- local right = trading.right
- right.coins:AlignRight(center - trading.right.coins:GetWide() + 2)
- right.coins:AlignBottom(70)
- right.coinslabel:CopyPos(right.coins)
- right.coinslabel:MoveRightOf(right.coins, 5)
- for key, side in pairs({trading.left, trading.right}) do
- side.name:AlignTop(-13)
- end
- end
- function items.ShowNotify(player)
- local frame = vgui.Create( "DFrame" )
- frame:Center()
- frame:AlignTop()
- frame:ShowCloseButton(true)
- frame:SetTitle("Trading invitation")
- local starttime = RealTime()
- local text = vgui.Create("DLabel", frame)
- local c = math.ceil(30-(RealTime()-starttime))
- local t = player:Nick() .. " wants to trade with you!\nDo you want to accept?\nIgnoring in "..c.." second"..(c != 1 and "s" or "").."\n(hold c to get to this window)"
- text:SetText(t)
- function text:Think()
- c = math.ceil(30-(RealTime()-starttime))
- if c <= 0 then
- frame:Remove()
- return
- end
- local nt = player:Nick() .. " wants to trade with you!\nDo you want to accept?\nIgnoring in "..c.." second"..(c != 1 and "s" or "").."\n(hold c to get to this window)"
- if nt ~= t then
- text:SetText(nt)
- text:SizeToContents()
- t = nt
- end
- end
- text:SizeToContents()
- frame:SetSize(30 + text:GetWide(), 60 + text:GetTall())
- text:Center()
- text:AlignTop(25)
- local accept = vgui.Create("DButton", frame)
- accept:SetText("Accept")
- accept:AlignLeft(5)
- accept:AlignBottom(5)
- accept.DoClick = function()
- RunConsoleCommand("items_trade", player:EntIndex(), "accepted")
- frame:Remove()
- g_ItemsTradingMenu = vgui.Create("items.Trading")
- g_ItemsTradingMenu:SetRightName(player:Nick())
- end
- local decline = vgui.Create("DButton", frame)
- decline:SetText("Decline")
- decline:CopyPos(accept)
- decline:MoveRightOf(accept, 5)
- decline.DoClick = function()
- RunConsoleCommand("items_trade", LocalPlayer():EntIndex(), "decline")
- frame:Remove()
- timer.Destroy("RemoveTradeRequest")
- end
- end
- usermessage.Hook("items.Trading", function(umsg)
- local type = umsg:ReadString()
- if type == "notify" then
- items.ShowNotify(umsg:ReadEntity())
- elseif type == "accepted" then
- local trader = umsg:ReadEntity()
- items.CurrentTrader = trader
- g_ItemsTradingMenu = vgui.Create("items.Trading")
- g_ItemsTradingMenu:SetRightName(trader:Nick())
- g_ItemsTradingMenu:SetTrader(trader)
- elseif type == "declined" then
- elseif type == "cancel" then
- if ValidPanel(g_ItemsTradingMenu) then
- g_ItemsTradingMenu:Close() -- disables screen clicker too, which reminds me: why does it not enable it in the first place?
- end
- elseif type == "addition" then
- local menu = g_ItemsTradingMenu
- if IsValid(menu) then
- local class = umsg:ReadString()
- local amount = umsg:ReadLong()
- menu:SetRightItem(class, amount)
- end
- elseif type == "coins" then
- g_ItemsTradingMenu.trading.right.coins:SetValue(tonumber(umsg:ReadString()) or 0)
- elseif type == "finished" then
- g_ItemsTradingMenu:Close()
- elseif type == "message" then
- chat.AddText(umsg:ReadBool() and Color(0,255,0) or Color(255,0,0), umsg:ReadString())
- end
- end)
- local function CheckDistance(a, b)
- return a and a:GetShootPos():Distance(b:GetShootPos()) < 80
- end
- local function Notify(ply, positive, message)
- umsg.Start("items.Trading", ply)
- umsg.String("message")
- umsg.Bool(positive)
- umsg.String(message)
- umsg.End()
- end
- concommand.Add("items_trade", function(player, _, arguments)
- local target = Entity(tonumber(arguments[1]))
- target = IsValid(target) and target
- if not target then return end
- local ttype = arguments[2]
- if ttype == "request" and CheckDistance(target, player) then
- if player.Trading then
- Notify(player, false, "You are already trading!")
- return
- end
- player.TradeRequests = player.TradeRequests or {}
- for k,v in pairs(player.TradeRequests) do
- if IsValid(Entity(k)) then
- if CurTime()-v <= 0 then
- player.TradeRequests[k] = nil
- return
- elseif CurTime()-v <= 30 then
- Notify(player, false, "You already have an open trade request!")
- return
- else
- Notify(player, false, "Cancelled your trade request with " .. target:Nick() .."!")
- end
- end
- player.TradeRequests[k] = nil
- end
- target.TradeRequests = target.TradeRequests or {}
- for k,v in pairs(target.TradeRequests) do
- if CurTime()-v <= 30 and IsValid(Entity(k)) then
- Notify(player, false, target:Nick().." is busy!")
- return
- else
- player.TradeRequests[k] = nil
- end
- end
- umsg.Start("items.Trading", target)
- umsg.String("notify")
- umsg.Entity(player)
- umsg.End()
- player.TradeRequests[target:EntIndex()] = CurTime()
- print(player:Nick() .. " requested a trade with " .. target:Nick())
- Notify(player, true, "You have invitied " .. target:Nick() .. " to trade")
- elseif ttype == "accepted" then
- if type(target.TradeRequests) ~= "table" or
- type(target.TradeRequests[player:EntIndex()]) ~= "number"
- then
- player:ChatPrint(target:Nick() .. " is busy!")
- return
- elseif CurTime()-target.TradeRequests[player:EntIndex()] > 30 then
- Notify(player, false, "Your trade request with " .. target:Nick() .. " expired!")
- return end
- umsg.Start("items.Trading", target)
- umsg.String("accepted")
- umsg.Entity(player)
- umsg.End()
- player.TradeRequests = player.TradeRequests or {}
- for k,v in pairs(player.TradeRequests) do
- player.TradeRequests[k] = nil
- end
- target.TradeRequests = target.TradeRequests or {}
- for k,v in pairs(target.TradeRequests) do
- target.TradeRequests[k] = nil
- end
- target.Trading = true
- player.Trading = true
- player.TradeItems = nil
- target.TradeItems = nil
- target.TradingWith = player
- player.TradingWith = target
- print(player:Nick() .. " and " .. target:Nick() .. " are now trading")
- elseif ttype == "declined" then
- player:ChatPrint(target:Nick().." declined your request!")
- elseif ttype == "cancel" then
- if not player.Trading then
- Notify(player, false, "You are not trading!")
- return
- end
- local target = player.TradingWith
- umsg.Start("items.Trading", target)
- umsg.String("cancel")
- umsg.End()
- target.Trading = false
- player.Trading = false
- target.Finished = nil
- player.Finished = nil
- Notify(target, false, player:Nick().." cancelled the trade!")
- Notify(player, false, "Trade cancelled!")
- print(player:Nick() .. " cancelled trade with " .. target:Nick())
- elseif ttype == "coins" then
- if not player.Trading or not IsValid(player.TradingWith) then return end
- local target = player.TradingWith
- local amount = tonumber(arguments[3])
- if not amount or amount < 0 then return end
- player.TradeCoins = amount
- umsg.Start("items.Trading", target)
- umsg.String("coins")
- umsg.String(amount)
- umsg.End()
- elseif ttype == "addition" then
- if not player.Trading or not IsValid(player.TradingWith) then return end
- player.TradeItems = player.TradeItems or {}
- local target = player.TradingWith
- local class = arguments[3]
- if not class then return end
- if not items.Classes[class] then
- Notify(player, false, class .. " is not a valid item!")
- return
- end
- local amount = tonumber(arguments[4])
- if not amount or amount == 0 then return end
- if amount < 0 then
- player.TradeItems[class] = player.TradeItems[class] or 0
- if player.TradeItems[class]-amount < 0 then
- Notify(player, false, "You do not have that many items to remove!")
- return
- end
- elseif amount > 0 then
- player.TradeItems[class] = player.TradeItems[class] or 0
- local pamount = player:GetInventory()[class] or 0
- if pamount < player.TradeItems[class]+amount then
- Notify(player, false, "You do not have that many items to add!")
- return
- end
- end
- player.TradeItems[class] = player.TradeItems[class]+amount
- umsg.Start("items.Trading", player.TradingWith)
- umsg.String("addition")
- umsg.String(class)
- umsg.Long(player.TradeItems[class] or 0)
- umsg.End()
- player.Finished = nil
- target.Finished = nil
- elseif ttype == "finished" then
- if not player.Trading or not IsValid(player.TradingWith) then return end
- local target = player.TradingWith
- if player.Finished then
- Notify(player, false, "You are already finished. Please wait on the other player.")
- return
- end
- if not target.Finished then
- Notify(player, true, "Waiting on other player...")
- Notify(target, true, "Other player is done.")
- player.Finished = true
- return
- end
- print("Finishing trade:")
- for k,v in pairs(player.TradeItems or {}) do
- target:AddToInventory(k, v)
- print("\tAdded "..tostring(v).." "..tostring(k).." to "..target:Nick().."'s inventory")
- player:RemoveFromInventory(k, v)
- print("\tRemoved "..tostring(v).." "..tostring(k).." from "..target:Nick().."'s inventory")
- end
- for k,v in pairs(target.TradeItems or {}) do
- player:AddToInventory(k, v)
- print("\tAdded "..tostring(v).." "..tostring(k).." to "..player:Nick().."'s inventory")
- target:RemoveFromInventory(k, v)
- print("\tRemoved "..tostring(v).." "..tostring(k).." from "..target:Nick().."'s inventory")
- end
- local c, c2 = player.TradeCoins or 0, target.TradeCoins or 0
- target:SetCoins(target:GetCoins()+(c-c2))
- print("\tGave "..target:Nick().." "..(c-c2).." coins")
- player:SetCoins(player:GetCoins()+(c2-c))
- print("\tGave "..player:Nick().." "..(c2-c).." coins")
- local RF = RecipientFilter()
- RF:AddPlayer(target)
- RF:AddPlayer(player)
- umsg.Start("items.Trading", RF)
- umsg.String("finished")
- umsg.End()
- target.Finished = nil
- player.Finished = nil
- target.TradeItems = nil
- player.TradeItems = nil
- target.Trading = nil
- player.Trading = nil
- target.TradingWith = nil
- player.TradingWith = nil
- target.TradeCoins = nil
- player.TradeCoins = nil
- print(player:Nick() .. " and " .. target:Nick() .. " finished trading")
- elseif not CheckDistance(target, player) then
- player:ChatPrint("You are too far away to start trading")
- end
- end)
Advertisement
Add Comment
Please, Sign In to add comment