-- do return end -- -- --[[ -- Various functions to work with inventories -- player:GetCredits() -- player:SetCredits(number credits) -- -- concommands: -- artery_showinventory -- artery_setcredits [playername=admin] numcredits -- ]] -- --- Various functions to deal with inventories. -- -- @module Player -- local pmeta = FindMetaTable("Player") -- local emeta = FindMetaTable("Entity") -- local invfuncs = include("inventory_common.lua") -- -- --A 2d array of the inventory. -- pmeta.Inventory = pmeta.Inventory or {} -- -- --Money -- pmeta.Inventory.Credits = pmeta.Inventory.Credits or 0 -- --each backpack has 1:a tbl containing items or false, 2: a tbl {width,height} and 3:name -- pmeta.Inventory.Backpacks = pmeta.Inventory.Backpacks or {} -- -- --Eqiped stuff at base, player has 1=Head, 2=Body, 3=Legs, 4=Boots, 5=Gloves, 6=Left Hand, 7=Right Hand -- pmeta.Inventory.Equiped = pmeta.Inventory.Equiped or {} -- local equipedslots = { -- "Head","Body","Legs","Boots","Gloves","Left","Right" -- } -- for _,v in pairs(equipedslots) do -- pmeta.Inventory.Equiped[v] = pmeta.Inventory.Equiped[v] or false -- end -- -- if SERVER then -- --- Gets a player's credits. -- -- Gets the number of credits a player has -- -- @return The number of credits for this player -- function pmeta:GetCredits() -- return self.Inventory.Credits -- end -- -- util.AddNetworkString( "art_synch_credits" ) -- local function SynchCredits(ply) -- net.Start("art_synch_credits") -- net.WriteUInt(ply.Inventory.Credits,32) -- net.Send(ply) -- end -- -- --- Sets a player's credits. -- -- Sets the number of credits this player has. Credits are synchronized after every set -- -- @param num The number of credits to set on the player -- function pmeta:SetCredits(num) -- assert(type(num) == "number","Attempted to set credits to something other than a number:" .. type(num)) -- self.Inventory.Credits = num -- SynchCredits(self) -- end -- -- end -- -- if CLIENT then -- net.Receive("art_synch_credits",function() -- ART.Credits = net.ReadUInt(32) -- print("I updated my credits! now:", ART.Credits) -- end) -- end -- -- --- Puts an item in the inventory. -- -- Puts an item in an inventory, overwriteing all other items it might be overlapping, you should check to make sure you're not over writeing something first. -- -- @param backpack the backpack number this item should be placed in -- -- @param x the column in the backpack this item should be placed in -- -- @param y the row in the backpack this item should be placed in -- -- @param item the item to place in the backpack. -- -- @see Player.FindSpotForItem -- function pmeta:PutInvItem(backpack,x,y,item) -- invfuncs.PutItemInBackpack(self.Inventory.Backpacks[backpack],x,y,item) -- end -- -- --- Finds a spot for an item. -- -- Finds a backpack, row, and column for an item in a player's inventory. -- -- @param item The item to try and fit into the backpack. -- -- @return row The row where a spot was found -- -- @return col The column where a spot was found -- -- @return n The backpack number where a spot was found -- function pmeta:FindSpotForItem(item) -- for n,v in pairs(self.Inventory.Backpacks) do -- for row = 1,v[2][2] do -- for col = 1,v[2][1] do -- if self:CanFitInBackpack(v,row,col,item) then -- return row,col,n -- end -- end -- end -- end -- end -- -- local function DefaultCompare(item, itemname) -- return item.Name == itemname -- end -- -- --- Checks if the player has an item. -- -- Check to see if the player has an item. Supply the name of the item, or supply a function that takes 2 items, and returns true if they are equial. If any of the returns are nil, then all the the returns will be nil, and the item could not be found. -- -- @param nameorcomparitor The item name as a string, or a function that returns true when given an item that you want. -- -- @return row The row the items was found in -- -- @return col The column the item was found in -- -- @return n The backpack number the item was found in. -- function pmeta:HasItem(nameorcomparitor) -- local comparitor -- if type(nameorcomparitor) == "string" then -- comparitor = function(t) return t.Name == nameorcomparitor end -- else -- comparitor = nameorcomparitor -- end -- for n,v in pairs(self.Inventory.Backpacks) do -- for row = 1,v[2][2] do -- for col = 1,v[2][1] do -- local itemin = v[1][row][col] -- if (type(itemin) ~= "boolean") and comparitor(itemin) then -- return row,col,n -- end -- end -- end -- end -- end -- -- --- Removes an item. -- -- Remoes an item in the backpack of the player -- -- @param backpack The backpack to remove the item from -- -- @param row The row in the backpack the item is located at -- -- @param col The column in the backpack the item is located at -- function pmeta:RemoveItemAt(backpack,row,col) -- local item = self.Inventory.Backpacks[backpack][1][row][col] -- for k = 1,#item.Shape do -- for i = 1,#(item.Shape[k]) do -- self.Inventory.Backpacks[backpack][1][row + k - 1][col + i - 1] = false -- end -- end -- self:SynchronizeInventory() -- end -- -- --- Gives an item to a player. -- -- Gives an item to the player in the next avaliable slot the item can fit in -- -- @param item The item to give the player -- function pmeta:GiveItem(item) -- local x,y,b = self:FindSpotForItem(item) -- print("putting in ",x,y,b) -- if x and y and b then -- self:PutInvItem(b,x,y,item) -- self:SynchronizeInventory() -- return true -- else -- return false -- end -- end -- -- --- Check if an item can fit in a position in a backpack -- -- Check if an item can fit in a specific position in a specific backpack -- -- @param backpack The backpack to try to fit the item in -- -- @param x The row to try to fit the item in -- -- @param y The column to try to fit the item in -- -- @return bool If the item can fit in the backpack -- function pmeta:CanFitInBackpack(backpack,x,y,item) -- return invfuncs.CanFitInBackpack(backpack,x,y,item) -- end -- -- if SERVER then -- util.AddNetworkString("synchinventory") -- util.AddNetworkString("moveitem") -- util.AddNetworkString("equipitem") -- util.AddNetworkString("unequipitem") -- util.AddNetworkString("buyitem") -- end -- -- --- Unequips an item. -- -- Unequips an item, and puts it in the specified backpack (makes sure that it's possible first) -- -- @param equipslot The equipment slot the item is in right now -- -- @param backpack The destination backpack to put the item into -- -- @param row The row in the backpack to put the item -- -- @param col The column in the backpack to put the item -- function pmeta:UnEquip(equipslot, backpack, row, col) -- local item = self.Inventory.Equiped[equipslot] -- local tobackpack = self.Inventory.Backpacks[backpack] -- print("Unequiping into backpack", tobackpack) -- if self:CanFitInBackpack( -- tobackpack, -- row, -- col, -- item -- ) then -- self.Inventory.Equiped[equipslot] = false -- self:PutInvItem(backpack,row,col,item) -- if item.onUnEquip ~= nil then -- item:onUnEquip(self) -- end -- self:SynchronizeInventory() -- else -- error("Could not fit item in backpack, client might be de-synchronized") -- end -- end -- -- net.Receive("unequipitem",function(len,ply) -- local itemslot = net.ReadString() -- local tobackpack = net.ReadUInt(16) -- local row = net.ReadUInt(16) -- local col = net.ReadUInt(16) -- -- ply:UnEquip(itemslot,tobackpack,row,col) -- end) -- -- --- Equips an item -- -- Moves an item from a backpack to an equiped slot, makes sure the item can be equiped in that slot first -- -- @param frombackpack The backpack to take the item from -- -- @param fromrow The row to take the item from -- -- @param fromcol The column to take the item from -- -- @param toslo The equipment slot to put the item into -- function pmeta:EquipItem(frombackpack, fromrow, fromcol, toslot) -- local item = self.Inventory.Backpacks[frombackpack][1][fromrow][fromcol] -- if item.Equipable ~= nil and item.Equipable == toslot then -- --Remove from the backpack -- for k = 1,#item.Shape do -- for i = 1,#item.Shape[k] do -- if k == 1 and i == 1 then continue end -- self.Inventory.Backpacks[frombackpack][1][fromrow + k - 1][fromcol + i - 1] = false -- end -- end -- self.Inventory.Backpacks[frombackpack][1][fromrow][fromcol] = false -- self.Inventory.Equiped[toslot] = item -- if item.onEquip ~= nil then -- item:onEquip(self) -- end -- self:SynchronizeInventory() -- end -- end -- -- net.Receive("equipitem",function(len,ply) -- local backpacknum = net.ReadUInt(16) -- local fromrow = net.ReadUInt(16) -- local fromcol = net.ReadUInt(16) -- local equippos = net.ReadString() -- ply:EquipItem(backpacknum,fromrow,fromcol,equippos) -- end) -- -- net.Receive("buyitem",function(len,ply) -- local itemname = net.ReadString() -- local backpack = net.ReadUInt(8) -- local j = net.ReadUInt(8) -- local i = net.ReadUInt(8) -- local item = ART.GetItemByName(itemname) -- local nearshops = ents.FindInSphere( ply:GetPos(), 100 ) -- local cost -- for k,v in pairs(nearshops) do -- if v:GetClass() ~= "npc_shop" then goto nextent end -- print("Checking if ", v, " has a ", itemname) -- print("Shop items were") -- PrintTable(v.shopitems) -- for i,j in pairs(v.shopitems) do -- if j[1] == itemname then -- cost = j[2] -- goto itemfound -- end -- end -- ::nextent:: -- end -- ::itemfound:: -- if cost == nil then -- ply:ChatPrint("Could not find a shop selling that!") -- return false -- end -- print("Found item, cost was ", cost,"type",type(cost)) -- local playercreds = ply:GetCredits() -- print("player credits:",playercreds,"type:",type(playercreds)) -- local tbp = ply.Inventory.Backpacks[backpack] -- local canfit = invfuncs.CanFitInBackpack(tbp,j,i,item) -- print("Can fit?",canfit) -- if playercreds < cost then -- ply:ChatPrint("You don't have enough credits to buy that!") -- return false -- end -- if not canfit then -- ply:ChatPrint("You can't put that into your packpack there!") -- return false -- end -- ply:SetCredits(playercreds - cost) -- invfuncs.PutItemInBackpack(tbp,j,i,item) -- ply:SynchronizeInventory() -- return true -- end) -- -- net.Receive("moveitem",function(len,ply) -- local froment = net.ReadEntity() -- local toent = net.ReadEntity() -- -- local frombackpack = net.ReadUInt(16) -- local tobackpack = net.ReadUInt(16) -- -- local frompos = {net.ReadUInt(16),net.ReadUInt(16)} -- local topos = {net.ReadUInt(16),net.ReadUInt(16)} -- -- if froment:IsPlayer() and toent:IsPlayer() and (froment ~= toent) then--Just don't allow stealing between players, anything else is fine -- ply:PrintMessage( HUD_PRINTCENTER, "You can't steal from this person!" ) -- return -- end -- local item = froment.Inventory.Backpacks[frombackpack][1][frompos[1]][frompos[2]] -- -- --Set the shape it was at to false -- for k = 1,#item.Shape do -- for i = 1,#(item.Shape[k]) do -- if k == 1 and i == 1 then continue end -- froment.Inventory.Backpacks[frombackpack][1][frompos[1] + k - 1][frompos[2] + i - 1] = false -- end -- end -- froment.Inventory.Backpacks[frombackpack][1][frompos[1]][frompos[2]] = false -- --now check if it can fit in the backpack -- if invfuncs.CanFitInBackpack(toent.Inventory.Backpacks[tobackpack],topos[1],topos[2],item) then -- invfuncs.PutItemInBackpack(toent.Inventory.Backpacks[tobackpack],topos[1],topos[2],item) -- else -- invfuncs.PutItemInBackpack(froment.Inventory.Backpacks[frombackpack],frompos[1],frompos[2],item) -- end -- froment:SynchronizeInventory() -- toent:SynchronizeInventory() -- end) -- -- --- Networks a player's inventory -- -- Makes sure the client's version of the inventory matches up to the server's version, this should be called after manipulateing the client's inventory in any way. -- function pmeta:SynchronizeInventory() -- net.Start("synchinventory") -- net.WriteEntity(self) -- net.WriteFloat(#self.Inventory.Backpacks) -- for k,v in pairs(self.Inventory.Backpacks) do -- invfuncs.SerializeBackpack(v) -- end -- for k,v in pairs(equipedslots) do -- if self.Inventory.Equiped and self.Inventory.Equiped[v] ~= false then -- net.WriteString(v) -- local data = self.Inventory.Equiped[v]:Serialize() -- net.WriteString(self.Inventory.Equiped[v].Name) -- net.WriteUInt(#data,32) -- net.WriteData(data,#data) -- end -- end -- net.WriteString("END_EQUIPED") -- net.Send(self) -- end -- if CLIENT then -- net.Receive("synchinventory",function(len,ply) -- if LocalPlayer().invdisplays == nil then -- LocalPlayer().invdisplays = {} -- end -- local what = net.ReadEntity() -- what.Inventory.Backpacks = {} -- local numbackpacks = net.ReadFloat() -- for k = 1,numbackpacks do -- local tbackpack = invfuncs.DeSerializeBackpack() -- table.insert(what.Inventory.Backpacks,tbackpack) -- end -- local neq = net.ReadString() -- local updated_slots = {} -- while neq ~= "END_EQUIPED" do -- local itemslot = neq -- local itemname = net.ReadString() -- local itemdata = net.ReadData(net.ReadUInt(32)) -- local item = ART.GetItemByName(itemname):DeSerialize(itemdata) -- what.Inventory.Equiped[itemslot] = item -- updated_slots[itemslot] = true -- neq = net.ReadString() -- end -- if what.Inventory.Equiped ~= nil then -- for k,v in pairs(equipedslots) do -- if updated_slots[v] then continue end -- what.Inventory.Equiped[v] = false -- end -- end -- ART.RefreshDisplays() -- end) -- end -- -- concommand.Add("artery_showinventory",function(ply,cmd,args) -- PrintTable(ply.Inventory) -- PrintTable(ply.ClientInventory) -- end) -- -- concommand.Add("artery_setcredits",function(ply,cmd,args) -- if not (ply:IsValid() and ply:IsAdmin()) then return end -- local e -- local i = false -- for k,v in pairs(player.GetAll()) do -- if v:Nick() == args[1] then -- e = v -- i = true -- break -- end -- end -- e = e or ply -- e:SetCredits(tonumber(args[i and 2 or 1])) -- end) -- -- hook.Add( "PlayerSpawn", "artery_disable_sprint", function(ply) -- ply:SetRunSpeed(ply:GetWalkSpeed()) -- end )