Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*-------------------------------------------------
- Documentation (for other coders)
- Player:SetupDefaultInventory()
- Creates the player's inventory table if it doesn't exist already. You should have to touch this.
- Player:HasItem(<string>)
- Returns
- -------------------------------------------------*/
- if (SERVER) then
- AddCSLuaFile("rp_inventory.lua")
- AddCSLuaFile("rp_inventory_items.lua")
- hook.Add("ShowHelp", "OpenInventory", function(ply)
- ply:ConCommand("rp_inventory")
- end)
- end
- RPI = {}
- RPI.Items = {}
- RPI.Shipments = {}
- include("rp_inventory_items.lua")
- /*-------------------------------------------------*/
- MAX_ITEMS = 30 -- Maximum default number of items
- PICKUP_SOUND = Sound("weapons/zoom.wav")
- /*-------------------------------------------------*/
- // Thanks JetBoom!
- function Deserialize(sIn)
- SRL = nil
- RunString(sIn)
- return SRL
- end
- local allowedtypes = {}
- allowedtypes["string"] = true
- allowedtypes["number"] = true
- allowedtypes["table"] = true
- allowedtypes["Vector"] = true
- allowedtypes["Angle"] = true
- allowedtypes["boolean"] = true
- local function MakeTable(tab, done)
- local str = ""
- local done = done or {}
- local sequential = table.IsSequential(tab)
- for key, value in pairs(tab) do
- local keytype = type(key)
- local valuetype = type(value)
- if allowedtypes[keytype] and allowedtypes[valuetype] then
- if sequential then
- key = ""
- else
- if keytype == "number" or keytype == "boolean" then
- key ="["..tostring(key).."]="
- else
- key = "["..string.format("%q", tostring(key)).."]="
- end
- end
- if valuetype == "table" and not done[value] then
- done[value] = true
- if type(value._serialize) == "function" then
- str = str..key..value:_serialize()..","
- else
- str = str..key.."{"..MakeTable(value, done).."},"
- end
- else
- if valuetype == "string" then
- value = string.format("%q", value)
- elseif valuetype == "Vector" then
- value = "Vector("..value.x..","..value.y..","..value.z..")"
- elseif valuetype == "Angle" then
- value = "Angle("..value.pitch..","..value.yaw..","..value.roll..")"
- else
- value = tostring(value)
- end
- str = str .. key .. value .. ","
- end
- end
- end
- if string.sub(str, -1) == "," then
- return string.sub(str, 1, #str - 1)
- else
- return str
- end
- end
- function Serialize(tIn, bRaw)
- if bRaw then
- return "{"..MakeTable(tIn).."}"
- end
- return "SRL={"..MakeTable(tIn).."}"
- end
- local meta = FindMetaTable("Player")
- function meta:SetupDefaultInventory()
- self.Inventory = self.Inventory or {}
- self.Inventory.Items = self.Inventory.Items or {}
- self.Inventory.SlotSpace = self.Inventory.SlotSpace or MAX_ITEMS
- end
- function meta:HasItem(itm)
- return table.HasValue(self.Inventory.Items, itm)
- end
- function meta:GetItems()
- return self.Inventory.Items
- end
- function meta:GetItemCount(itm)
- if (itm) then
- local count = 0
- for _, v in pairs (self.Inventory.Items) do
- if (v == itm) then
- count = count + 1
- end
- end
- return count
- else
- return #self.Inventory.Items
- end
- end
- function meta:AddItem(itm)
- table.insert(self.Inventory.Items, itm)
- end
- function meta:RemoveItem(itm, all)
- for _, v in pairs (self.Inventory.Items) do
- if (v == itm) then
- table.remove(self.Inventory.Items, _)
- if (!all) then
- break
- end
- end
- end
- end
- function meta:GetMaxItems()
- return self.Inventory.SlotSpace
- end
- if (SERVER) then
- util.AddNetworkString("RPI_OpenInventory")
- util.AddNetworkString("RPI_DropSpecial")
- function meta:SavePlayerInventory()
- if (!self.Inventory) then return end
- local steamid = string.gsub(string.sub(self:SteamID(), 7), ":", "_")
- local result = Serialize(self.Inventory)
- file.Write("rp_inventory/" .. steamid .. ".txt", result)
- end
- function meta:OpenInventory()
- net.Start("RPI_OpenInventory")
- net.WriteTable(self.Inventory.Items)
- net.WriteInt(self.Inventory.SlotSpace, 32)
- net.Send(self)
- end
- hook.Add("InitPostEntity", "InitRPInventory", function()
- if (!file.IsDir("rp_inventory", "DATA")) then
- file.CreateDir("rp_inventory")
- end
- end)
- hook.Add("PlayerInitialSpawn", "InitPlayerInventory", function(ply)
- local steamid = string.gsub(string.sub(ply:SteamID(), 7), ":", "_")
- if (file.Exists("rp_inventory/" .. steamid .. ".txt", "DATA")) then
- local inventory = Deserialize(file.Read("rp_inventory/" .. steamid .. ".txt", "DATA"))
- ply.Inventory = table.Copy(inventory)
- else
- ply:SetupDefaultInventory()
- end
- end)
- hook.Add("PlayerUse", "HandleItemPickup", function(ply, ent)
- if (!ply:KeyDown(IN_WALK)) then return end
- if (!RPI.Items[ent:GetClass()]) then return false end
- if (ply.NextPickup and ply.NextPickup > CurTime()) then return end
- ply.NextPickup = CurTime() + 0.2
- if (ply:GetItemCount() >= ply:GetMaxItems()) then
- ply:ChatPrint("Your inventory is full.")
- return
- end
- if (ent:GetClass() == "spawned_shipment") then
- local id = ent:Getcontents()
- local shipment = CustomShipments[id]
- ply:AddItem({
- class = "spawned_shipment",
- name = shipment.name,
- count = ent:Getcount(),
- id = ent:Getcontents()
- })
- elseif (ent:GetClass() == "spawned_weapon") then
- local class = ent.weaponclass
- local weapon = {}
- for _, v in pairs (CustomShipments) do
- if (v.entity == class) then
- weapon = v
- break
- end
- end
- ply:AddItem({
- class = "spawned_weapon",
- name = weapon.name,
- model = weapon.model,
- weaponclass = class
- })
- elseif (ent:GetClass() == "spawned_food") then
- ply:AddItem({
- class = "spawned_food",
- name = "Food",
- model = ent:GetModel(),
- foodenergy = ent.FoodEnergy
- })
- elseif (ent:GetClass() == "armor") then
- ply:AddItem({
- class = "armor",
- name = "Armor",
- model = ent:GetModel(),
- armorcharge = ent.ArmorCharge
- })
- else
- ply:AddItem(ent:GetClass())
- end
- ply:SavePlayerInventory()
- ply:EmitSound(PICKUP_SOUND)
- ent:Remove()
- return false
- end)
- hook.Add("PlayerDisconnected", "SavePlayerInventory", function(ply)
- ply:SavePlayerInventory()
- end)
- concommand.Add("rp_inventory", function(ply)
- if (!ply.Inventory) then
- ply:ChatPrint("There was en error while loading your inventory. If after rejoining this doesn't fix, contact the server administrator.")
- return
- end
- ply:OpenInventory()
- end)
- concommand.Add("rp_dropitem", function(ply, cmd, args)
- if (!ply.Inventory) then
- ply:ChatPrint("There was en error while loading your inventory. If after rejoining this doesn't fix, contact the server administrator.")
- return
- end
- local itm = tostring(args[1] or "")
- if (!RPI.Items[itm]) then return end
- if (ply:GetItemCount(itm) <= 0) then return end
- local pos = ply:GetShootPos()
- local ang = ply:GetAimVector()
- local tracedata = {}
- tracedata.start = pos
- tracedata.endpos = pos + (ang * 100)
- tracedata.filter = ply
- local trace = util.TraceLine(tracedata)
- local ent = ents.Create(itm)
- if (!ent or !ent:IsValid()) then GAMEMODE:Notify(ply, 1,4, "Invalid!") return end
- if (ply.SID) then ent.SID = ply.SID end
- if (ent.Setowning_ent) then ent:Setowning_ent(ply) end
- ent.nodupe = true
- ent:SetPos(trace.HitPos)
- ent:Spawn()
- ply:RemoveItem(itm)
- ply:SavePlayerInventory()
- ply:OpenInventory()
- end)
- net.Receive("RPI_DropSpecial", function(length, client)
- local special = net.ReadTable()
- local drop = false
- for _, item in pairs (client:GetItems()) do
- if (type(item) ~= "table") then continue end
- if (special.count and item.count and special.count == item.count) then
- table.remove(client:GetItems(), _)
- drop = true
- break
- elseif (special.weaponclass and item.weaponclass and special.weaponclass == item.weaponclass) then
- table.remove(client:GetItems(), _)
- drop = true
- break
- elseif (special.foodenergy and item.foodenergy and special.foodenergy == item.foodenergy) and (special.model and item.model and special.model == item.model) then
- table.remove(client:GetItems(), _)
- drop = true
- break
- elseif (special.armorcharge and item.armorcharge and special.armorcharge == item.armorcharge) and (special.model and item.model and special.model == item.model) then
- table.remove(client:GetItems(), _)
- drop = true
- break
- end
- end
- if (drop) then
- local pos = client:GetShootPos()
- local ang = client:GetAimVector()
- local tracedata = {}
- tracedata.start = pos
- tracedata.endpos = pos + (ang * 100)
- tracedata.filter = client
- local trace = util.TraceLine(tracedata)
- local ent = ents.Create(special.class)
- if (!ent or !ent:IsValid()) then GAMEMODE:Notify(ply, 1,4, "Invalid!") return end
- if (special.model) then ent:SetModel(Model(special.model)) end
- if (client.SID) then ent.SID = client.SID end
- if (ent.Setowning_ent) then ent:Setowning_ent(client) end
- if (ent.Setcontents and special.id) then ent:Setcontents(special.id) end
- if (ent.Setcount and special.count) then ent:Setcount(special.count) end
- if (special.weaponclass) then ent.weaponclass = special.weaponclass end
- if (special.foodenergy) then ent.FoodEnergy = special.foodenergy end
- if (special.armorcharge) then ent.ArmorCharge = special.armorcharge end
- ent:SetPos(trace.HitPos)
- ent:Spawn()
- client:SavePlayerInventory()
- client:OpenInventory()
- end
- end)
- hook.Add("PlayerSay", "InvCommand", function(ply, say, team)
- if (say:lower() == "!inv" or say:lower() == "/inv") then
- ply:OpenInventory()
- return ""
- end
- end)
- else
- pInventory = pInventory or NULL
- net.Receive("RPI_OpenInventory", function()
- local inventory = net.ReadTable()
- local maxspace = net.ReadInt(32)
- local items = {}
- local count = 0
- for _, v in pairs (inventory) do
- if (type(v) == "table") then
- if (v.weaponclass) then
- if (items[v.weaponclass]) then
- items[v.weaponclass].count = items[v.weaponclass].count + 1
- else
- items[v.weaponclass] = {name = v.name, model = v.model, count = 1, weaponclass = v.weaponclass, class = v.weaponclass}
- end
- elseif (v.foodenergy) then
- if (items[v.model]) then
- items[v.model].count = items[v.model].count + 1
- else
- items[v.model] = {name = "Food", model = v.model, count = 1, class = "spawned_food", foodenergy = v.foodenergy}
- end
- elseif (v.armorcharge) then
- if (items[v.model]) then
- items[v.model].count = items[v.model].count + 1
- else
- items[v.model] = {name = "Armor", model = v.model, count = 1, class = "armor", armorcharge = v.armorcharge}
- end
- else
- table.insert(items, v)
- end
- else
- items[v] = (items[v] or 0) + 1
- end
- count = count + 1
- end
- local x, y
- if (pInventory and pInventory:IsValid()) then
- x, y = pInventory:GetPos()
- pInventory:Remove()
- pInventory = nil
- end
- local frame = vgui.Create("DFrame")
- frame:SetTitle("Inventory")
- frame:SetSize(500, 500)
- if (x and y) then
- frame:SetPos(x, y)
- else
- frame:Center()
- end
- frame:MakePopup()
- pInventory = frame
- local ilist = vgui.Create("DPanelList", frame)
- ilist:EnableHorizontal(true)
- ilist:EnableVerticalScrollbar(true)
- ilist:StretchToParent(5, 27, 5, 5)
- ilist.Paint = function(me)
- local w, h = me:GetSize()
- draw.RoundedBox(4, 0, 0, w, h, Color(75, 75, 75, 255))
- draw.WordBox(4, 5, h - 26, "Space left: " .. maxspace - count, "DermaDefault", Color(0, 0, 0, 160), color_white)
- end
- for k, v in pairs (items) do
- if (type(v) == "table") then
- local item = v
- local icon = vgui.Create("SpawnIcon")
- icon:SetSize(64, 64)
- if (v.model) then
- icon:SetModel(Model(v.model))
- else
- icon:SetModel(Model("models/items/item_item_crate.mdl"))
- end
- icon:SetToolTip(item.name)
- icon.PaintOver = function(me)
- local w, h = me:GetSize()
- draw.SimpleTextOutlined(item.name or "", "DermaDefault", w * 0.5, 5, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_LEFT, 1, color_black)
- if (item.class and item.class == "spawned_shipment") then
- draw.SimpleTextOutlined("x" .. item.count, "DermaDefault", w - 5, h - 5, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, color_black)
- draw.SimpleTextOutlined("Shipment", "DermaDefault", w * 0.5, 18, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_LEFT, 1, color_black)
- elseif (item.count) then
- draw.SimpleTextOutlined("x" .. item.count, "DermaDefault", w - 5, h - 5, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, color_black)
- end
- end
- icon.DoClick = function()
- local menu = DermaMenu()
- menu:AddOption("Drop", function()
- net.Start("RPI_DropSpecial")
- net.WriteTable(item)
- net.SendToServer()
- surface.PlaySound(Sound("buttons/button5.wav"))
- end)
- menu:Open()
- end
- ilist:AddItem(icon)
- else
- local itm = k
- local count = v
- local item = RPI.Items[itm]
- local icon = vgui.Create("SpawnIcon")
- icon:SetSize(64, 64)
- icon:SetModel(item.model)
- icon:SetToolTip(item.name .. [[
- ]] .. (item.description or "") .. [[
- Category: ]] .. item.category)
- icon.PaintOver = function(me)
- local w, h = me:GetSize()
- draw.SimpleTextOutlined(item.name, "DermaDefault", w * 0.5, 5, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_LEFT, 1, color_black)
- draw.SimpleTextOutlined("x" .. count, "DermaDefault", w - 5, h - 5, color_white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, color_black)
- end
- icon.DoClick = function()
- local menu = DermaMenu()
- menu:AddOption("Drop", function()
- RunConsoleCommand("rp_dropitem", itm)
- surface.PlaySound(Sound("buttons/button5.wav"))
- end)
- menu:Open()
- end
- ilist:AddItem(icon)
- end
- end
- end)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement