aboutsummaryrefslogtreecommitdiff
path: root/gamemode/shared
diff options
context:
space:
mode:
Diffstat (limited to 'gamemode/shared')
-rw-r--r--gamemode/shared/accounts.lua153
-rw-r--r--gamemode/shared/entity_ext.lua19
-rw-r--r--gamemode/shared/game_rounds.lua105
-rw-r--r--gamemode/shared/player_accountinventory.lua98
-rw-r--r--gamemode/shared/player_dropitem.lua26
-rw-r--r--gamemode/shared/player_ghost.lua97
-rw-r--r--gamemode/shared/player_human.lua66
-rw-r--r--gamemode/shared/player_inventory.lua99
-rw-r--r--gamemode/shared/player_lootventory.lua53
-rw-r--r--gamemode/shared/player_pigeon.lua44
-rw-r--r--gamemode/shared/player_recipes.lua102
-rw-r--r--gamemode/shared/player_transferitem.lua44
-rw-r--r--gamemode/shared/player_useitem.lua40
-rw-r--r--gamemode/shared/stream.lua125
-rw-r--r--gamemode/shared/synchronize.lua22
-rw-r--r--gamemode/shared/system_admin.lua118
-rw-r--r--gamemode/shared/system_fatigue.lua46
-rw-r--r--gamemode/shared/system_heat.lua42
-rw-r--r--gamemode/shared/system_hunger.lua42
-rw-r--r--gamemode/shared/system_water.lua53
-rw-r--r--gamemode/shared/vars.lua3
-rw-r--r--gamemode/shared/weaponswap.lua168
22 files changed, 1565 insertions, 0 deletions
diff --git a/gamemode/shared/accounts.lua b/gamemode/shared/accounts.lua
new file mode 100644
index 0000000..06cc296
--- /dev/null
+++ b/gamemode/shared/accounts.lua
@@ -0,0 +1,153 @@
+
+--Not sure if i should make this MySQLoo, textbased or SQLites
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("UpdatePlayerDB")
+
+ concommand.Add("ws_printallaccounts",function(pl)
+ if (!IsValid(pl) or !pl:IsAdmin()) then return end
+
+ local dat = sql.Query("SELECT * FROM WS2Accounts")
+
+ pl:ChatPrint(table.Count(dat) .. " accounts registered!")
+ end)
+
+ concommand.Add("ws_setrank",function(pl,com,arg)
+ if (!IsValid(pl) or !pl:IsAdmin()) then return end
+ if (!arg[2]) then return end
+
+ local name = arg[1]:lower()
+ local rank = tonumber(arg[2])
+
+ for k,v in pairs(player.GetAll()) do
+ if (v:Nick():find(name)) then
+ v.Rank = rank
+ v:ChatPrint("Your rank has been set to "..rank)
+
+ if (rank == 1) then v:SetUserGroup("admin") end
+
+ MsgN("Player "..v:Nick().." has been set to "..rank)
+ break
+ end
+ end
+ end)
+
+
+ hook.Add("Initialize","InitSQLiteDB",function()
+ if (!sql.TableExists("WS2Accounts")) then
+ local Dat = {
+ "id INT UNSIGNED NOT NULL PRIMARY KEY",
+ "inventory MEDIUMTEXT",
+ "equipped MEDIUMTEXT",
+ "rank TINYINT",
+ "timespent INT UNSIGNED",
+ }
+
+ Msg("Table not found. Creating new table for accounts!\n")
+ sql.Query("CREATE TABLE IF NOT EXISTS WS2Accounts ("..table.concat(Dat,",")..");")
+ end
+ end)
+
+ hook.Add("PlayerAuthed","InitSQLitePlayer",function(pl)
+ pl:LoadPlayer()
+ end)
+
+ hook.Add("EntityRemoved","UpdatePlayer",function(ent)
+ if (ent:IsPlayer()) then
+ local f,err = pcall(ent.UpdateSQLite,ent)
+ end
+ end)
+
+ hook.Add("Tick","UpdatePlayerDB",function()
+ for k,v in pairs(player.GetAll()) do
+ if (v.UpdateTime and v.UpdateTime < CurTime()) then
+ v.UpdateTime = CurTime()+30
+ v:UpdateSQLite()
+ end
+ end
+ end)
+
+ function meta:LoadPlayer()
+ local ID = self:SteamID64()
+
+ if (!ID) then
+ Msg("Retrying loading player "..self:Nick().."\n")
+ timer.Simple(1,function() if (IsValid(self)) then self:LoadPlayer() end end)
+ return
+ end
+
+ local data = sql.Query("SELECT * FROM WS2Accounts WHERE id="..ID)
+
+ self.UpdateTime = CurTime()+30
+ self.LastJoined = CurTime()
+ self.AccountInv = {}
+ self.Equipped = {}
+ self.Rank = 0
+
+ self.StoredID = ID
+
+ if (!data) then
+ Msg("Player "..self:Nick().." was not found. Creating new account!\n")
+
+ local dat = {
+ self.StoredID,
+ "''",
+ "''",
+ 0,
+ 0,
+ }
+
+ sql.Query("INSERT INTO WS2Accounts(id,inventory,equipped,rank,timespent) VALUES ("..table.concat(dat,",")..");")
+ else
+ self.LastJoined = CurTime()-tonumber(data[1].timespent)
+ self.Rank = tonumber(data[1].rank)
+
+ for k,v in pairs(string.Explode("\n",data[1].inventory)) do
+ local Ab = string.Explode("æ",v)
+ if (Ab[2]) then self:AddAccountItem(Ab[1],tonumber(Ab[2])) end
+ end
+
+ if (self.Rank == 1) then self:SetUserGroup("admin") self:ChatPrint("You are an admin on this server!") end
+
+ net.Start("UpdatePlayerDB")
+ net.WriteUInt(tonumber(data[1].timespent),32)
+ net.WriteUInt(self.Rank,4)
+ net.Send(self)
+ end
+ end
+
+ function meta:UpdateSQLite()
+ if (!self.StoredID) then self:Kick("Your ID seems to be invailed. Reconnect please!") return end
+
+ local Inventory = ""
+
+ for k,v in pairs(self:GetAccountInventory()) do
+ Inventory = Inventory..v.Name.."æ"..v.Quantity.."\n"
+ end
+
+ local dat = {
+ "timespent="..math.ceil(CurTime()-self.LastJoined),
+ "rank="..self.Rank,
+ "inventory="..SQLStr(Inventory)
+ }
+
+ sql.Query("UPDATE WS2Accounts SET "..table.concat(dat,",").." WHERE id="..self.StoredID..";")
+ end
+else
+ net.Receive("UpdatePlayerDB",function()
+ local pl = LocalPlayer()
+
+ pl.LastJoined = CurTime()-net.ReadUInt(32)
+ pl.Rank = net.ReadUInt(4)
+ end)
+end
+
+function meta:GetRank()
+ return self.Rank or 0
+end
+
+function meta:GetTimeSpent()
+ return ((self.LastJoined and CurTime() - self.LastJoined) or 0)
+end \ No newline at end of file
diff --git a/gamemode/shared/entity_ext.lua b/gamemode/shared/entity_ext.lua
new file mode 100644
index 0000000..c0e1b34
--- /dev/null
+++ b/gamemode/shared/entity_ext.lua
@@ -0,0 +1,19 @@
+local meta = FindMetaTable("Entity")
+
+function meta:IsTree()
+ local model = self:GetModel()
+ local class = self:GetClass()
+ return ((model:find("tree") or model:find("pine")) and !class:find("ws_"))
+end
+
+function meta:IsRock()
+ local model = self:GetModel()
+ local class = self:GetClass()
+ return (model:find("rock") and !class:find("ws_"))
+end
+
+function meta:IsPlant()
+ local model = self:GetModel()
+ local class = self:GetClass()
+ return (model:find("antlionhill") and !class:find("ws_"))
+end \ No newline at end of file
diff --git a/gamemode/shared/game_rounds.lua b/gamemode/shared/game_rounds.lua
new file mode 100644
index 0000000..67b77c9
--- /dev/null
+++ b/gamemode/shared/game_rounds.lua
@@ -0,0 +1,105 @@
+local meta = FindMetaTable("Player")
+local Time = 10
+
+if (SERVER) then
+ util.AddNetworkString("RoundStart")
+
+ function GM:StartCountDown()
+ self.CountDown = CurTime()+Time+1
+
+ //items to clean up in between rounds
+ cleanup = {
+ "ws_alter",
+ "ws_arrow",
+ "ws_barrel",
+ "ws_campfire",
+ "ws_grave",
+ "ws_infuser",
+ "ws_item",
+ "ws_prop",
+ "ws_researchtable",
+ "ws_shop",
+ "ws_rune",
+ }
+ for k,v in pairs(cleanup) do
+ for i,j in pairs(ents.FindByClass(v)) do
+ j:Remove()
+ end
+ end
+
+
+
+ --Generate a completly new rain of props :D
+ self:GeneratePropRain()
+
+ net.Start("RoundStart")
+ net.WriteUInt(Time,8)
+ net.Broadcast()
+ end
+
+ function meta:UpdateRoundTimer()
+ if (!self.CountDown or self.CountDown<CurTime()) then return end
+
+ net.Start("RoundStart")
+ net.WriteUInt(math.floor(self.CountDown-CurTime()),8)
+ net.Send(self)
+ end
+ hasprinted = false
+ hook.Add("Tick","CountDowner",function()
+ if (GAMEMODE.GameOn) then
+ if (#player.GetAll() < 2) then
+ --TODO: Less than 2 players in the server
+ GAMEMODE.CountDown = nil
+ GAMEMODE.GameOn = false
+ return
+ elseif (#player.GetAllHumans() < 2) then
+ GAMEMODE.CountDown = nil
+ GAMEMODE.GameOn = false
+ for k,v in pairs(player.GetAllHumans()) do
+ v:AddAccountItem(table.Random(GetItemsByClass("account")).Name,1)
+ end
+
+ timer.Simple(Time,function() for k,v in pairs(player.GetAllHumans()) do v:Kill() end end)
+
+ GAMEMODE:StartCountDown()
+ return
+ end
+ else
+ if(!hasprinted) then
+ for k,v in pairs(player.GetAll()) do
+ v:ChatPrint("Winter survival requires 2 players or more to play")
+ v:ChatPrint("Invite a friend!")
+ end
+ hasprinted = true
+ end
+ end
+
+ if (GAMEMODE.GameOn or !GAMEMODE.CountDown) then return end
+
+ if (GAMEMODE.CountDown < CurTime()) then
+ print("Test2")
+ if (#player.GetAll() < 2) then
+ GAMEMODE.CountDown = CurTime()+Time+1
+ return
+ end
+
+ for k,v in pairs(player.GetAll()) do
+ if (v:IsPigeon()) then
+ if (IsValid(v.Pigeon)) then v.Pigeon:Remove() end
+ v:SetHuman(true)
+ v:KillSilent()
+
+ timer.Simple(1,function() if (IsValid(v) and !v:Alive()) then v:Spawn() end end)
+ end
+ end
+
+ GAMEMODE.GameOn = true
+ end
+ end)
+else
+ net.Receive("RoundStart",function() GAMEMODE.CountDown = CurTime()+net.ReadUInt(8) end)
+end
+
+function GetCountDown()
+ return GAMEMODE.CountDown
+end
diff --git a/gamemode/shared/player_accountinventory.lua b/gamemode/shared/player_accountinventory.lua
new file mode 100644
index 0000000..2a1b684
--- /dev/null
+++ b/gamemode/shared/player_accountinventory.lua
@@ -0,0 +1,98 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("UpdateAccountInventory")
+
+ function meta:UpdateAccountSlot(id)
+ if (!self.AccountInv[id]) then return end
+
+ net.Start("UpdateAccountInventory")
+ net.WriteUInt(id,5)
+ net.WriteString(self.AccountInv[id].Name)
+ net.WriteUInt(self.AccountInv[id].Quantity,32)
+ net.Send(self)
+ end
+
+ function meta:AddAccountItem(item,quantity)
+ local Item = GetItemByName(item)
+
+ if (!Item) then return end
+ if (!self.AccountInv) then self.AccountInv = {} end
+
+ --First search for existing items
+ for i = 1,MAIN_MAX_SLOTS do
+ if (self.AccountInv[i] and self.AccountInv[i].Name == item) then
+ self.AccountInv[i].Quantity = self.AccountInv[i].Quantity+quantity
+ self:UpdateAccountSlot(i)
+ return
+ end
+ end
+
+ --If it hasnt found any existing item, find an empty spot
+ for i = 1,MAIN_MAX_SLOTS do
+ if (!self.AccountInv[i]) then
+ self.AccountInv[i] = {Name = item,Quantity = quantity}
+ self:UpdateAccountSlot(i)
+ return
+ end
+ end
+ end
+
+ function meta:RemoveAccountItem(item,quantity)
+ for i = 1,MAIN_MAX_SLOTS do
+ if (self.AccountInv[i] and self.AccountInv[i].Name == item) then
+ if (self.AccountInv[i].Quantity > quantity) then
+ self.AccountInv[i].Quantity = self.AccountInv[i].Quantity-quantity
+ self:UpdateAccountSlot(i)
+ return
+ else
+ quantity = quantity - self.AccountInv[i].Quantity
+
+ self.AccountInv[i].Quantity = 0
+
+ self:UpdateAccountSlot(i)
+
+ self.AccountInv[i] = nil
+
+ if (quantity > 0) then self:RemoveAccountItem(item,quantity) return end
+ end
+ end
+ end
+ end
+else
+ net.Receive("UpdateAccountInventory",function()
+ local pl = LocalPlayer()
+
+ if (!pl.AccountInv) then pl.AccountInv = {} end
+
+ local ID = net.ReadUInt(5)
+ pl.AccountInv[ID] = {Name = net.ReadString(),Quantity = net.ReadUInt(32)}
+
+ if (pl.AccountInv[ID].Quantity <= 0) then pl.AccountInv[ID] = nil end
+
+ ReloadAccountMenu()
+ end)
+end
+
+function meta:GetAccountInventory()
+ return self.AccountInv or {}
+end
+
+function meta:HasAccountItem(name,quantity)
+ if (!self.AccountInv) then return end
+
+ quantity = quantity or 1
+
+ for k,v in pairs(self.AccountInv) do
+ if (v.Name == name and v.Quantity >= quantity) then
+ return k
+ end
+ end
+
+ return false
+end
+
+function meta:GetAccountSlot(id)
+ return (self.AccountInv and self.AccountInv[id]) or nil
+end \ No newline at end of file
diff --git a/gamemode/shared/player_dropitem.lua b/gamemode/shared/player_dropitem.lua
new file mode 100644
index 0000000..717e1b5
--- /dev/null
+++ b/gamemode/shared/player_dropitem.lua
@@ -0,0 +1,26 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("DropItemReq")
+
+ function meta:DropItem(item,bAccount)
+ if ((!bAccount and !self:HasItem(item)) or (bAccount and !self:HasAccountItem(item))) then return end
+
+ if (bAccount) then self:RemoveAccountItem(item,1) return
+ else self:RemoveItem(item,1) end
+
+ SpawnWSItem(item,self:GetShootPos()+self:GetAimVector()*20)
+ end
+
+ net.Receive("DropItemReq",function(seq,pl) pl:DropItem(net.ReadString(),util.tobool(net.ReadBit())) end)
+else
+ function RequestDropItem(item,bAccount)
+ net.Start("DropItemReq")
+ net.WriteString(item)
+ net.WriteBit(bAccount)
+ net.SendToServer()
+ end
+end
+
+ \ No newline at end of file
diff --git a/gamemode/shared/player_ghost.lua b/gamemode/shared/player_ghost.lua
new file mode 100644
index 0000000..049ede7
--- /dev/null
+++ b/gamemode/shared/player_ghost.lua
@@ -0,0 +1,97 @@
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("Ghost")
+ util.AddNetworkString("GhostRemove")
+
+ function meta:GhostStructure(item)
+ item = GetItemByName(item)
+
+ if (!item or !item.Ghost) then return end
+ if (!self.StructurePlace) then self.StructurePlace = true end
+
+ net.Start("Ghost")
+ net.WriteString(item.Name)
+ net.Send(self)
+ end
+
+ function meta:GhostRemove()
+ self.StructurePlace = false
+ net.Start("GhostRemove") net.Send(self)
+ end
+else
+ local Zero = Vector(0,0,0)
+ local gr = Color(0,255,0,100)
+ local Box = Vector(8,8,8)
+
+ net.Receive("Ghost",function()
+ local pl = LocalPlayer()
+ local It = GetItemByName(net.ReadString())
+
+ if (!It) then return end
+ if (!IsValid(pl.Ghost)) then pl.Ghost = ClientsideModel("error.mdl") pl.Ghost:SetNoDraw(true) end
+
+ pl.GhostItem = It
+ pl.StructurePlace = true
+ end)
+
+ net.Receive("GhostRemove",function() LocalPlayer().StructurePlace = false end)
+
+ hook.Add("PostDrawTranslucentRenderables","GhostStructure",function()
+ local pl = LocalPlayer()
+
+ if (pl:IsPigeon() or !pl.GhostItem or !pl.GhostItem.Ghost or !IsValid(pl.Ghost) or !pl.StructurePlace) then return end
+
+ local Ghost = pl.Ghost
+ local Aim = Angle(0,pl:GetAimVector():Angle().y+90,0)
+ local Pos = util.TraceHull({
+ start = pl:GetShootPos(),
+ endpos = pl:GetShootPos()+pl:GetAimVector()*pl.GhostItem.Range,
+ filter = pl,
+ mins = Box*-1,
+ maxs = Box,
+ })
+
+ local CanP = pl:CanPlaceStructure(Pos)
+ Pos = Pos.HitPos
+
+ for k,v in pairs(pl.GhostItem.Ghost) do
+ local OffPos = v.Pos*1
+ OffPos:Rotate(Aim)
+
+ Ghost:SetModel(v.Model)
+ Ghost:SetRenderOrigin(Pos+OffPos)
+ Ghost:SetRenderAngles(v.Ang+Aim)
+
+ local mat = Matrix()
+ mat:Scale( v.Size or Zero )
+
+ Ghost:EnableMatrix( "RenderMultiply", mat )
+ Ghost:SetupBones()
+
+ if (CanP) then render.SetColorModulation(0,10,0)
+ else render.SetColorModulation(10,0,0) end
+
+ render.SetBlend(0.7)
+ Ghost:DrawModel()
+ render.SetColorModulation(1,1,1)
+ render.SetBlend(1)
+ end
+
+ Ghost:SetRenderOrigin(Pos)
+ end)
+end
+
+function meta:CanPlaceStructure(Tr)
+ if (Tr and Tr.HitPos) then
+ local A = util.PointContents( Tr.HitPos )
+ local Ang = math.AngleNormalize(Tr.HitNormal:Angle())
+
+ if (A == CONTENTS_WATER or A == CONTENTS_WATER+CONTENTS_TRANSLUCENT ) then return false end
+ if (Ang.p < -120 or Ang.p > -60) then return false end
+
+ --if (!Tr.HitWorld) then return false end
+ end
+
+ return self.StructurePlace
+end
diff --git a/gamemode/shared/player_human.lua b/gamemode/shared/player_human.lua
new file mode 100644
index 0000000..8fa6997
--- /dev/null
+++ b/gamemode/shared/player_human.lua
@@ -0,0 +1,66 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("SetHuman")
+
+ function meta:SetHuman(bool)
+ self.IsHuman = bool
+ self.Inventory = {}
+ self.Weapons = {}
+
+ net.Start("SetHuman")
+ net.WriteEntity(self)
+ net.WriteBit(self.IsHuman)
+ net.Broadcast()
+ end
+
+ function meta:UpdateHumans()
+ for k,v in pairs(player.GetAll()) do
+ if (v.IsHuman) then
+ timer.Simple(math.Rand(0.1,0.2),function()
+ net.Start("SetHuman")
+ net.WriteEntity(v)
+ net.WriteBit(true)
+ net.Send(self)
+ end)
+ end
+ end
+ end
+else
+ net.Receive("SetHuman",function()
+ local pl = net.ReadEntity()
+
+ pl.IsHuman = util.tobool(net.ReadBit())
+ pl.Inventory = {}
+ pl.Weapons = {}
+ end)
+end
+
+function meta:IsPigeon()
+ return !util.tobool(self.IsHuman)
+end
+
+function player.GetAllHumans()
+ local dat = {}
+
+ for k,v in pairs(player.GetAll()) do
+ if (!v:IsPigeon()) then
+ table.insert(dat,v)
+ end
+ end
+
+ return dat
+end
+
+function player.GetAllHumansAlive()
+ local dat = {}
+
+ for k,v in pairs(player.GetAll()) do
+ if (!v:IsPigeon() and v:Alive()) then
+ table.insert(dat,v)
+ end
+ end
+
+ return dat
+end
diff --git a/gamemode/shared/player_inventory.lua b/gamemode/shared/player_inventory.lua
new file mode 100644
index 0000000..8cb31ea
--- /dev/null
+++ b/gamemode/shared/player_inventory.lua
@@ -0,0 +1,99 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("UpdateInventory")
+
+ function meta:UpdateSlot(id)
+ if (!self.Inventory[id]) then return end
+
+ net.Start("UpdateInventory")
+ net.WriteUInt(id,5)
+ net.WriteString(self.Inventory[id].Name)
+ net.WriteUInt(self.Inventory[id].Quantity,32)
+ net.Send(self)
+ end
+
+ function meta:AddItem(item,quantity)
+ local Item = GetItemByName(item)
+
+ if (!Item) then return end
+ if (!self.Inventory) then self.Inventory = {} end
+
+ --First search for existing items
+ for i = 1,MAIN_MAX_SLOTS do
+ if (self.Inventory[i] and self.Inventory[i].Name == item) then
+ self.Inventory[i].Quantity = self.Inventory[i].Quantity+quantity
+ self:UpdateSlot(i)
+ return
+ end
+ end
+
+ --If it hasnt found any existing item, find an empty spot
+ for i = 1,MAIN_MAX_SLOTS do
+ if (!self.Inventory[i]) then
+ self.Inventory[i] = {Name = item,Quantity = quantity}
+ self:UpdateSlot(i)
+ return
+ end
+ end
+ end
+
+ function meta:RemoveItem(item,quantity)
+ for i = 1,MAIN_MAX_SLOTS do
+ if (self.Inventory[i] and self.Inventory[i].Name == item) then
+ if (self.Inventory[i].Quantity > quantity) then
+ self.Inventory[i].Quantity = self.Inventory[i].Quantity-quantity
+ self:UpdateSlot(i)
+ return
+ else
+ quantity = quantity - self.Inventory[i].Quantity
+
+ self.Inventory[i].Quantity = 0
+
+ self:UpdateSlot(i)
+
+ self.Inventory[i] = nil
+
+ if (quantity > 0) then self:RemoveItem(item,quantity) return end
+ end
+ end
+ end
+ end
+else
+ net.Receive("UpdateInventory",function()
+ local pl = LocalPlayer()
+
+ if (!pl.Inventory) then pl.Inventory = {} end
+
+ local ID = net.ReadUInt(5)
+ pl.Inventory[ID] = {Name = net.ReadString(),Quantity = net.ReadUInt(32)}
+
+ if (pl.Inventory[ID].Quantity <= 0) then pl.Inventory[ID] = nil end
+
+ ReloadInventory()
+ end)
+end
+
+
+function meta:GetInventory()
+ return self.Inventory or {}
+end
+
+function meta:HasItem(name,quantity)
+ if (!self.Inventory) then return end
+
+ quantity = quantity or 1
+
+ for k,v in pairs(self.Inventory) do
+ if (v.Name == name and v.Quantity >= quantity) then
+ return k
+ end
+ end
+
+ return false
+end
+
+function meta:GetSlot(id)
+ return (self.Inventory and self.Inventory[id]) or nil
+end \ No newline at end of file
diff --git a/gamemode/shared/player_lootventory.lua b/gamemode/shared/player_lootventory.lua
new file mode 100644
index 0000000..b973932
--- /dev/null
+++ b/gamemode/shared/player_lootventory.lua
@@ -0,0 +1,53 @@
+local insert = table.insert
+
+if (SERVER) then
+ util.AddNetworkString("OpenLootventory")
+ util.AddNetworkString("DemandLootventoryUpdate")
+
+ function OpenLootventory(pl,items,entity)
+ if (!IsValid(pl) or !items) then return end
+
+ net.Start("OpenLootventory")
+ net.WriteEntity(entity)
+ for k,v in pairs(items) do
+ if (v.Name and v.Quantity) then
+ net.WriteBit(true)
+ net.WriteString(v.Name)
+ net.WriteUInt(v.Quantity,32)
+ end
+ end
+ net.Send(pl)
+ end
+
+ net.Receive("DemandLootventoryUpdate",function(siz,pl)
+ local ent = net.ReadEntity()
+
+ if (!IsValid(ent) or !ent.GetItems) then return end
+ if (pl:GetPos():Distance(ent:GetPos()) > 200) then return end
+
+ OpenLootventory(pl,ent:GetItems(),ent)
+ end)
+else
+ net.Receive("OpenLootventory",function()
+ local dat = {}
+ local ent = net.ReadEntity()
+
+ while (util.tobool(net.ReadBit())) do
+ local Ab = GetItemByName(net.ReadString())
+ local Co = net.ReadUInt(32)
+
+ if (Ab and Co > 0) then insert(dat,{Name = Ab.Name, Quantity = Co}) end
+ end
+
+ MakeLootventory(dat,ent)
+ GAMEMODE:OnSpawnMenuOpen()
+ end)
+
+ function DemandLootventoryUpdate(entity)
+ if (!IsLootventoryOpen()) then return end
+
+ net.Start("DemandLootventoryUpdate")
+ net.WriteEntity(entity)
+ net.SendToServer()
+ end
+end \ No newline at end of file
diff --git a/gamemode/shared/player_pigeon.lua b/gamemode/shared/player_pigeon.lua
new file mode 100644
index 0000000..2256af0
--- /dev/null
+++ b/gamemode/shared/player_pigeon.lua
@@ -0,0 +1,44 @@
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("AssignPigeon")
+
+ function meta:SpawnPigeon()
+ if (IsValid(self.Pigeon)) then return end
+
+ self.Pigeon = ents.Create("ws_pigeon")
+ self.Pigeon:SetPos(self:GetPos())
+ self.Pigeon:SetPlayer(self)
+ self.Pigeon:Spawn()
+ self.Pigeon:Activate()
+
+ print("Spawned Pigeon: "..self:Nick())
+
+ timer.Simple(0.2,function()
+ net.Start("AssignPigeon")
+ net.WriteEntity(self)
+ net.WriteEntity(self.Pigeon)
+ net.Broadcast() end)
+ end
+
+ function meta:UpdatePigeons()
+ for k,v in pairs(player.GetAll()) do
+ if (IsValid(v.Pigeon)) then
+ timer.Simple(math.Rand(0.1,0.2),function()
+ net.Start("AssignPigeon")
+ net.WriteEntity(v)
+ net.WriteEntity(v.Pigeon)
+ net.Send(self)
+ end)
+ end
+ end
+ end
+else
+ net.Receive("AssignPigeon",function() net.ReadEntity().Pigeon = net.ReadEntity() end)
+end
+
+function meta:GetPigeon()
+ return self.Pigeon
+end
+
+
diff --git a/gamemode/shared/player_recipes.lua b/gamemode/shared/player_recipes.lua
new file mode 100644
index 0000000..4a85535
--- /dev/null
+++ b/gamemode/shared/player_recipes.lua
@@ -0,0 +1,102 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("CreateRecipe")
+ util.AddNetworkString("ResetRecipes")
+
+ function meta:CreateRecipe(item)
+ if (!self:CanCreateItem(item)) then return end
+
+ local Rec,Item = GetRecipeForItem(item)
+
+ if (!Rec) then return false end
+
+ for a,b in pairs(Rec.Resources) do
+ self:RemoveItem(a,b)
+ end
+
+ if(Item.OnCraft) then
+ Item:OnCraft(self)
+ end
+
+ self:AddItem(item,1)
+ end
+
+ function meta:ResetKnownRecipes()
+ net.Start("ResetRecipes") net.Send(self)
+ end
+
+ net.Receive("CreateRecipe",function(siz,pl) pl:CreateRecipe(net.ReadString()) end)
+else
+ function RequestCreateRecipe(item)
+ net.Start("CreateRecipe")
+ net.WriteString(item)
+ net.SendToServer()
+ end
+
+ function DiscoverItems(Combinations)
+ local Dat = {}
+
+ for k,v in pairs(GAMEMODE.Recipes) do
+ local Ab = v.Recipe.Resources
+ local Tools = v.Recipe.Tools
+ local PA = table.Count(Ab)
+
+ if (PA == table.Count(Combinations)) then
+ local Check = 0
+
+ for e,c in pairs(Combinations) do
+ for a,b in pairs(Ab) do
+ if (c.Name == a and c.Quantity == b) then Check = Check+1 break end
+ end
+ end
+
+ if (Check == PA) then table.insert(Dat,v) end
+ end
+ end
+
+ if (table.Count(Dat) > 0) then
+ for e,c in pairs(GAMEMODE.KnownRecipes) do
+ for k,v in pairs(Dat) do
+ if (v.Name == c.Name) then table.remove(Dat,k) break end
+ end
+ end
+
+ if (table.Count(Dat) > 0) then
+ for k,v in pairs(Dat) do
+ LocalPlayer():AddNote("You discovered the recipe for "..v.Name)
+ end
+
+ table.Add(GAMEMODE.KnownRecipes,Dat)
+
+ ReloadRecipes()
+ end
+ end
+ end
+
+ net.Receive("ResetRecipes",function()
+ GAMEMODE.KnownRecipes = {
+ GetItemByName("Axe"),
+ GetItemByName("Campfire"),
+ GetItemByName("Pickaxe"),
+ GetItemByName("Research Table")
+ }
+
+ ReloadRecipes()
+ end)
+end
+
+function meta:CanCreateItem(name)
+ local Rec,Item = GetRecipeForItem(name)
+
+ if (!Rec) then return false end
+
+ for k,v in pairs(Rec) do
+ for a,b in pairs(v) do
+ if (!self:HasItem(a,b)) then return false end
+ end
+ end
+
+ return true
+end
diff --git a/gamemode/shared/player_transferitem.lua b/gamemode/shared/player_transferitem.lua
new file mode 100644
index 0000000..944af63
--- /dev/null
+++ b/gamemode/shared/player_transferitem.lua
@@ -0,0 +1,44 @@
+
+if (SERVER) then
+ util.AddNetworkString("RequestTransfer")
+ util.AddNetworkString("RequestTransferFrom")
+
+ net.Receive("RequestTransfer",function(siz,pl)
+ local item = net.ReadString()
+ local quan = net.ReadUInt(32)
+ local ent = net.ReadEntity()
+
+ if (!IsValid(ent) or !ent.AddItem) then return end
+
+ if (!pl:HasItem(item,quan)) then return end
+
+ pl:RemoveItem(item,quan)
+ ent:AddItem(item,quan)
+ end)
+
+ net.Receive("RequestTransferFrom",function(siz,pl)
+ local item = net.ReadString()
+ local quan = net.ReadUInt(32)
+ local ent = net.ReadEntity()
+
+ if (!IsValid(ent) or !ent.TakeItem) then return end
+
+ ent:TakeItem(pl,item,quan)
+ end)
+else
+ function TransferItems(item,quantity,to)
+ net.Start("RequestTransfer")
+ net.WriteString(item)
+ net.WriteUInt(quantity,32)
+ net.WriteEntity(to)
+ net.SendToServer()
+ end
+
+ function DemandItems(item,quantity,from)
+ net.Start("RequestTransferFrom")
+ net.WriteString(item)
+ net.WriteUInt(quantity,32)
+ net.WriteEntity(from)
+ net.SendToServer()
+ end
+end \ No newline at end of file
diff --git a/gamemode/shared/player_useitem.lua b/gamemode/shared/player_useitem.lua
new file mode 100644
index 0000000..128146a
--- /dev/null
+++ b/gamemode/shared/player_useitem.lua
@@ -0,0 +1,40 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("UseItem")
+ util.AddNetworkString("UseItemReq")
+
+ function meta:UseItem(item,bAccount)
+ if ((!bAccount and !self:HasItem(item)) or (bAccount and !self:HasAccountItem(item))) then return end
+
+ local IT = GetItemByName(item)
+
+ if (IT.OnUse) then
+ IT:OnUse(self)
+
+ net.Start("UseItem")
+ net.WriteEntity(self)
+ net.WriteString(item)
+ net.Broadcast()
+ end
+ end
+
+ net.Receive("UseItemReq",function(seq,pl) pl:UseItem(net.ReadString(),util.tobool(net.ReadBit())) end)
+else
+ net.Receive("UseItem",function()
+ local pl = net.ReadEntity()
+ local it = GetItemByName(net.ReadString())
+
+ if (it.OnUse) then it:OnUse(pl) end
+ end)
+
+ function RequestUseItem(item,bAccount)
+ net.Start("UseItemReq")
+ net.WriteString(item)
+ net.WriteBit(bAccount)
+ net.SendToServer()
+ end
+end
+
+ \ No newline at end of file
diff --git a/gamemode/shared/stream.lua b/gamemode/shared/stream.lua
new file mode 100644
index 0000000..e4d45e8
--- /dev/null
+++ b/gamemode/shared/stream.lua
@@ -0,0 +1,125 @@
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("STREAM")
+ util.AddNetworkString("ENDSTREAM")
+
+ concommand.Add("StreamURL",function(pl,com,args)
+ if (!IsValid(pl)) then return end
+
+ pl:StreamSong(table.concat(args," "))
+ end)
+
+ concommand.Add("EndStream",function(pl,com,args)
+ if (!IsValid(pl)) then return end
+
+ pl:EndStream()
+ end)
+
+ function meta:StreamSong(URL)
+ if (!self:IsAdmin()) then return end
+
+ self.URL = URL
+
+ net.Start("STREAM")
+ net.WriteEntity(self)
+ net.WriteString(URL)
+ net.Broadcast()
+ end
+
+ function meta:EndStream()
+ if (!self:IsAdmin()) then return end
+
+ self.URL = nil
+
+ net.Start("ENDSTREAM")
+ net.WriteEntity(self)
+ net.Broadcast()
+ end
+
+ function meta:UpdateStream(v)
+ if (v.URL) then
+ net.Start("STREAM")
+ net.WriteEntity(v)
+ net.WriteString(v.URL)
+ net.Send(self)
+ end
+ end
+else
+ local Emitter = ParticleEmitter( Vector(0,0,0) )
+ local Up = Vector(0,0,20)
+ local Retries = 0
+ local Streams = {}
+
+ function TryURL(url,pl)
+ if (!IsValid(pl)) then return end
+
+ local ID = pl:UniqueID()
+ if (Streams[ID]) then Streams[ID]:Stop() Streams[ID] = nil end
+
+ if (Retries < 4) then
+ sound.PlayURL( url, "3d mono noplay", function( chan )
+ if (!chan) then TryURL(url,pl) Retries = Retries+1
+ elseif (IsValid(pl)) then Streams[ID] = chan chan:Play() Retries = 0 end
+ end)
+ else
+ Retries = 0
+ Msg("Couldn't play "..url.." \n")
+ end
+ end
+
+ net.Receive("STREAM",function()
+ local pl = net.ReadEntity()
+ local URL = net.ReadString()
+
+ if (!IsValid(pl)) then return end
+
+ TryURL(URL,pl)
+ end)
+
+ net.Receive("ENDSTREAM",function()
+ local pl = net.ReadEntity()
+
+ if (!IsValid(pl)) then return end
+
+ local ID = pl:UniqueID()
+ if (Streams[ID]) then Streams[ID]:Stop() Streams[ID] = nil end
+ end)
+
+ hook.Add("Think","Streamer",function()
+ for k,st in pairs(Streams) do
+ if (!st) then table.remove(Streams,k)
+ else
+ local v = player.GetByUniqueID(k)
+
+ if (!IsValid(v)) then
+ st:Stop()
+ table.remove(Streams,k)
+ else
+ local pig = v:GetPigeon()
+ local Pos = v:GetPos()
+
+ if (IsValid(pig)) then Pos = pig:GetPos() end
+
+ if (!v.PTime or v.PTime < CurTime()) then
+ local particle = Emitter:Add( "lam/musicnotes/note"..math.random(1,2), Pos + VectorRand()*15)
+ particle:SetDieTime( 1 )
+ particle:SetVelocity( Up )
+
+ particle:SetStartAlpha( 250 )
+ particle:SetEndAlpha( 0 )
+
+ particle:SetStartSize( 10 )
+ particle:SetEndSize( 10 )
+
+ particle:SetColor( math.random( 0, 250 ), math.random( 0, 250 ), math.random( 0, 250 ) )
+
+ v.PTime = CurTime()+0.1
+ end
+
+ st:SetPos(Pos)
+ end
+ end
+ end
+ end)
+end \ No newline at end of file
diff --git a/gamemode/shared/synchronize.lua b/gamemode/shared/synchronize.lua
new file mode 100644
index 0000000..126c616
--- /dev/null
+++ b/gamemode/shared/synchronize.lua
@@ -0,0 +1,22 @@
+
+if (SERVER) then
+ util.AddNetworkString("LoadEntity_WS")
+
+ net.Receive("LoadEntity_WS",function(siz,pl)
+ local Ab = net.ReadEntity()
+
+ if (Ab:IsPlayer()) then
+ Ab:UpdateSelection(pl)
+ --pl:UpdateStream(Ab)
+ end
+ end)
+else
+ local Q = 0
+ function GM:NetworkEntityCreated(ent)
+ Q=Q+1
+ timer.Simple(math.Rand(0.1,0.2)*Q,function()
+ net.Start("LoadEntity_WS") net.WriteEntity(ent) net.SendToServer()
+ Q=Q-1
+ end)
+ end
+end \ No newline at end of file
diff --git a/gamemode/shared/system_admin.lua b/gamemode/shared/system_admin.lua
new file mode 100644
index 0000000..14dfb3d
--- /dev/null
+++ b/gamemode/shared/system_admin.lua
@@ -0,0 +1,118 @@
+
+
+local meta = FindMetaTable("Player")
+local Banlist = {}
+
+local insert = table.insert
+
+if (SERVER) then
+ hook.Add("InitPostEntity","InitBanlist",function()
+ if (!sql.TableExists("Banlist")) then
+ local Dat = {
+ "id INTEGER PRIMARY KEY",
+ "steamid TEXT",
+ "time INT",
+ "name TEXT",
+ "reason TEXT",
+ }
+
+ Msg("No banlist was found.\nCreating new banlist!\n")
+ sql.Query("CREATE TABLE IF NOT EXISTS Banlist ("..table.concat(Dat,",")..");")
+ else
+ local dat = sql.Query("SELECT * FROM Banlist")
+
+ if (dat) then
+ for k,v in pairs(dat) do insert(Banlist,v.steamid) end
+ end
+ end
+ end)
+
+ hook.Add("CheckPassword","BlockBannedPlayers",function(SteamID64,NetworkID,ServerPassword,Password,Name)
+ if (table.HasValue(Banlist,util.SteamIDFrom64(SteamID64))) then
+ print(Name.." attempted to join, but was found in the banlist. Blocking access!")
+
+ return false, "You are banned from this server!"
+ end
+ end)
+
+ concommand.Add("mas_bansteamid",function(pl,com,arg)
+ if (!IsValid(pl) or !pl:IsAdmin()) then return end
+ if (!arg[3]) then return end
+
+ local steamid = arg[1]
+ local time = tonumber(arg[2] or 0)
+ local reason = table.concat(arg," ",3)
+
+ local dat = sql.Query("SELECT * FROM Banlist WHERE steamid="..SQLStr(steamid))
+
+ if (!dat) then
+ sql.Query("INSERT INTO Banlist(steamid,time,name,reason) VALUES ("..SQLStr(steamid)..","..time..",'Unknown',"..SQLStr(reason)..")")
+ insert(Banlist,steamid)
+
+ for k,v in pairs(player.GetAll()) do
+ if (v:SteamID() == steamid) then
+ v:Kick("Banned from server: "..reason)
+ end
+
+ v:ChatPrint(pl:Nick().." has banned "..steamid)
+ end
+
+ MsgN(pl:Nick().." has banned "..steamid)
+ else
+ MsgN(steamid.." was already located in the database.")
+ end
+ end)
+
+ concommand.Add("mas_unbansteamid",function(pl,com,arg)
+ if (!IsValid(pl) or !pl:IsAdmin()) then return end
+ if (!arg[1]) then return end
+
+ local dat = sql.Query("DELETE * FROM Banlist WHERE steamid="..SQLStr(arg[1]))
+
+ if (dat) then
+ MsgN(pl:Nick().." has unbanned "..arg[1])
+
+ for k,v in pairs(Banlist) do
+ if (v == arg[1]) then
+ table.remove(Banlist,k)
+ break
+ end
+ end
+ end
+ end)
+
+ concommand.Add("mas_printbannedplayers",function(pl,com,arg)
+ if (!IsValid(pl) or !pl:IsAdmin()) then return end
+
+ local dat = sql.Query("SELECT * FROM Banlist")
+
+ if (dat) then
+ for k,v in pairs(dat) do
+ pl:ChatPrint(v.steamid.." - "..v.name)
+ end
+ end
+ end)
+
+ concommand.Add("mas_banplayer",function(pl,com,arg)
+ if (!IsValid(pl) or !pl:IsAdmin()) then return end
+ if (!arg[3]) then return end
+
+ local name = arg[1]
+ local time = tonumber(arg[2] or 0)
+ local reason = table.concat(arg," ",3)
+
+ for k,v in pairs(player.GetAll()) do
+ if (v:Nick():lower():find(name:lower())) then
+ local dat = sql.Query("SELECT * FROM Banlist WHERE steamid="..SQLStr(v:SteamID()))
+
+ if (!dat) then
+ sql.Query("INSERT INTO Banlist(steamid,time,name,reason) VALUES ("..SQLStr(v:SteamID())..","..time..","..SQLStr(v:Nick())..","..SQLStr(reason)..")")
+ insert(Banlist,v:SteamID())
+ v:Kick("Banned from server: "..reason)
+ break
+ end
+ end
+ end
+ end)
+else
+end \ No newline at end of file
diff --git a/gamemode/shared/system_fatigue.lua b/gamemode/shared/system_fatigue.lua
new file mode 100644
index 0000000..9f5a413
--- /dev/null
+++ b/gamemode/shared/system_fatigue.lua
@@ -0,0 +1,46 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("SetFatigue")
+
+ local Tick = CurTime()
+
+ function meta:SetFatigue(s)
+ if (s > 100) then self:TakeDamage(s-100) s = 100 end
+ s = math.Clamp(s,0,100)
+
+ self.Fatigue = s
+
+ net.Start("SetFatigue")
+ net.WriteUInt(s,8)
+ net.Send(self)
+ end
+
+ function meta:AddFatigue(s)
+ self:SetFatigue(self:GetFatigue()+s)
+ end
+
+ hook.Add("Tick","Fatigue",function()
+ if (Tick < CurTime()) then
+ for k,v in pairs(player.GetAllHumans()) do
+ local Fat = v.Fatigue or 0
+
+ if (Fat > 0) then Fat = Fat-2 end
+ Fat = Fat+math.ceil(v:GetVelocity():Length()/100)
+
+ v:SetFatigue(Fat)
+ end
+
+ Tick = CurTime()+0.5
+ end
+ end)
+else
+ net.Receive("SetFatigue",function()
+ LocalPlayer().Fatigue = net.ReadUInt(8)
+ end)
+end
+
+function meta:GetFatigue()
+ return self.Fatigue or 0
+end
diff --git a/gamemode/shared/system_heat.lua b/gamemode/shared/system_heat.lua
new file mode 100644
index 0000000..84c9c30
--- /dev/null
+++ b/gamemode/shared/system_heat.lua
@@ -0,0 +1,42 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("SetHeat")
+
+ local Tick = CurTime()
+
+ function meta:SetHeat(s)
+ if (s > 100) then self:TakeDamage(s-100) s = 100 end
+ s = math.Clamp(s,0,100)
+
+ self.Heat = s
+
+ net.Start("SetHeat")
+ net.WriteUInt(s,8)
+ net.Send(self)
+ end
+
+ function meta:AddHeat(s)
+ self:SetHeat(self:GetHeat()+s)
+ end
+
+ hook.Add("Tick","Heat",function()
+ if (Tick < CurTime()) then
+ for k,v in pairs(player.GetAllHumans()) do
+ v:AddHeat(1+v:WaterLevel())
+ end
+
+ Tick = CurTime()+1.5
+ end
+ end)
+else
+ net.Receive("SetHeat",function()
+ LocalPlayer().Heat = net.ReadUInt(8)
+ end)
+end
+
+function meta:GetHeat()
+ return self.Heat or 0
+end
+ \ No newline at end of file
diff --git a/gamemode/shared/system_hunger.lua b/gamemode/shared/system_hunger.lua
new file mode 100644
index 0000000..99128b1
--- /dev/null
+++ b/gamemode/shared/system_hunger.lua
@@ -0,0 +1,42 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("SetHunger")
+
+ local Tick = CurTime()
+
+ function meta:SetHunger(s)
+ if (s > 100) then self:TakeDamage(s-100) s = 100 end
+ s = math.Clamp(s,0,100)
+
+ self.Hunger = s
+
+ net.Start("SetHunger")
+ net.WriteUInt(s,8)
+ net.Send(self)
+ end
+
+ function meta:AddHunger(s)
+ self:SetHunger(self:GetHunger()+s)
+ end
+
+ hook.Add("Tick","Hunger",function()
+ if (Tick < CurTime()) then
+ for k,v in pairs(player.GetAllHumans()) do
+ v:AddHunger(1)
+ end
+
+ Tick = CurTime()+10
+ end
+ end)
+else
+ net.Receive("SetHunger",function()
+ LocalPlayer().Hunger = net.ReadUInt(8)
+ end)
+end
+
+function meta:GetHunger()
+ return self.Hunger or 0
+end
+ \ No newline at end of file
diff --git a/gamemode/shared/system_water.lua b/gamemode/shared/system_water.lua
new file mode 100644
index 0000000..f55dd53
--- /dev/null
+++ b/gamemode/shared/system_water.lua
@@ -0,0 +1,53 @@
+
+local meta = FindMetaTable("Player")
+
+if (SERVER) then
+ util.AddNetworkString("SetWater")
+
+ local Tick = CurTime()
+
+ function meta:SetWater(s)
+ if (s > 100) then self:TakeDamage(s-100) s = 100 end
+ s = math.Clamp(s,0,100)
+
+ self.Water = s
+
+ net.Start("SetWater")
+ net.WriteUInt(s,8)
+ net.Send(self)
+ end
+
+ function meta:AddWater(s)
+ self:SetWater(self:GetWater()+s)
+ end
+
+ hook.Add("Tick","Water",function()
+ if (Tick < CurTime()) then
+ for k,v in pairs(player.GetAllHumans()) do
+ v:AddWater(1)
+ end
+
+ Tick = CurTime()+3.5
+ end
+ end)
+
+ hook.Add("KeyPress","FindWater",function(pl,key)
+ if (key == IN_USE) then
+ local tr = util.TraceLine({start=pl:GetShootPos(),endpos=pl:GetShootPos()+pl:GetAimVector()*200,filter=pl})
+ local A = util.PointContents( tr.HitPos )
+
+ if (A == CONTENTS_WATER or A == CONTENTS_WATER+CONTENTS_TRANSLUCENT ) then
+ pl:AddWater(-20)
+ end
+ end
+ end)
+else
+ net.Receive("SetWater",function()
+ LocalPlayer().Water = net.ReadUInt(8)
+ end)
+end
+
+function meta:GetWater()
+ return self.Water or 0
+end
+ \ No newline at end of file
diff --git a/gamemode/shared/vars.lua b/gamemode/shared/vars.lua
new file mode 100644
index 0000000..e605816
--- /dev/null
+++ b/gamemode/shared/vars.lua
@@ -0,0 +1,3 @@
+MAIN_PVPTIMER = 300
+
+MAIN_MAX_SLOTS = 30 \ No newline at end of file
diff --git a/gamemode/shared/weaponswap.lua b/gamemode/shared/weaponswap.lua
new file mode 100644
index 0000000..f6e0a5c
--- /dev/null
+++ b/gamemode/shared/weaponswap.lua
@@ -0,0 +1,168 @@
+
+local meta = FindMetaTable("Player")
+
+if (CLIENT) then
+ local Num = 0
+ local STi = CurTime()
+
+ hook.Add("PlayerBindPress","SwapWeapons",function(pl,bind,pressed)
+ if (LocalPlayer():IsPigeon()) then
+ if (bind:find("invprev")) then return true
+ elseif (bind:find("invnext")) then return true end
+ end
+
+ if (pressed) then
+ local Wep = pl:GetActiveWeapon()
+
+ if (bind:find("invprev")) then
+ Num = Num+1
+ STi = CurTime()
+
+ if (Num > 9) then Num = 0 end
+
+ net.Start("Select") net.WriteUInt(Num,4) net.SendToServer()
+
+ surface.PlaySound("wintersurvival2/hud/itemequip.wav")
+
+ if (IsValid(Wep)) then
+ if (pl.Weapons and pl.Weapons[Num]) then Wep:SetWeaponHoldType(pl.Weapons[Num].Item.HoldType)
+ else Wep:SetWeaponHoldType("normal") end
+ end
+
+ return true
+ elseif (bind:find("invnext")) then
+ Num = Num-1
+ STi = CurTime()
+
+ if (Num < 0) then Num = 9 end
+
+ net.Start("Select") net.WriteUInt(Num,4) net.SendToServer()
+
+ surface.PlaySound("wintersurvival2/hud/itemequip.wav")
+
+ if (IsValid(Wep)) then
+ if (pl.Weapons and pl.Weapons[Num]) then Wep:SetWeaponHoldType(pl.Weapons[Num].Item.HoldType)
+ else Wep:SetWeaponHoldType("normal") end
+ end
+
+ return true
+ end
+ end
+ end)
+
+ function GetWeaponSlot()
+ return Num
+ end
+
+ function GetRecentSwapTime()
+ return STi
+ end
+
+ net.Receive("ReceiveSelect",function()
+ local pl = net.ReadEntity()
+ if (!IsValid(pl)) then return end
+
+ pl.Select = net.ReadUInt(4)
+ local wep = pl:GetActiveWeapon()
+
+ if (!IsValid(wep)) then return end
+
+ if (pl.Weapons and pl.Weapons[pl.Select]) then wep:SetWeaponHoldType(pl.Weapons[pl.Select].Item.HoldType)
+ else wep:SetWeaponHoldType("normal") end
+ end)
+
+ net.Receive("SetSlot",function()
+ local pl = net.ReadEntity()
+
+ if (!IsValid(pl)) then return end
+ if (!pl.Weapons) then pl.Weapons = {} end
+
+ local id = net.ReadUInt(5)
+ local na = net.ReadString()
+ local A = GetItemByName(na)
+
+ if (A) then pl.Weapons[id] = {Name = na,Item = A}
+ else pl.Weapons[id] = nil end
+
+ pl:EmitSound("wintersurvival2/hud/itemequip.wav")
+ end)
+
+ function RequestEquip(id,item)
+ net.Start("SetSlotReq")
+ net.WriteUInt(id,5)
+ net.WriteString(item)
+ net.SendToServer()
+ end
+
+ function RequestUnEquip(id)
+ net.Start("SetSlotReqUn")
+ net.WriteUInt(id,5)
+ net.SendToServer()
+ end
+
+ function EraseSlot(id)
+ net.Start("EraseSlot")
+ net.WriteUInt(id,5)
+ net.SendToServer()
+ end
+else
+ util.AddNetworkString("Select")
+ util.AddNetworkString("ReceiveSelect")
+ util.AddNetworkString("SetSlot")
+ util.AddNetworkString("SetSlotReq")
+ util.AddNetworkString("SetSlotReqUn")
+ util.AddNetworkString("EraseSlot")
+
+ net.Receive("Select",function(siz,pl) pl.Select = net.ReadUInt(4) pl:UpdateSelection() end)
+ net.Receive("SetSlotReq",function(siz,pl) pl:SetWeaponSlot(net.ReadUInt(5),net.ReadString()) end)
+ net.Receive("SetSlotReqUn",function(siz,pl) pl:UnEquipWeaponSlot(net.ReadUInt(5)) end)
+ net.Receive("EraseSlot",function(siz,pl) pl:UnEquipWeaponSlot(net.ReadUInt(5),true) end)
+
+ function meta:UpdateSelection(pl)
+ if (self.Select) then
+ net.Start("ReceiveSelect")
+ net.WriteEntity(self)
+ net.WriteUInt(self.Select,4)
+ if (IsValid(pl)) then net.Send(pl)
+ else net.Broadcast() end
+ end
+
+ if (self:CanPlaceStructure()) then self:GhostRemove() end
+ end
+
+ function meta:SetWeaponSlot(id,item)
+ if (!self:HasItem(item)) then return end
+ if (!self.Weapons) then self.Weapons = {} end
+
+ self:RemoveItem(item,1)
+
+ local A = GetItemByName(item)
+
+ if (self.Weapons[id]) then self:AddItem(self.Weapons[id].Name,1) end
+
+ self.Weapons[id] = {Name = item,Item = A}
+
+ net.Start("SetSlot")
+ net.WriteEntity(self)
+ net.WriteUInt(id,5)
+ net.WriteString(item)
+ net.Broadcast()
+ end
+
+ function meta:UnEquipWeaponSlot(id,bErase)
+ if (!self.Weapons or !self.Weapons[id]) then return end
+
+ if (!bErase) then self:AddItem(self.Weapons[id].Name,1) end
+
+ self.Weapons[id] = nil
+
+ net.Start("SetSlot")
+ net.WriteEntity(self)
+ net.WriteUInt(id,5)
+ net.Broadcast()
+ end
+end
+
+function meta:GetSelectedWeapon()
+ return self.Select or 0
+end \ No newline at end of file