summaryrefslogtreecommitdiff
path: root/ftp_gmstranded/gamemode
diff options
context:
space:
mode:
authorScott <scotth0828@gmail.com>2016-04-30 20:31:37 -0400
committerScott <scotth0828@gmail.com>2016-04-30 20:31:37 -0400
commite8fc8b5bf824ed3283dede946e66f5fd843d54ff (patch)
treecf935647c5c5ae0c44b30e8a1256df7799c41a5a /ftp_gmstranded/gamemode
parent6f6cce0561c19e7af14bcc6e6b1c7de2d5efc530 (diff)
downloadgmstranded-e8fc8b5bf824ed3283dede946e66f5fd843d54ff.tar.gz
gmstranded-e8fc8b5bf824ed3283dede946e66f5fd843d54ff.tar.bz2
gmstranded-e8fc8b5bf824ed3283dede946e66f5fd843d54ff.zip
Some changes
Diffstat (limited to 'ftp_gmstranded/gamemode')
-rw-r--r--ftp_gmstranded/gamemode/chatcommands.lua466
-rw-r--r--ftp_gmstranded/gamemode/cl_deathmenu.lua368
-rw-r--r--ftp_gmstranded/gamemode/cl_hud.lua412
-rw-r--r--ftp_gmstranded/gamemode/cl_init.lua605
-rw-r--r--ftp_gmstranded/gamemode/cl_panels.lua1158
-rw-r--r--ftp_gmstranded/gamemode/cl_qmenu.lua989
-rw-r--r--ftp_gmstranded/gamemode/cl_scoreboard.lua231
-rw-r--r--ftp_gmstranded/gamemode/combinations.lua3358
-rw-r--r--ftp_gmstranded/gamemode/combinations2.lua1196
-rw-r--r--ftp_gmstranded/gamemode/combirenbuy.lua21
-rw-r--r--ftp_gmstranded/gamemode/combirensell.lua1500
-rw-r--r--ftp_gmstranded/gamemode/init.lua3256
-rw-r--r--ftp_gmstranded/gamemode/processes.lua1269
-rw-r--r--ftp_gmstranded/gamemode/resources.lua68
-rw-r--r--ftp_gmstranded/gamemode/shared.lua1029
-rw-r--r--ftp_gmstranded/gamemode/spp/cl_init.lua101
-rw-r--r--ftp_gmstranded/gamemode/spp/sh_cppi.lua88
-rw-r--r--ftp_gmstranded/gamemode/spp/sh_spp.lua97
-rw-r--r--ftp_gmstranded/gamemode/spp/sv_init.lua369
-rw-r--r--ftp_gmstranded/gamemode/time_weather.lua185
-rw-r--r--ftp_gmstranded/gamemode/unlocks.lua153
21 files changed, 16919 insertions, 0 deletions
diff --git a/ftp_gmstranded/gamemode/chatcommands.lua b/ftp_gmstranded/gamemode/chatcommands.lua
new file mode 100644
index 0000000..54d4bba
--- /dev/null
+++ b/ftp_gmstranded/gamemode/chatcommands.lua
@@ -0,0 +1,466 @@
+
+function GM:PlayerSay( ply, text, teamonly )
+ local args = string.Explode( " ", text )
+ if ( args == nil ) then args = {} end
+
+ if ( teamonly ) then
+ if ( GMS.RunChatCmd( ply, args ) != "" ) then
+ for k, v in pairs( player.GetAll() ) do
+ if ( IsValid( v ) && v:IsPlayer() && v:Team() == ply:Team() ) then
+ v:PrintMessage( 3, "[TRIBE] " .. ply:Nick() .. ": " .. text )
+ end
+ end
+ end
+ return ""
+ else
+ return GMS.RunChatCmd( ply, args ) or text
+ end
+end
+
+GMS.ChatCommands = {}
+function GMS.RegisterChatCmd( tbl )
+ GMS.ChatCommands[ tbl.Command ] = tbl
+end
+
+function GMS.RunChatCmd( ply, arg )
+ if ( #arg > 0 && ( string.Left( arg[ 1 ], 1 ) == "/" or string.Left( arg[1], 1 ) == "!" ) ) then
+ local cmd = string.sub( arg[ 1 ], 2, string.len( arg[ 1 ] ) )
+ table.remove( arg, 1 )
+
+ if ( ply:GetNWBool( "AFK" ) && cmd != "afk" ) then
+ ply:SendMessage( "You can't do this while afk.", 3, Color( 200, 0, 0, 255 ) )
+ elseif ( ply:GetNWBool( "Sleeping" ) && cmd != "wakeup" ) then
+ ply:SendMessage( "You can't do this while sleeping.", 3, Color( 200, 0, 0, 255 ) )
+ end
+
+ if ( GMS.ChatCommands[ cmd ] != nil ) then
+ GMS.ChatCommands[cmd]:Run( ply, arg )
+ return ""
+ end
+ end
+end
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "commands"
+CHATCMD.Desc = "Prints all possible commands"
+
+function CHATCMD:Run( ply )
+ ply:PrintMessage( HUD_PRINTCONSOLE, "\n\n\nGarry's Mod Stranded chat commands:\n\n" )
+ for _, v in pairs( GMS.ChatCommands ) do
+ if ( v.Command != nil ) then
+ local desc = v.Desc or "No description given."
+ local syntax = v.Syntax or ""
+ if ( syntax != "" ) then syntax = syntax .. " " end
+ ply:PrintMessage( HUD_PRINTCONSOLE, v.Command .. " " .. syntax .. "- " .. v.Desc )
+ end
+ end
+ ply:PrintMessage( HUD_PRINTCONSOLE, "\n<arg> - Required argument, [arg] - Optional argument\n" )
+ ply:PrintMessage( HUD_PRINTCONSOLE, "All commands start with '!' or '/'." )
+ ply:PrintMessage( HUD_PRINTCONSOLE, "For item names with spaces use '_', for example !drop Water_Bottles 5\n\n" )
+ ply:PrintMessage( HUD_PRINTTALK, "All commands were printed into console (~)" )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "help"
+CHATCMD.Desc = "Open help menu"
+CHATCMD.CCName = "gms_help"
+
+function CHATCMD:Run( ply, args )
+ ply:ConCommand( self.CCName )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "drop"
+CHATCMD.Desc = "No amount will drop all"
+CHATCMD.Syntax = "<Resource Type> [Amount]"
+CHATCMD.CCName = "gms_dropresources"
+
+function CHATCMD:Run( ply, args )
+ GAMEMODE.DropResource( ply, self.CCName, args )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "sleep"
+CHATCMD.Desc = "Goto sleep"
+CHATCMD.CCName = "gms_sleep"
+
+function CHATCMD:Run( ply )
+ ply:Sleep()
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "stuck"
+CHATCMD.Desc = "In case you are stuck"
+CHATCMD.CCName = "gms_stuck"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlayerStuck( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "adrop"
+CHATCMD.Desc = "Drops a specified of resources out of nowhere. Admin only."
+CHATCMD.Syntax = "<Resource Type> <Amount>"
+CHATCMD.CCName = "gms_adropresources"
+
+function CHATCMD:Run( ply, args )
+ GAMEMODE.ADropResource( ply, self.CCName, args )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "wakeup"
+CHATCMD.Desc = "Wakeup from sleep."
+CHATCMD.CCName = "gms_wakeup"
+
+function CHATCMD:Run( ply )
+ ply:Wakeup()
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+CHATCMD.Command = "campfire"
+CHATCMD.Desc = "Make a camp fire."
+CHATCMD.CCName = "gms_makefire"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.MakeCampfire( ply )
+end
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "drink"
+CHATCMD.Desc = "Drink a water bottle."
+CHATCMD.CCName = "gms_drinkbottle"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.DrinkFromBottle( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "melon"
+CHATCMD.Desc = "Plant a watermelon."
+CHATCMD.CCName = "gms_plantmelon"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlantMelon( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "banana"
+CHATCMD.Desc = "Plant a banana."
+CHATCMD.CCName = "gms_plantbanana"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlantBanana( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "orange"
+CHATCMD.Desc = "Plant an orange."
+CHATCMD.CCName = "gms_plantorange"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlantOrange( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "grain"
+CHATCMD.Desc = "Plant grain."
+CHATCMD.CCName = "gms_plantgrain"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlantGrain( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "berrybush"
+CHATCMD.Desc = "Plant berry bush."
+CHATCMD.CCName = "gms_plantbush"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlantBush( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "tree"
+CHATCMD.Desc = "Plant a tree."
+CHATCMD.CCName = "gms_planttree"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.PlantTree( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "dropweapon"
+CHATCMD.Desc = "Drop your current weapon."
+CHATCMD.CCName = "gms_dropweapon"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.DropWeapon( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "take"
+CHATCMD.Desc = "Take resources out of Resource Pack/Box."
+CHATCMD.Syntax = "[Resource Type] [Amount]"
+CHATCMD.CCName = "gms_takeresources"
+function CHATCMD:Run( ply, args )
+ GAMEMODE.TakeResource( ply, self.CCName, args )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "medicine"
+CHATCMD.Desc = "Take a Medicine."
+CHATCMD.CCName = "gms_takemedicine"
+
+function CHATCMD:Run( ply )
+ GAMEMODE.TakeAMedicine( ply )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "afk"
+CHATCMD.Desc = "Go away from keyboard. ( Doesn't reduce your needs )"
+CHATCMD.CCName = "gms_afk"
+
+function CHATCMD:Run( ply, args )
+ GAMEMODE.AFK( ply, self.CCName, args )
+ ply:ConCommand("-menu")
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "rn"
+CHATCMD.Syntax = "[Player]"
+CHATCMD.Desc = "Reset your / someone's needs. Admin Only."
+
+function CHATCMD:Run( ply, args )
+ if ( !ply:IsAdmin() ) then return end
+ if ( args && #args > 0 ) then
+ pl = player.FindByName( args[ 1 ] )
+ if ( !pl ) then ply:SendMessage( "Player not found!", 3, Color( 200, 10, 10, 255 ) ) return end
+ pl.Hunger = 1000
+ pl.Thirst = 1000
+ pl.Sleepiness = 1000
+ pl:UpdateNeeds()
+ else
+ ply.Hunger = 1000
+ ply.Thirst = 1000
+ ply.Sleepiness = 1000
+ ply:UpdateNeeds()
+ end
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "finish"
+CHATCMD.Desc = "Finish the structure you are looking at."
+
+function CHATCMD:Run( ply, args )
+ if ( !ply:IsAdmin() || ply:GetEyeTrace().Entity:GetClass() != "gms_buildsite" ) then return end
+ ply:GetEyeTrace().Entity:Finish()
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "r"
+CHATCMD.Desc = "Give resources to yourself / someone"
+CHATCMD.Syntax = "[player] <Resource> <Amount>"
+
+function CHATCMD:Run(ply, arg)
+ if ( !ply:IsAdmin() || !arg ) then return end
+ if ( #arg > 2 ) then
+ local pl = player.FindByName( arg[ 1 ] )
+ if ( !pl ) then ply:SendMessage( "Player not found!", 3, Color( 200, 10, 10, 255 ) ) return end
+ pl:IncResource( arg[ 2 ], tonumber( arg[ 3 ] ) )
+ elseif ( #arg == 2 ) then
+ ply:IncResource( arg[ 1 ], tonumber( arg[ 2 ] ) )
+ end
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "steal"
+CHATCMD.Desc = "Steal a prop."
+CHATCMD.CCName = "gms_steal"
+
+function CHATCMD:Run( ply )
+ ply.ConCommand( ply, "gms_steal" )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "createtribe"
+CHATCMD.Desc = "Opens create tribe menu."
+CHATCMD.CCName = "gms_tribemenu"
+
+function CHATCMD:Run( ply, args )
+ ply:ConCommand( self.CCName )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "invite"
+CHATCMD.Desc = "Invite someone to your tribe"
+CHATCMD.Syntax = "<player>"
+
+function CHATCMD:Run( ply, args )
+ local him = player.FindByName( args[ 1 ] )
+ if ( !him ) then ply:SendMessage( "Player not found!", 3, Color( 200, 10, 10, 255 ) ) return end
+ if ( him == ply ) then ply:SendMessage( "Why invite yourself?", 3, Color( 200, 64, 10, 255 ) ) return end
+ if ( him.LastInvite && him.LastInvite > CurTime() ) then ply:SendMessage( "Too much invitations to " .. him:Name() .. "! Wait " .. ( CurTime() - him.LastInvite) .. " seconds.", 3, Color( 200, 10, 10, 255 ) ) return end
+ local mahTribe = GAMEMODE.FindTribeByID( ply:Team() )
+
+ him.LastInvite = CurTime() + 30
+
+ if ( !mahTribe ) then ply:SendMessage( "Something went wrong! Report this to admins: " .. ply:Team(), 3, Color( 200, 10, 10, 255 ) ) return end
+
+ ply:SendMessage( "Invitation sent!", 3, Color( 200, 200, 200, 255 ) )
+
+ umsg.Start( "gms_invite", him )
+ umsg.String( mahTribe.name )
+ umsg.String( tostring( mahTribe.password ) )
+ umsg.End()
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "join"
+CHATCMD.Desc = "Opens join tribe menu."
+CHATCMD.CCName = "gms_tribes"
+
+function CHATCMD:Run( ply, args )
+ ply:ConCommand( self.CCName )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
+
+----------------------------------------------------------------------------------------------------
+
+local CHATCMD = {}
+
+CHATCMD.Command = "leave"
+CHATCMD.Desc = "Leave a tribe."
+CHATCMD.CCName = "gms_leave"
+
+function CHATCMD:Run( ply, args )
+ GAMEMODE.LeaveTribeCmd( ply, self.CCName, args )
+end
+
+GMS.RegisterChatCmd( CHATCMD )
diff --git a/ftp_gmstranded/gamemode/cl_deathmenu.lua b/ftp_gmstranded/gamemode/cl_deathmenu.lua
new file mode 100644
index 0000000..472547a
--- /dev/null
+++ b/ftp_gmstranded/gamemode/cl_deathmenu.lua
@@ -0,0 +1,368 @@
+
+surface.CreateFont( "Header", {
+ font = "Arial", -- Use the font-name which is shown to you by your operating system Font Viewer, not the file name
+ size = 16,
+ weight = 500,
+ blursize = 0,
+ scanlines = 0,
+ antialias = true,
+ underline = false,
+ italic = false,
+ strikeout = false,
+ symbol = false,
+ rotary = false,
+ shadow = false,
+ additive = false,
+ outline = false,
+} )
+
+surface.CreateFont( "Items", {
+ font = "Arial", -- Use the font-name which is shown to you by your operating system Font Viewer, not the file name
+ size = 14,
+ weight = 0,
+ blursize = 0,
+ scanlines = 0,
+ antialias = true,
+ underline = false,
+ italic = false,
+ strikeout = false,
+ symbol = false,
+ rotary = false,
+ shadow = false,
+ additive = false,
+ outline = false,
+} )
+
+
+
+active = 0
+
+local res
+local wep
+local dmFrame
+
+local function receive_message(len)
+
+res = net.ReadTable()
+wep = net.ReadTable()
+
+if (active == 0) then dmFrame = vgui.Create("dmFrame") active = 1 end
+
+end
+net.Receive('deathmenu', receive_message)
+
+
+
+local PANEL = {}
+
+width = 100
+height = 100
+
+function PANEL:Init()
+
+ self:SetSize( 440, 400 )
+ self:Center()
+ self:MakePopup()
+ self:SetTitle("")
+
+ local pnl = vgui.Create( "DPanel", self )
+ pnl:SetSize(self:GetWide()-10, self:GetTall()-25)
+ pnl:SetPos(5,25)
+
+ local DScrollPanel = vgui.Create( "DScrollPanel", pnl )
+ DScrollPanel:SetSize( pnl:GetWide(), pnl:GetTall() )
+ DScrollPanel:SetPos( 0, 0 )
+
+ // Weapons
+
+ local wepPnlHeader = vgui.Create("DPanel", DScrollPanel)
+ wepPnlHeader:SetSize( DScrollPanel:GetWide(), 25 )
+ wepPnlHeader:SetPos(0,0)
+ wepPnlHeader.Paint = function()
+
+ draw.RoundedBox( 0, 0, 0, wepPnlHeader:GetWide(), wepPnlHeader:GetTall(), Color( 48, 48, 48, 255 ) )
+ draw.SimpleText( "Weapons", "Header", 30, 12, Color(255, 255, 255), 1, 1 )
+ end
+
+ column = 1
+ row = 1
+ XOffset = 12
+ for k,v in pairs(wep) do
+ local wepPNL = vgui.Create( "DButton", DScrollPanel )
+ wepPNL:SetSize( width, height )
+ if (k/4 <= column) then
+ wepPNL:SetPos( (row-1)*(width+2) + XOffset,(column-1)*(height+2) + 25)
+ row=row+1
+ else
+ column=column+1
+ row=1
+ wepPNL:SetPos( (row-1)*(width+2) + XOffset,(column-1)*(height+2) + 25)
+ row=row+1
+ end
+
+ wepPNL:SetDrawBackground( false )
+
+ wepPNL.Paint = function()
+
+ draw.RoundedBox( 0, 0, 0, wepPNL:GetWide(), wepPNL:GetTall(), Color(69,69,69,125) )
+
+ surface.SetFont("Items")
+ surface.SetTextColor( 0,0,0 )
+ surface.SetTextPos( (width/2)-(surface.GetTextSize(v)/2), height-20 )
+ surface.DrawText(v)
+ end
+
+ wepPNL.DoClick = function()
+ if (!LocalPlayer():HasWeapon(v)) then
+
+ net.Start('givePlayerWeapon')
+ net.WriteString(v)
+ for i,o in pairs(wep) do
+ if (v == o) then
+ net.WriteInt(i, 32)
+ table.remove(wep,i)
+ end
+ end
+ wepPNL:Remove()
+
+ net.SendToServer()
+ end
+ end
+
+ local img = vgui.Create("DImage", wepPNL)
+ img:SetPos(0, 0)
+ img:SetSize(wepPNL:GetSize())
+ img:SetImage("gms_icons/gms_weapon.png")
+
+
+ end
+
+ // Resources
+
+ local resPnlHeader = vgui.Create("DPanel", DScrollPanel)
+ resPnlHeader:SetSize( DScrollPanel:GetWide(), 25 )
+ resPnlHeader:SetPos(0,column*height + 25)
+ resPnlHeader.Paint = function()
+ draw.RoundedBox( 0, 0, 0, resPnlHeader:GetWide(), resPnlHeader:GetTall(), Color( 48, 48, 48, 255 ) )
+ draw.SimpleText( "Resources", "Header", 35, 12, Color(255, 255, 255), 1, 1 )
+ end
+
+ row2 = 1
+ column2 = 1
+ for k,v in pairs(res) do
+ local resPNL = vgui.Create( "DButton", DScrollPanel )
+ resPNL:SetSize( width, height )
+ if (k/4 <= column2) then
+ resPNL:SetPos( (row2-1)*(width+2) + XOffset,(column2-1)*(height+2) + (column*height + 50))
+ row2=row2+1
+ else
+ column2=column2+1
+ row2=1
+ resPNL:SetPos( (row2-1)*(width+2) + XOffset,(column2-1)*(height+2) + (column*height + 50))
+ row2=row2+1
+ end
+
+ local tbl1 = string.Split(res[k], " ")
+ local tbl2 = string.Split(tbl1[2], "x")
+ local amount = tbl2[2]
+
+ resPNL.DoClick = function()
+ local mb = DermaMenu()
+
+
+ mb:AddOption("Take x1", function()
+
+ if (amount - 1 <= 0) then
+ amount = 0
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], 1, i)
+ table.remove(res,i)
+ end
+ end
+ resPNL:Remove()
+ else
+ amount = amount - 1
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], 1, i)
+ res[i] = tbl1[1] .. " x" .. amount
+ v = res[i]
+ end
+ end
+
+ end
+
+ end)
+ mb:AddOption("Take x5", function()
+
+ if (amount - 5 <= 0) then
+
+ if (amount - 5 == 0) then
+ amount = 0
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], 5, i)
+ table.remove(res, i)
+ end
+ end
+ resPNL:Remove()
+ else
+
+ num1 = amount - 5
+ num2 = 5 + num1
+ amount = 0
+
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], num2, i)
+ print(i)
+ table.remove(res,i)
+ end
+ end
+ resPNL:Remove()
+ end
+ else
+ amount = amount - 5
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], 5, i)
+ res[i] = tbl1[1] .. " x" .. amount
+ v = res[i]
+ end
+ end
+
+ end
+
+ end)
+ mb:AddOption("Take x10", function()
+
+ if (amount - 10 <= 0) then
+
+ if (amount - 10 == 0) then
+ amount = 0
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], 10, i)
+ table.remove(res, i)
+ end
+ end
+ resPNL:Remove()
+ else
+
+ num1 = amount - 10
+ num2 = 10 + num1
+ amount = 0
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], num2, i)
+ table.remove(res,i)
+ end
+ end
+
+ resPNL:Remove()
+
+ end
+ else
+ amount = amount - 10
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], 10, i)
+ res[i] = tbl1[1] .. " x" .. amount
+ v = res[i]
+ end
+ end
+
+ end
+
+ end)
+ mb:AddOption("Take All", function()
+
+
+ for i,o in pairs(res) do
+ spl1 = string.Split(v, " ")
+ spl2 = string.Split(o, " ")
+ if (spl1[1] == spl2[1]) then
+ giveRes(tbl1[1], amount, i)
+ amount = 0
+ table.remove(res,i)
+ end
+ end
+
+ resPNL:Remove()
+ end)
+ mb:Open()
+ end
+
+ resPNL.Paint = function()
+ draw.RoundedBox( 0, 0, 0, resPNL:GetWide(), resPNL:GetTall(), Color( 69, 69, 69, 125 ) )
+
+
+ surface.SetFont("Items")
+ surface.SetTextColor( 0,0,0 )
+ surface.SetTextPos( (width/2)-(surface.GetTextSize(v)/2), height-20 )
+ surface.DrawText(v)
+
+ end
+
+ local img = vgui.Create("DImage", resPNL)
+ img:SetPos(0, 0)
+ img:SetSize(resPNL:GetSize())
+ img:SetImage("gms_icons/gms_resourcepack.png")
+ end
+
+end
+
+function PANEL:Close()
+ active = 0
+ self:Remove()
+end
+
+function giveRes(res, amount, slot)
+
+ net.Start('givePlayerResource')
+
+ net.WriteString(res)
+ net.WriteInt(amount, 32)
+ net.WriteInt(slot, 32)
+
+ net.SendToServer()
+
+end
+
+function PANEL:Paint( w, h )
+ draw.RoundedBox( 0, 0, 0, w, h, Color( 69, 69, 69, 125 ) )
+end
+
+vgui.Register( "dmFrame", PANEL, "DFrame" )
+
+
diff --git a/ftp_gmstranded/gamemode/cl_hud.lua b/ftp_gmstranded/gamemode/cl_hud.lua
new file mode 100644
index 0000000..b217c2c
--- /dev/null
+++ b/ftp_gmstranded/gamemode/cl_hud.lua
@@ -0,0 +1,412 @@
+surface.CreateFont( "DefaultSmall", {
+ font = "Tahoma",
+ size = ScreenScale( 7 ),
+ weight = 500
+} )
+
+surface.CreateFont( "DefaultHealth", {
+ font = "Tahoma",
+ size = ScreenScale( 30 ),
+ weight = 900
+} )
+
+function GM:DrawStrandedHUD()
+
+ local w = ScrW() / 6
+ local h = 4 * 12 + 10
+
+ if ( self.SkillsHud ) then self.SkillsHud:SetPos( 0, h ) end
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( 0, 0, w, h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawLine( w - 1, 0, w - 1, h ) -- Nice line instead of messy outlined rect
+ surface.DrawLine( 0, h - 1, w, h - 1 )
+
+ local width = w - 10
+
+ //Health
+ local hp_w = math.floor( ( LocalPlayer():Health() / 200 ) * width )
+ surface.SetDrawColor( 0, 0, 0, 255 )
+ surface.DrawRect( 5, 5, width, 10 )
+
+ surface.SetDrawColor( 176, 0, 0, 255 )
+ surface.DrawRect( 5, 5, math.min( hp_w, width ), 10 )
+
+ draw.SimpleTextOutlined( "Health", "DefaultSmall", w / 2, 9, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+ //Hunger
+ local hunger_w = math.floor( ( Hunger / 1000 ) * width )
+ surface.SetDrawColor( 0, 0, 0, 255 )
+ surface.DrawRect( 5, 17, width, 10 )
+
+ surface.SetDrawColor( 0, 176, 0, 255 )
+ surface.DrawRect( 5, 17, hunger_w, 10 )
+
+ draw.SimpleTextOutlined( "Hunger","DefaultSmall", w / 2, 21, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+ //Thirst
+ local thrst_w = math.floor( ( Thirst / 1000 ) * width )
+ surface.SetDrawColor( 0, 0, 0, 255 )
+ surface.DrawRect( 5, 29, width, 10 )
+
+ surface.SetDrawColor( 0, 0, 176, 255 )
+ surface.DrawRect( 5, 29, thrst_w, 10 )
+
+ draw.SimpleTextOutlined( "Thirst", "DefaultSmall", w / 2, 33, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+ //Fatigue
+ local sleep_w = math.floor( math.min( Sleepiness / 1000, 1000 ) * width )
+ surface.SetDrawColor( 0, 0, 0, 255 )
+ surface.DrawRect( 5, 41, width, 10 )
+
+ surface.SetDrawColor( 176, 0, 176, 255 )
+ surface.DrawRect( 5, 41, sleep_w, 10 )
+
+ draw.SimpleTextOutlined( "Fatigue", "DefaultSmall", w / 2, 45, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+end
+
+function GM:DrawStrandedHUD()
+ local w = ScrW() / 12
+ local h = ScrW() / 22
+ local x = 5
+ local y = ScrH() - h - 5
+
+ local w_bar = ScrW() / 8
+ local h_bar = ScrW() / 80
+ local x_bar = x + w + 5
+ local bar_spacing = ScrW() / 300
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x, y, w, h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x, y, w, h )
+
+ local hpColor = StrandedTextColor
+ if ( LocalPlayer():Health() < 25 ) then hpColor = StrandedHealthColor end
+ draw.SimpleTextOutlined( tostring( LocalPlayer():Health() ), "DefaultHealth", x + w / 2, y + h / 2, hpColor, 1, 1, 0.5, StrandedBorderColor )
+
+ local bar_y = y + h / 2 - h_bar / 2 - h_bar - bar_spacing
+ local hunger_w = math.floor( ( Hunger / 1000 ) * w_bar )
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x_bar, bar_y, w_bar, h_bar )
+
+ surface.SetDrawColor( StrandedHungerColor )
+ surface.DrawRect( x_bar, bar_y, hunger_w, h_bar )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x_bar, bar_y, w_bar, h_bar )
+
+ draw.SimpleTextOutlined( "Hunger","DefaultSmall", x_bar + w_bar / 2, bar_y + h_bar / 2, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+ local bar_y = y + h / 2 - h_bar / 2
+ local thrst_w = math.floor( ( Thirst / 1000 ) * w_bar )
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x_bar, bar_y, w_bar, h_bar )
+
+ surface.SetDrawColor( StrandedThirstColor )
+ surface.DrawRect( x_bar, bar_y, thrst_w, h_bar )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x_bar, bar_y, w_bar, h_bar )
+
+ draw.SimpleTextOutlined( "Thirst", "DefaultSmall", x_bar + w_bar / 2, bar_y + h_bar / 2, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+ local bar_y = y + h / 2 - h_bar / 2 + h_bar + bar_spacing
+ local sleep_w = math.floor( math.min( Sleepiness / 1000, 1000 ) * w_bar )
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x_bar, bar_y, w_bar, h_bar )
+
+ surface.SetDrawColor( StrandedFatigueColor )
+ surface.DrawRect( x_bar, bar_y, sleep_w, h_bar )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x_bar, bar_y, w_bar, h_bar )
+
+ draw.SimpleTextOutlined( "Fatigue", "DefaultSmall", x_bar + w_bar / 2, bar_y + h_bar / 2, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+end
+
+function GM:DrawWristWatch()
+
+ if ( GetConVarNumber( "gms_daynight" ) <= 0 || !Resources[ "Wrist_Watch" ] || Resources[ "Wrist_Watch" ] < 1 ) then return end
+
+ local w = ScrW() / 12
+ local h = ScrH() / 25
+ local x = 5//ScrW() - ScrH() / 16 - w
+ local y = ScrH() - ScrW() / 22 - 10 - h //ScrH() / 16
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x, y, w, h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x, y, w, h )
+
+ local hours = os.date( "%M", Time )
+ local mins = os.date( "%S", Time )
+ draw.SimpleTextOutlined( hours .. ":" .. mins, "ScoreboardSub", x + w / 2, y + h / 2, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+end
+
+function GM:DrawOxygenBar()
+
+ if ( Oxygen >= 1000 ) then return end
+
+ local w = ScrW() / 5
+ local h = ScrH() / 48
+ local x = ScrW() / 2 - w / 2
+ local y = ScrH() / 6
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x, y, w, h )
+
+ surface.SetDrawColor( StrandedOxygenColor )
+ surface.DrawRect( x, y, math.min( math.floor( math.min( Oxygen / 1000, 1000 ) * w ), w ), h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x, y, w, h )
+
+ draw.SimpleTextOutlined( "Oxygen", "DefaultSmall", x + w / 2, y + h / 2, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+end
+
+function GM:DrawPowerBar()
+
+ if ( !Resources[ "Flashlight" ] or Resources[ "Flashlight" ] < 1 ) then return end
+
+ local maxPower = 50
+ if ( Resources[ "Batteries" ] ) then maxPower = math.min( maxPower + Resources[ "Batteries" ] * 50, 500 ) end
+
+ if ( Power >= maxPower ) then return end
+
+ local w = ScrW() / 6
+ local h = ScrH() / 48
+ local x = ScrW() / 2 - w / 2
+ local y = ScrH() - ScrH() / 16 - h * 2
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x, y, w, h )
+
+ surface.SetDrawColor( StrandedPowerColor )
+ surface.DrawRect( x, y, math.min( math.floor( math.min( Power / maxPower, maxPower ) * w ), w ), h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x, y, w, h )
+
+ draw.SimpleTextOutlined( "Flashlight Power", "DefaultSmall", x + w / 2, y + h / 2.5, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+
+end
+
+function GM:DrawProcessBar()
+ if ( !ProcessCompleteTime ) then return end
+
+ local w = ScrW() / 3.2
+ local h = ScrH() / 30
+ local x = ScrW() / 2 - w / 2
+ local y = ScrH() / 8
+
+ local width = math.min( ( CurTime() - ProcessStart ) / ProcessCompleteTime * w, w )
+ if ( width > w ) then GAMEMODE.StopProgressBar() end
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x, y, w, h )
+
+ surface.SetDrawColor( StrandedForegroundColor )
+ surface.DrawRect( x, y, width, h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x, y, w, h )
+
+ local txt = CurrentProcess
+ if ( ProcessCancelAble ) then txt = txt .. " ( F4 to Cancel )" end
+
+ draw.SimpleText( txt, "ScoreboardText", x + w / 2, y + h / 2, StrandedTextColor, 1, 1 )
+
+end
+
+function GM:HUDDrawTargetID()
+ local tr = util.GetPlayerTrace( LocalPlayer() )
+ local trace = util.TraceLine( tr )
+ if (!trace.Hit) then return end
+ if (!trace.HitNonWorld) then return end
+
+ local text = "ERROR"
+ local font = "TargetID"
+
+ if (trace.Entity:IsPlayer()) then
+ text = trace.Entity:Nick()
+ else
+ return
+ end
+
+ surface.SetFont( font )
+ local w, h = surface.GetTextSize( text )
+
+ local MouseX, MouseY = gui.MousePos()
+
+ if ( MouseX == 0 && MouseY == 0 ) then
+ MouseX = ScrW() / 2
+ MouseY = ScrH() / 2
+ end
+
+ local x = MouseX
+ local y = MouseY
+
+ x = x - w / 2
+ y = y + 30
+
+ -- The fonts internal drop shadow looks lousy with AA on
+ draw.SimpleText( text, font, x+1, y+1, Color(0,0,0,120) )
+ draw.SimpleText( text, font, x+2, y+2, Color(0,0,0,50) )
+ draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
+
+ y = y + h
+
+ local text = trace.Entity:Team()
+ local font = "TargetIDSmall"
+
+ for id, tabl in pairs( Tribes ) do
+ if ( id == text ) then text = tabl.name end
+ end
+
+ surface.SetFont( font )
+ local w, h = surface.GetTextSize( text )
+ local x = MouseX - w / 2
+
+ draw.SimpleText( text, font, x+1, y+1, Color(0,0,0,120) )
+ draw.SimpleText( text, font, x+2, y+2, Color(0,0,0,50) )
+ draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
+
+ y = y + h + 5
+
+ local text = trace.Entity:Health() .. "%"
+ local font = "TargetIDSmall"
+
+ surface.SetFont( font )
+ local w, h = surface.GetTextSize( text )
+ local x = MouseX - w / 2
+
+ draw.SimpleText( text, font, x+1, y+1, Color(0,0,0,120) )
+ draw.SimpleText( text, font, x+2, y+2, Color(0,0,0,50) )
+ draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
+end
+
+function GM:DrawResourceDropsHUD()
+ local ply = LocalPlayer()
+ local str = nil
+ local draw_loc = nil
+ local w, h = nil, nil
+ local tr = nil
+ local cent = nil
+ local pos = ply:GetShootPos()
+
+ for _, v in ipairs( ents.GetAll() ) do
+ if ( !IsValid( v ) ) then continue end
+ local class = v:GetClass()
+
+ if ( class == "gms_resourcedrop" ) then
+ cent = v:LocalToWorld( v:OBBCenter() )
+
+ tr = {
+ start = pos,
+ endpos = cent,
+ filter = ply
+ }
+
+ if ( ( cent - pos ):Length() <= 200 && util.TraceLine( tr ).Entity == v ) then
+ str = ( v.Res or "Loading" ) .. ": " .. tostring( v.Amount or 0 )
+ draw_loc = cent:ToScreen()
+ surface.SetFont( "ChatFont" )
+ w, h = surface.GetTextSize( str )
+ draw.RoundedBox( 4, draw_loc.x - ( w / 2 ) - 3, draw_loc.y - ( h / 2 ) - 3, w + 6, h + 6, Color( 50, 50, 50, 200 ) )
+ surface.SetTextColor( 255, 255, 255, 200 )
+ surface.SetTextPos( draw_loc.x - ( w / 2 ), draw_loc.y -( h / 2 ) )
+ surface.DrawText( str )
+ end
+ continue
+ end
+
+ if ( class == "gms_resourcepack" or class == "gms_fridge" ) then
+ cent = v:LocalToWorld( v:OBBCenter() )
+
+ tr = {
+ start = pos,
+ endpos = cent,
+ filter = ply
+ }
+
+ if ( ( cent - pos ):Length() <= 200 and util.TraceLine( tr ).Entity == v ) then
+ draw_loc = cent:ToScreen()
+ surface.SetFont( "ChatFont" )
+ str = "Resource pack"
+ if ( class == "gms_fridge" ) then str = "Fridge" end
+ for res, num in pairs( v.Resources or {} ) do
+ str = str .. "\n" .. res .. ": " .. num
+ end
+ w, h = surface.GetTextSize( str )
+ draw.RoundedBox( 4, draw_loc.x - ( w / 2 ) - 3, draw_loc.y - ( h / 2 ) - 3, w + 6, h + 6, Color( 50, 50, 50, 200 ) )
+ surface.SetTextColor( 255, 255, 255, 200 )
+ for id, st in pairs( string.Explode( "\n", str ) ) do
+ id = id - 1
+ w2, h2 = surface.GetTextSize( st )
+ surface.SetTextPos( draw_loc.x - ( w / 2 ), draw_loc.y - ( h / 2 ) + ( id * h2 ) )
+ surface.DrawText( st )
+ end
+ end
+ continue
+ end
+
+ if ( table.HasValue( GMS.StructureEntities, class ) ) then
+ cent = v:LocalToWorld( v:OBBCenter() )
+ local minimum = v:LocalToWorld( v:OBBMins() )
+ local maximum = v:LocalToWorld( v:OBBMaxs() )
+ local distance = ( maximum - minimum ):Length()
+ if ( distance < 200 ) then distance = 200 end
+
+
+
+ tr2 = {}
+ tr2.start = pos
+ tr2.endpos = Vector( cent.x, cent.y, pos.z )
+ tr2.filter = ply
+
+ if ( ( cent - pos ):Length() <= distance and ( util.TraceLine( tr2 ).Entity == v or !util.TraceLine( tr2 ).Hit ) ) then
+ str = language.GetPhrase( class ) -- ( v:GetNWString( "Name" ) or "Loading" )
+ if ( class == "gms_buildsite" ) then
+ str = v:GetNWString( "Name" ) .. v:GetNWString( "Resources" )
+ end
+
+ draw_loc = cent:ToScreen()
+ surface.SetFont( "ChatFont" )
+ w, h = surface.GetTextSize( str )
+ draw.RoundedBox( 4, draw_loc.x - ( w / 2 ) - 3, draw_loc.y - ( h / 2 ) - 3, w + 6, h + 6, Color( 50, 50, 50, 200 ) )
+ surface.SetTextColor( Color( 255, 255, 255, 200 ) )
+
+ local strs = string.Explode( "\n", str )
+ for id, str in pairs( strs ) do
+ surface.SetTextPos( draw_loc.x - ( w / 2 ), draw_loc.y - ( h / 2 ) + ( id - 1 ) * 15 )
+ surface.DrawText( str )
+ end
+ end
+ end
+ end
+end
+
+
+function GM:HUDPaint()
+ self.BaseClass:HUDPaint()
+ self:DrawResourceDropsHUD()
+
+ self:DrawStrandedHUD()
+ self:DrawWristWatch()
+ self:DrawProcessBar()
+ self:DrawOxygenBar()
+ self:DrawPowerBar()
+end
+
+function GM:HUDShouldDraw( name )
+ if ( name != "CHudHealth" && name != "CHudBattery" ) then
+ return true
+ end
+end \ No newline at end of file
diff --git a/ftp_gmstranded/gamemode/cl_init.lua b/ftp_gmstranded/gamemode/cl_init.lua
new file mode 100644
index 0000000..bbf57a5
--- /dev/null
+++ b/ftp_gmstranded/gamemode/cl_init.lua
@@ -0,0 +1,605 @@
+
+include( "shared.lua" )
+
+include( "cl_qmenu.lua" )
+include( "cl_scoreboard.lua" )
+include( "cl_panels.lua" )
+include( "cl_hud.lua" )
+include( "cl_deathmenu.lua" )
+
+-- HUD Theme
+StrandedColorTheme = Color( 0, 0, 0, 240 )
+StrandedBorderTheme = Color( 0, 0, 0, 180 )
+
+StrandedBackgroundColor = Color( 0, 0, 0, 180 )
+StrandedForegroundColor = Color( 0, 128, 176, 220 )
+StrandedBorderColor = Color( 0, 0, 0, 150 )
+StrandedTextColor = color_white
+StrandedTextShadowColor = Color( 100, 100, 100, 140 )
+
+StrandedHealthColor = Color( 176, 0, 0, 240 )
+StrandedHungerColor = Color( 0, 176, 0, 240 )
+StrandedThirstColor = Color( 0, 0, 176, 240 )
+StrandedFatigueColor = Color( 176, 0, 176, 240 )
+StrandedOxygenColor = Color( 0, 200, 200, 220 )
+StrandedPowerColor = Color( 200, 200, 0, 220 )
+
+-- Clientside player variables
+Tribes = Tribes or {}
+Skills = Skills or {}
+Resources = Resources or {}
+Experience = Experience or {}
+FeatureUnlocks = FeatureUnlocks or {}
+MaxResources = MaxResources or 25
+CampFires = CampFires or {}
+
+Sleepiness = Sleepiness or 1000
+Hunger = Hunger or 1000
+Thirst = Thirst or 1000
+Oxygen = Oxygen or 1000
+Power = Power or 50
+
+/* Language */
+language.Add( "gms_stonefurnace", "Stone Furnace" )
+language.Add( "gms_stoneworkbench", "Stone Workbench" )
+language.Add( "gms_copperfurnace", "Copper Furnace" )
+language.Add( "gms_copperworkbench", "Copper Workbench" )
+language.Add( "gms_ironfurnace", "Iron Furnace" )
+language.Add( "gms_ironworkbench", "Iron Workbench" )
+language.Add( "gms_techfurnace", "Tech Furnace" )
+language.Add( "gms_techworkbench", "Tech Workbench" )
+language.Add( "gms_silverfurnace", "Silver Furnace" )
+language.Add( "gms_silverworkbench", "Silver Workbench" )
+language.Add( "gms_goldfurnace", "Gold Furnace" )
+language.Add( "gms_goldworkbench", "Gold Workbench" )
+language.Add( "gms_steelfurnace", "Steel Furnace" )
+language.Add( "gms_steelworkbench", "Steel Workbench" )
+language.Add( "gms_platinumfurnace", "Platinum Furnace" )
+language.Add( "gms_platinumworkbench", "Platinum Workbench" )
+language.Add( "gms_factory", "Factory" )
+language.Add( "gms_fridge", "Fridge" )
+language.Add( "gms_pistolgunlab", "Pistol Gun Lab" )
+language.Add( "gms_smggunlab", "SMG Gun Lab" )
+language.Add( "gms_hightechgunlab", "High Tech Gun Lab" )
+language.Add( "gms_transmutator", "Transmutator" )
+language.Add( "gms_advancedtransmutator", "Advanced Transmutator" )
+language.Add( "gms_gunchunks", "Gun Chunks" )
+language.Add( "gms_resourcepack", "Resource Pack" )
+language.Add( "gms_grindingstone", "Grinding Stone" )
+language.Add( "gms_waterfountain", "Water Fountain" )
+language.Add( "gms_stove", "Stove" )
+language.Add( "gms_renbuyshop", "Ren Buy Shop" )
+language.Add( "gms_rensellshop", "Ren Sell Shop" )
+language.Add( "gms_obelisk", "Obelisk")
+language.Add( "gms_mithrilfactory", "Mithril Factory")
+language.Add( "gms_mithrilworkbench", "Mithril WorkBench" )
+language.Add( "gms_runealtar", "Rune Altar" )
+language.Add( "gms_runicinfuser", "Runic Infuser")
+
+/* The chat hints */
+HintsRus = {
+ "Держите Ваши реÑурÑÑ‹ в реÑÑƒÑ€Ñ Ð¿Ð°ÐºÐµ, чтобы их не украли ночью.",
+ "Рзнаете ли Ð’Ñ‹, что реÑурÑÑ‹ в меню реÑурÑов ( F2 ) нажимаемы мышью?",
+ "Храните Вашу еду в холодильнике, чтобы она не портилаÑÑŒ.",
+ "Чтобы Ð¿Ð»ÐµÐ¼Ñ Ð¼Ð¾Ð³Ð»Ð¾ иÑпользовать вещи друг друга, Ñто Ð¿Ð»ÐµÐ¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ иметь пароль.",
+ "Чтобы иÑпользовать фонарь, Вам нужно его Ñделать.",
+ "Чем больше у Ð’Ð°Ñ Ð±Ð°Ñ‚Ð°Ñ€ÐµÐµÐº, тем больше у Ð’Ð°Ñ Ñнергии Ð´Ð»Ñ Ñ„Ð¾Ð½Ð°Ñ€Ñ.",
+ "Ð¨Ð°Ð½Ñ Ð¿Ð¾Ð¹Ð¼Ð°Ñ‚ÑŒ что-то без наживки ( Baits ) в 4 раза ниже, чем Ñ Ð½Ð°Ð¶Ð¸Ð²ÐºÐ¾Ð¹.",
+ "Чтобы добыть железо ( Iron ) или медь ( Copper ) вам нужна кирка.",
+ "Проблемы? Прочтите !help Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ð¹ информации об Ñтом игровом режиме.",
+ "Чтобы приглаÑить игрока в племÑ, напишите !invite <Ð¸Ð¼Ñ Ð¸Ð³Ñ€Ð¾ÐºÐ°>"
+}
+
+HintsEng = {
+ "Store your resources in resource pack, so they wont get stolen at night.",
+ "Did you know that resources in Resources menu ( F2 ) are clickable?",
+ "Keep your food in fridge, so it does not spoil.",
+ "In order to share items within a tribe, the tribe must have a password.",
+ "In order to use flashlight, you need to craft it.",
+ "The more batteries you have, the more flashlight power you have.",
+ "Chance to catch something without Baits is 4 times lower, then with Baits.",
+ "In order to get Iron or Copper you need a pickaxe.",
+ "Having trouble? Read !help to learn the basics of this gamemode.",
+ "In order to invite a player into a tribe, type !invite <player name>"
+}
+
+timer.Create( "Client.HINTS", 360, 0, function()
+ if ( GetConVarString( "gmod_language" ) == "ru" ) then
+ chat.AddText( Color( 50, 255, 50 ), "[HINT] ", Color( 255, 255, 255 ), HintsRus[ math.random( 1, #HintsRus ) ] )
+ else
+ chat.AddText( Color( 50, 255, 50 ), "[HINT] ", Color( 255, 255, 255 ), HintsEng[ math.random( 1, #HintsEng ) ] )
+ end
+end )
+
+function GM.FindTribeByID( Tid )
+ for id, tabl in pairs( Tribes ) do
+ if ( tabl.id == Tid ) then return tabl end
+ end
+ return false
+end
+
+concommand.Add( "gms_resetcharacter_verify", function( ply, cmd, args )
+ Derma_StringRequest( "Character Reset", "WARNING! This will reset all your skills and resources back to where you started.\nIf you are sure you want to do this, type 'I agree' into box below:", "", function( text )
+ RunConsoleCommand( "gms_resetcharacter", text )
+ end )
+end )
+
+/* Resource pack GUI */
+
+GM.ResourcePackFrame = nil
+
+concommand.Add( "gms_openrespackmenu", function( ply, cmd, args )
+ local resPack = ply:GetEyeTrace().Entity
+
+ if ( !IsValid( resPack ) ) then return end
+
+ local frame = vgui.Create( "DFrame" )
+ frame:SetSize( ScrW() / 1.5, ScrH() / 2 )
+ frame:MakePopup()
+ frame:Center()
+ function frame:Update()
+ // Left side
+ for id, item in pairs( self.Resources:GetItems() ) do item:Remove() end
+ for res, num in SortedPairs( self.ResourcePack.Resources or {} ) do
+ local reso = vgui.Create( "gms_resourceLine" )
+ if ( self.ResourcePack:GetClass() == "gms_fridge" ) then
+ reso:SetRes( res, num, false )
+ else
+ reso:SetRes( res, num, true )
+ end
+ self.Resources:AddItem( reso )
+ end
+
+ // Right side
+ if ( self.ResourcePack:GetClass() == "gms_fridge" || !IsValid( self.Inventory ) ) then return end
+ timer.Simple( 0, function()
+ if ( !IsValid( self.Inventory ) ) then return end
+ for id, item in pairs( self.Inventory:GetItems() ) do item:Remove() end
+ for res, num in SortedPairs( Resources or {} ) do
+ if ( num <= 0 ) then continue end
+ local reso = vgui.Create( "gms_resourceLineStore" )
+ reso:SetRes( res, num )
+ self.Inventory:AddItem( reso )
+ end
+ end )
+ end
+
+ local panelList = vgui.Create( "DPanelList", frame )
+ panelList:SetPos( 5, 30 )
+ panelList:SetSpacing( 5 )
+ panelList:SetPadding( 5 )
+ panelList:EnableHorizontal( false )
+ panelList:EnableVerticalScrollbar( true )
+ function panelList:Paint( w, h )
+ draw.RoundedBox( 2, 0, 0, w, h, Color( 80, 80, 80 ) )
+ end
+
+ if ( resPack:GetClass() == "gms_fridge" ) then
+ frame:SetSize( ScrW() / 2, ScrH() / 2 )
+ frame:SetTitle( "Fridge" )
+ frame:Center()
+ panelList:SetSize( frame:GetWide() - 10, frame:GetTall() - 35 )
+ else
+ frame:SetTitle( "Resource pack" )
+ panelList:SetSize( frame:GetWide() - 15 - ScrW() / 4, frame:GetTall() - 35 )
+ end
+
+ frame.Resources = panelList
+ frame.ResourcePack = resPack
+
+ if ( resPack:GetClass() != "gms_fridge" ) then
+ local panelListInv = vgui.Create( "DPanelList", frame )
+ panelListInv:SetPos( frame:GetWide() - 10 - ScrW() / 4 + 5, 30 )
+ panelListInv:SetSize( ScrW() / 4, frame:GetTall() - 35 )
+ panelListInv:SetSpacing( 5 )
+ panelListInv:SetPadding( 5 )
+ panelListInv:EnableHorizontal( false )
+ panelListInv:EnableVerticalScrollbar( true )
+ function panelListInv:Paint( w, h )
+ draw.RoundedBox( 2, 0, 0, w, h, Color( 80, 128, 80 ) )
+ end
+ frame.Inventory = panelListInv
+ end
+
+ GAMEMODE.ResourcePackFrame = frame
+ frame:Update()
+end )
+
+hook.Add( "Think", "CampFireLight", function()
+ for id, e in pairs( ents.FindByClass("prop_p*") ) do
+ if ( !e:IsOnFire() ) then continue end
+ local campfire = DynamicLight( e:EntIndex() )
+ if ( campfire ) then
+ campfire.Pos = e:GetPos()
+ campfire.r = math.random( 224, 255 )
+ campfire.g = math.random( 128, 150 )
+ campfire.b = 0
+ campfire.Brightness = 2.4
+
+ if ( !e.campfireSize ) then
+ local min, max = e:OBBMins(), e:OBBMaxs()
+ local vol = math.abs( max.x - min.x ) * math.abs( max.y - min.y ) * math.abs( max.z - min.z )
+ e.campfireSize = vol / 5
+ end
+
+ campfire.Size = e.campfireSize
+ campfire.Decay = 0
+ campfire.DieTime = CurTime() + 0.25
+ end
+ end
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Hooks
+---------------------------------------------------------------------------------------------------- */
+
+function GM:Initialize()
+ if ( !IsValid( self.SkillsHud ) ) then self.SkillsHud = vgui.Create( "gms_SkillsHud" ) end
+ if ( !IsValid( self.ResourcesHud ) ) then self.ResourcesHud = vgui.Create( "gms_ResourcesHud" ) end
+ if ( !IsValid( self.CommandsHud ) ) then self.CommandsHud = vgui.Create( "gms_CommandsHud" ) end
+ if ( !IsValid( self.LoadingBar ) ) then self.LoadingBar = vgui.Create( "gms_LoadingBar" ) self.LoadingBar:SetVisible( false ) end
+ if ( !IsValid( self.SavingBar ) ) then self.SavingBar = vgui.Create( "gms_SavingBar" ) self.SavingBar:SetVisible( false ) end
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Skills, Resources & Experience
+---------------------------------------------------------------------------------------------------- */
+
+usermessage.Hook( "gms_MakeProcessBar", function( um )
+ CurrentProcess = um:ReadString()
+ ProcessStart = CurTime()
+ ProcessCompleteTime = um:ReadShort()
+ ProcessCancelAble = um:ReadBool()
+end )
+
+usermessage.Hook( "gms_ResetPlayer", function()
+ Tribes = {}
+ Skills = {}
+ Skills[ "Survival" ] = 0
+ Resources = {}
+ Experience = {}
+ Experience[ "Survival" ] = 0
+ FeatureUnlocks = {}
+ MaxResources = 25
+
+ GAMEMODE.ResourcesHud:RefreshResources()
+ GAMEMODE.SkillsHud:RefreshSkills()
+end )
+
+usermessage.Hook( "gms_StopProcessBar", function()
+ ProcessCompleteTime = false
+end )
+
+usermessage.Hook( "gms_MakeLoadingBar", function( um )
+ GAMEMODE.LoadingBar:Show( um:ReadString() )
+end )
+
+usermessage.Hook( "gms_StopLoadingBar", function( um )
+ GAMEMODE.LoadingBar:Hide()
+end )
+
+usermessage.Hook( "gms_MakeSavingBar", function( um )
+ GAMEMODE.SavingBar:Show( um:ReadString() )
+end )
+
+usermessage.Hook( "gms_StopSavingBar", function( um )
+ GAMEMODE.SavingBar:Hide()
+end )
+
+usermessage.Hook( "gms_SetSkill", function( um )
+ Skills[ um:ReadString() ] = um:ReadShort()
+ MaxResources = 25 + ( GetSkill( "Survival" ) * 5 )
+ GAMEMODE.SkillsHud:RefreshSkills()
+end )
+
+usermessage.Hook( "gms_SetXP", function( um )
+ Experience[ um:ReadString() ] = um:ReadShort()
+end )
+
+usermessage.Hook( "gms_SetResource", function( um )
+ local res = um:ReadString()
+ local amount = um:ReadShort()
+
+ Resources[res] = amount
+ GAMEMODE.ResourcesHud:RefreshResources()
+end )
+
+usermessage.Hook( "gms_SetMaxResources", function( um )
+ MaxResources = um:ReadShort()
+ GAMEMODE.ResourcesHud:RefreshResources()
+end )
+
+usermessage.Hook( "gms_OpenCombiMenu", function( um )
+ if ( GAMEMODE.CombiMenu ) then GAMEMODE.CombiMenu:Remove() end
+ GAMEMODE.CombiMenu = vgui.Create( "GMS_CombinationWindow" )
+ GAMEMODE.CombiMenu:SetTable( um:ReadString() )
+end )
+
+function GM:PlayerBindPress( ply, bind, pressed )
+ if ( string.find( bind, "gm_showhelp" ) ) then GAMEMODE.SkillsHud:ToggleExtend() end
+ if ( string.find( bind, "gm_showteam" ) ) then GAMEMODE.ResourcesHud:ToggleExtend() end
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Functions
+---------------------------------------------------------------------------------------------------- */
+
+function GetSkill( skill )
+ return Skills[ skill ] or 0
+end
+
+function GetXP( skill )
+ return Experience[ skill ] or 0
+end
+
+function GetResource( res )
+ return Resources[ res ] or 0
+end
+
+function TraceFromEyes( dist )
+ local trace = {}
+ trace.start = self:GetShootPos()
+ trace.endpos = trace.start + ( self:GetAimVector() * dist )
+ trace.filter = self
+
+ return util.TraceLine( trace )
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Messages
+---------------------------------------------------------------------------------------------------- */
+
+GM.InfoMessages = {}
+GM.InfoMessageLine = 0
+
+usermessage.Hook( "gms_sendmessage", function( um )
+ local text = um:ReadString()
+ local dur = um:ReadShort()
+ local col = um:ReadString()
+ local str = string.Explode( ",", col )
+ local col = Color( tonumber( str[1] ), tonumber( str[2] ), tonumber( str[3] ), tonumber( str[4] ) )
+
+ for k,v in pairs( GAMEMODE.InfoMessages ) do
+ v.drawline = v.drawline + 1
+ end
+
+ local message = {}
+ message.Text = text
+ message.Col = col
+ message.Tab = 5
+ message.drawline = 1
+
+ GAMEMODE.InfoMessages[#GAMEMODE.InfoMessages + 1] = message
+ GAMEMODE.InfoMessageLine = GAMEMODE.InfoMessageLine + 1
+
+ timer.Simple( dur, function() GAMEMODE.DropMessage( message ) end )
+end )
+
+hook.Add( "HUDPaint", "gms_drawmessages", function()
+ for k,msg in pairs( GAMEMODE.InfoMessages ) do
+ local txt = msg.Text
+ local line = ScrH() / 2 + ( msg.drawline * 20 )
+ local tab = msg.Tab
+ local col = msg.Col
+ draw.SimpleTextOutlined( txt, "ScoreboardText", tab, line, col, 0, 0, 0.5, Color( 100, 100, 100, 150 ) )
+
+ if ( msg.Fading ) then
+ msg.Tab = msg.Tab - ( msg.InitTab - msg.Tab - 0.05 )
+
+ if ( msg.Tab > ScrW() + 10 ) then
+ GAMEMODE.RemoveMessage( msg )
+ end
+ end
+ end
+end )
+
+function GM.DropMessage( msg )
+ msg.InitTab = msg.Tab
+ msg.Fading = true
+end
+
+function GM.RemoveMessage( msg )
+ for k, v in pairs( GAMEMODE.InfoMessages ) do
+ if ( v == msg ) then
+ GAMEMODE.InfoMessages[k] = nil
+ GAMEMODE.InfoMessageLine = GAMEMODE.InfoMessageLine - 1
+ table.remove( GAMEMODE.InfoMessages, k )
+ end
+ end
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Prop Fading
+---------------------------------------------------------------------------------------------------- */
+
+GM.FadingProps = {}
+
+usermessage.Hook( "gms_CreateFadingProp", function( um )
+ local mdl = um:ReadString()
+ local pos = um:ReadVector()
+ local dir = um:ReadVector()
+ local col = um:ReadVector()
+ local speed = um:ReadShort()
+
+ if ( !mdl or !pos or !dir or !speed ) then return end
+
+ local ent = ents.CreateClientProp( mdl )
+ ent:SetPos( pos )
+ ent:SetColor( Color( col.x, col.y, col.z) )
+ ent:SetAngles( Angle( dir.x, dir.y, dir.z ) )
+ ent:Spawn()
+
+ ent.Alpha = 255
+ ent.Speed = speed
+
+ table.insert( GAMEMODE.FadingProps, ent )
+end )
+
+hook.Add( "Think", "gms_FadeFadingPropsHook", function()
+ for k, v in pairs( GAMEMODE.FadingProps ) do
+ if ( v.Alpha ) then
+ if ( v.Alpha <= 0 ) then
+ v:Remove()
+ table.remove( GAMEMODE.FadingProps, k )
+ else
+ v.Alpha = v.Alpha - v.Speed
+
+ v:SetRenderMode( RENDERMODE_TRANSALPHA )
+ local oldColor = v:GetColor()
+ v:SetColor( Color( oldColor.r, oldColor.g, oldColor.b, math.min( math.max( v.Alpha, 0 ), 255 ) ) )
+ end
+ end
+ end
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Achievement Messages
+---------------------------------------------------------------------------------------------------- */
+
+GM.AchievementMessages = {}
+
+usermessage.Hook( "gms_sendachievement", function( um )
+ local tbl = {}
+ tbl.Text = um:ReadString()
+ tbl.Alpha = 255
+
+ table.insert( GAMEMODE.AchievementMessages, tbl )
+end )
+
+hook.Add( "HUDPaint", "gms_drawachievementmessages", function()
+ for k, msg in pairs( GAMEMODE.AchievementMessages ) do
+ msg.Alpha = msg.Alpha - 1
+ draw.SimpleTextOutlined( msg.Text, "ScoreboardHead", ScrW() / 2, ScrH() / 2, Color( 255, 255, 255, msg.Alpha ), 1, 1, 0.5, Color( 100, 100, 100, msg.Alpha ) )
+
+ if ( msg.Alpha <= 0 ) then
+ table.remove( GAMEMODE.AchievementMessages, k )
+ end
+ end
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Needs
+---------------------------------------------------------------------------------------------------- */
+
+usermessage.Hook( "gms_setneeds", function( um )
+ Sleepiness = um:ReadShort()
+ Hunger = um:ReadShort()
+ Thirst = um:ReadShort()
+ Oxygen = um:ReadShort()
+ Power = um:ReadShort()
+ Time = um:ReadShort()
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Help menu
+---------------------------------------------------------------------------------------------------- */
+
+concommand.Add( "gms_help", function()
+ if ( !LocalPlayer():GetNWBool( "AFK" ) ) then RunConsoleCommand( "gms_afk" ) end
+
+ local HelpMenu = vgui.Create( "DFrame" )
+ HelpMenu:MakePopup()
+ HelpMenu:SetSize( ScrW() - 100, ScrH() - 100 )
+ HelpMenu:Center()
+ HelpMenu:SetTitle( "Garry's Mod Stranded Help" )
+ function HelpMenu:OnClose()
+ if ( LocalPlayer():GetNWBool( "AFK" ) ) then RunConsoleCommand( "gms_afk" ) end
+ end
+
+ HelpMenu.HTML = vgui.Create( "HTML", HelpMenu )
+ HelpMenu.HTML:SetSize( HelpMenu:GetWide() - 10, HelpMenu:GetTall() - 30 )
+ HelpMenu.HTML:SetPos( 5, 25 )
+ HelpMenu.HTML:OpenURL( "http://steamcommunity.com/sharedfiles/filedetails/?id=135129872" )
+ //HelpMenu.HTML:SetHTML( file.Read( "help/helpnew.htm", "GAME" ) )
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Sleep
+---------------------------------------------------------------------------------------------------- */
+
+local SleepFade = 0
+hook.Add( "HUDPaint", "gms_sleepoverlay", function()
+ if ( LocalPlayer():GetNWBool( "Sleeping" ) ) then
+ SleepFade = math.min( SleepFade + 3, 254 )
+ else
+ SleepFade = math.max( SleepFade - 6, 0 )
+ end
+
+ if ( SleepFade == 0 ) then return end
+
+ surface.SetDrawColor( 0, 0, 0, SleepFade )
+ surface.DrawRect( 0, 0, ScrW(), ScrH() )
+
+ draw.SimpleText( "Use the command \"!wakeup\" or press F4 to wake up.", "ScoreboardSub", ScrW() / 2, ScrH() / 1.5, Color( 255, 255, 255, SleepFade ), 1, 1 )
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ AFK
+---------------------------------------------------------------------------------------------------- */
+
+local AFKFade = 0
+hook.Add( "HUDPaint", "gms_afkoverlay", function()
+ if ( LocalPlayer():GetNWBool( "AFK" ) ) then
+ AFKFade = math.min( AFKFade + 3, 254 )
+ else
+ AFKFade = math.max( AFKFade - 6, 0 )
+ end
+
+ if ( AFKFade == 0 ) then return end
+
+ surface.SetDrawColor( 0, 0, 0, AFKFade )
+ surface.DrawRect( 0, 0, ScrW(), ScrH() )
+
+ draw.SimpleText( "Use the command \"!afk\" or press F4 to stop being afk.", "ScoreboardSub", ScrW() / 2, ScrH() / 1.5, Color( 255, 255, 255, AFKFade ), 1, 1 )
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Unlocks
+---------------------------------------------------------------------------------------------------- */
+
+usermessage.Hook( "gms_AddUnlock", function( um )
+ local UnlockWindow = vgui.Create( "GMS_UnlockWindow" )
+ UnlockWindow:SetMouseInputEnabled( true )
+ UnlockWindow:SetUnlock( um:ReadString() )
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Tribes
+---------------------------------------------------------------------------------------------------- */
+
+concommand.Add( "gms_tribemenu", function()
+ if ( !GAMEMODE.TribeMenu ) then
+ GAMEMODE.TribeMenu = vgui.Create( "GMS_TribeMenu" )
+ GAMEMODE.TribeMenu:SetDeleteOnClose( false )
+ GAMEMODE.TribeMenu:SetVisible( false )
+ end
+
+ GAMEMODE.TribeMenu:SetVisible( !GAMEMODE.TribeMenu:IsVisible() )
+end )
+
+concommand.Add( "gms_tribes", function()
+ if ( #Tribes <= 0 ) then chat.AddText( Color( 255, 255, 255 ), "No tribes created so far. Why not create one?" ) return end
+ local TribesMenu = vgui.Create( "GMS_TribesList" )
+end )
+
+usermessage.Hook( "gms_invite", function( data )
+ local tn = data:ReadString()
+ local p = data:ReadString()
+ Derma_Query( "You are being invited to " .. tn .. ".\nChoose action below.", "Invitation",
+ "Join", function() RunConsoleCommand( "gms_join", tn, p ) end,
+ "Decline", function() RunConsoleCommand( "say", "I don't want to join " .. tn .. "." ) end
+ )
+end )
+
+usermessage.Hook( "sendTribe", function( data )
+
+ local id = data:ReadShort()
+ local name = data:ReadString()
+ local color = data:ReadVector()
+ local hazpass = data:ReadBool()
+
+ team.SetUp( id, name, Color( color.r, color.g, color.b ) )
+
+ table.insert( Tribes, { name = name, pass = hazpass, id = id, color = Color( color.r, color.g, color.b ) } )
+
+end )
diff --git a/ftp_gmstranded/gamemode/cl_panels.lua b/ftp_gmstranded/gamemode/cl_panels.lua
new file mode 100644
index 0000000..da01d3c
--- /dev/null
+++ b/ftp_gmstranded/gamemode/cl_panels.lua
@@ -0,0 +1,1158 @@
+
+surface.CreateFont( "DefaultBold", {
+ font = "Tahoma",
+ size = 16,
+ weight = 1000,
+ antialias = true,
+ additive = false
+} )
+
+surface.CreateFont( "GMSUnlockDescription", {
+ font = "Tahoma",
+ size = 14,
+ weight = 500,
+ antialias = true,
+ additive = false
+} )
+
+/*---------------------------------------------------------
+ Unlock window
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetTitle( "You have unlocked a new ability!" )
+ self:MakePopup()
+
+ self.Name = "Name"
+ self.Description = ""
+
+ self:SetSize( ScrW() / 3, 250 )
+ self:Center()
+
+ self.DescWindow = vgui.Create( "DLabel", self )
+ self.DescWindow:SetPos( 5, 100 )
+ self.DescWindow:SetSize( self:GetWide() - 10, self:GetTall() - 140 )
+ self.DescWindow:SetFont( "GMSUnlockDescription" )
+ self.DescWindow:SetWrap( true )
+ self.DescWindow:SetText( "" )
+
+ self.Okay = vgui.Create( "DButton", self )
+ self.Okay:SetSize( self:GetWide() - 10, 30 )
+ self.Okay:SetPos( 5, self:GetTall() - 35 )
+ self.Okay:SetText( "Okay" )
+ self.Okay.DoClick = function() self:Close() end
+end
+
+function PANEL:PaintOver( w, h )
+ draw.SimpleTextOutlined( self.Name, "ScoreboardHead", self:GetWide() / 2, 60, Color( 10, 200, 10 ), 1, 1, 0.5, Color( 100, 100, 100, 160 ) )
+ //draw.SimpleText( self.Description, "GMSUnlockDescription", self:GetWide() / 2, 140, Color( 200, 200, 200 ), 1, 1 )
+end
+
+function PANEL:SetUnlock( text )
+ local unlock = GMS.FeatureUnlocks[ text ]
+ if ( !unlock ) then return end
+
+ self.Name = unlock.Name
+ self.Description = unlock.Description
+ self.DescWindow:SetText( unlock.Description )
+end
+
+vgui.Register( "GMS_UnlockWindow", PANEL, "DFrame" )
+
+/*---------------------------------------------------------
+ Tribe Menu
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetTitle( "Create-A-Tribe" )
+ self:SetSize( 275, 305 )
+ self:MakePopup()
+ self:Center()
+
+ local tnamelabel = vgui.Create( "DLabel", self )
+ tnamelabel:SetPos( 5, 21 )
+ tnamelabel:SetText( "Tribe name" )
+
+ local tname = vgui.Create( "DTextEntry", self )
+ tname:SetSize( self:GetWide() - 10, 20 )
+ tname:SetPos( 5, 40 )
+
+ local tpwlabel = vgui.Create( "DLabel", self )
+ tpwlabel:SetPos( 5, 65 )
+ tpwlabel:SetText( "Tribe password ( Optional )" )
+ tpwlabel:SizeToContents()
+
+ local tpw = vgui.Create( "DTextEntry", self )
+ tpw:SetSize( self:GetWide() - 10, 20 )
+ tpw:SetPos( 5, 80 )
+
+ local tcollabel = vgui.Create( "DLabel", self )
+ tcollabel:SetPos( 5, 105 )
+ tcollabel:SetText( "Tribe color" )
+
+ local tcolor = vgui.Create( "DColorMixer", self )
+ tcolor:SetSize( self:GetWide() - 15, 150 )
+ tcolor:SetPos( 5, 125 )
+
+ local button = vgui.Create( "DButton", self )
+ button:SetSize( self:GetWide() - 10, 20 )
+ button:SetPos( 5, 280 )
+ button:SetText( "Create Tribe!" )
+ button.DoClick = function()
+ RunConsoleCommand( "gms_createtribe", tname:GetValue(), tcolor:GetColor().r, tcolor:GetColor().g, tcolor:GetColor().b, tpw:GetValue() )
+ self:SetVisible( false )
+ end
+end
+vgui.Register( "GMS_TribeMenu", PANEL, "DFrame" )
+
+/*---------------------------------------------------------
+ Tribes List
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetTitle( "Join-A-Tribe" )
+ self:MakePopup()
+
+ local width = ScrW() / 4
+
+ for id, tabl in pairs( Tribes ) do
+ surface.SetFont( "DefaultBold" )
+ local w = surface.GetTextSize( tabl.name )
+ width = math.max( width, w + 16 + 10 + 20 )
+ end
+
+ for id, tabl in pairs( Tribes ) do
+
+ local button = vgui.Create( "GMS_TribeButton", self )
+ button:SetSize( width - 16, 16 )
+ button:SetPos( 8, 10 + id * 21 )
+ button:SetInfo( tabl )
+
+ end
+
+ self:SetSize( width, #Tribes * 21 + 35 )
+ self:Center()
+end
+
+vgui.Register( "GMS_TribesList", PANEL, "DFrame" )
+
+----------------------------------------------------------------------------------------------------
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetText( "" )
+ self.Tribe = {}
+end
+
+function PANEL:Paint()
+
+ surface.SetDrawColor( self.Tribe.color )
+ surface.DrawRect( 0, 0, self:GetTall(), self:GetTall() )
+
+ surface.SetDrawColor( 0, 0, 0, 200 )
+ if ( self.Hovered ) then surface.SetDrawColor( 255, 255, 255, 64 ) end
+ surface.DrawRect( self:GetTall(), 0, self:GetWide() - self:GetTall(), self:GetTall() )
+
+ surface.SetFont( "DefaultBold" )
+ local w = surface.GetTextSize( self.Tribe.name )
+ draw.SimpleText( self.Tribe.name, "DefaultBold", ( self:GetWide() - 16 ) / 2 + 16, 0, color_white , 1 )
+
+end
+
+function PANEL:DoClick()
+ if ( self.Tribe.pass ) then
+ local name = self.Tribe.name
+ Derma_StringRequest( "Please enter password", "Please enter password for the tribe.", "", function( text ) RunConsoleCommand( "gms_join", name, text ) end )
+ else
+ RunConsoleCommand( "gms_join", self.Tribe.name )
+ end
+ self:GetParent():Close()
+end
+
+function PANEL:SetInfo( tbl )
+ self.Tribe = tbl
+end
+
+vgui.Register( "GMS_TribeButton", PANEL, "DButton" )
+
+/*---------------------------------------------------------
+ Skills panel
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetPos( 1, 0 )
+ self:SetSize( ScrW() / 6, 34 )
+
+ self:SetVisible( true )
+
+ self.Extended = false
+ self.SkillLabels = {}
+
+ self:RefreshSkills()
+end
+
+function PANEL:Paint()
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawLine( self:GetWide() - 1, 0, self:GetWide() - 1, self:GetTall() ) -- Nice line instead of messy outlined rect
+ surface.DrawLine( 0, self:GetTall() - 1, self:GetWide(), self:GetTall() - 1 )
+ surface.DrawLine( 0, 0, 0, self:GetTall() )
+ if ( self.Extended ) then
+ surface.DrawLine( 0, 33, self:GetWide(), 33 )
+ end
+
+ draw.SimpleText( "Skills ( F1 )", "ScoreboardSub", self:GetWide() / 2, 17, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+
+end
+
+function PANEL:RefreshSkills()
+ for k, v in pairs( self.SkillLabels ) do v:Remove() end
+
+ self.SkillLabels = {}
+ self.Line = 39
+
+ for k, v in SortedPairs( Skills ) do
+ local lbl = vgui.Create( "gms_SkillPanel", self )
+ lbl:SetPos( 0, self.Line )
+ lbl:SetSize( self:GetWide(), 16 )
+ local val = string.gsub( k, "_", " " )
+ lbl:SetSkill( val )
+
+ self.Line = self.Line + lbl:GetTall() + 5
+ table.insert( self.SkillLabels, lbl )
+ if ( !self.Extended ) then lbl:SetVisible( false ) end
+ end
+
+ if ( self.Extended ) then
+ self:SetSize( ScrW() / 6, 40 + ( table.Count( self.SkillLabels ) * 21 ) )
+ end
+end
+
+function PANEL:ToggleExtend()
+ if ( !self.Extended ) then
+ self:SetSize( ScrW() / 6, 40 + ( table.Count( self.SkillLabels ) * 21 ) )
+ self.Extended = true
+
+ for k, v in pairs( self.SkillLabels ) do v:SetVisible( true ) end
+ else
+ self:SetSize( ScrW() / 6, 34 )
+ self.Extended = false
+
+ for k, v in pairs( self.SkillLabels ) do v:SetVisible( false ) end
+ end
+end
+
+function PANEL:OnMousePressed( mc )
+ if ( mc == 107 ) then
+ self:ToggleExtend()
+ end
+end
+
+vgui.Register( "gms_SkillsHud", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Skill Sub-Panel
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+end
+
+function PANEL:Paint()
+ surface.SetDrawColor( 0, 0, 0, 178 ) -- XP bar background
+ surface.DrawRect( 5, 0, self:GetWide() - 10, self:GetTall() )
+
+ local XP = math.floor( Experience[ self.Skill ] / 100 * ( self:GetWide() - 10 ) )
+ surface.SetDrawColor( 0, 128, 0, 220 ) -- XP bar
+ if ( self.TxtSkill == "Survival" ) then
+ surface.SetDrawColor( 0, 128, 176, 220 ) -- XP bar
+ end
+ surface.DrawRect( 5, 0, XP, self:GetTall() )
+
+ draw.SimpleText( self.TxtSkill .. ": " .. Skills[ self.Skill ] .. " ( " .. Experience[ self.Skill ] .. " / 100 )", "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+end
+
+function PANEL:SetSkill( str )
+ self.TxtSkill = str
+ self.Skill = string.gsub( str, " ", "_" )
+end
+
+vgui.Register( "gms_SkillPanel", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Resource panel
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+
+ self:SetPos( ScrW() / 6 + 2, 0 )
+ self:SetSize( ScrW() / 6, 34 )
+ self:SetVisible( true )
+ self.Extended = false
+ self.ResourceLabels = {}
+
+ self:RefreshResources()
+
+end
+
+function PANEL:Paint()
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawLine( 0, 0, 0, self:GetTall() )
+ surface.DrawLine( self:GetWide() - 1, 0, self:GetWide() - 1, self:GetTall() )
+ surface.DrawLine( 0, self:GetTall() - 1, self:GetWide(), self:GetTall() - 1 )
+ if ( self.Extended ) then
+ surface.DrawLine( 0, 33, self:GetWide(), 33 )
+ end
+
+ draw.SimpleText( "Resources ( F2 )", "ScoreboardSub", self:GetWide() / 2, 17, StrandedTextColor, 1, 1 )
+ return true
+
+end
+
+function PANEL:RefreshResources()
+ if ( IsValid( GAMEMODE.ResourcePackFrame ) ) then GAMEMODE.ResourcePackFrame:Update() end
+ for k, v in pairs( self.ResourceLabels ) do v:Remove() end
+
+ self.ResourceLabels = {}
+ self.Line = 39
+ self.Resourcez = 0
+
+ for k, v in SortedPairs( Resources ) do
+ if ( v > 0 ) then
+ local lbl = vgui.Create( "gms_ResourcePanel", self )
+ lbl:SetPos( 0, self.Line )
+ lbl:SetSize( self:GetWide(), 16 )
+ lbl:SetResource( k )
+ self.Resourcez = self.Resourcez + v
+
+ self.Line = self.Line + lbl:GetTall() + 5
+ table.insert( self.ResourceLabels, lbl )
+ if ( !self.Extended ) then lbl:SetVisible( false ) end
+ end
+ end
+
+ self.Line = self.Line + 21
+
+ local lblT = vgui.Create( "gms_ResourcePanelTotal", self )
+ lblT:SetPos( 0, self.Line )
+ lblT:SetSize( self:GetWide(), 16 )
+ lblT:SetResources( self.Resourcez )
+
+ table.insert( self.ResourceLabels, lblT )
+ if ( !self.Extended ) then lblT:SetVisible( false ) end
+
+ if ( self.Extended ) then
+ self:SetSize( ScrW() / 6, 40 + ( ( table.Count( self.ResourceLabels ) + 1 ) * 21 ) )
+ end
+
+ if ( GAMEMODE.CommandsHud ) then GAMEMODE.CommandsHud:SetPos( ScrW() / 6 + 2, self:GetTall() ) end
+end
+
+function PANEL:ToggleExtend()
+ self:SetExtended( !self.Extended )
+end
+
+function PANEL:SetExtended( bool )
+ if ( bool ) then
+ self:SetSize( ScrW() / 6, 40 + ( ( table.Count( self.ResourceLabels ) + 1 ) * 21 ) )
+ self.Extended = true
+ for k,v in pairs( self.ResourceLabels ) do
+ v:SetVisible( true )
+ end
+ else
+ self:SetSize( ScrW() / 6, 34 )
+ self.Extended = false
+ for k, v in pairs( self.ResourceLabels ) do
+ v:SetVisible( false )
+ end
+ end
+ if ( GAMEMODE.CommandsHud ) then GAMEMODE.CommandsHud:SetPos( ScrW() / 6 + 2, self:GetTall() ) end
+end
+
+function PANEL:OnMousePressed( mc )
+ if ( mc == 107 ) then self:ToggleExtend() end
+end
+vgui.Register( "gms_ResourcesHud", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Resource Sub-Panel
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+PANEL.GroundActions = {}
+PANEL.GroundActions[ "Sprouts" ] = { cmd = "gms_planttree", name = "Plant" }
+PANEL.GroundActions[ "Banana_Seeds" ] = { cmd = "gms_plantbanana", name = "Plant" }
+PANEL.GroundActions[ "Orange_Seeds" ] = { cmd = "gms_plantorange", name = "Plant" }
+PANEL.GroundActions[ "Grain_Seeds" ] = { cmd = "gms_plantgrain", name = "Plant" }
+PANEL.GroundActions[ "Melon_Seeds" ] = { cmd = "gms_plantmelon", name = "Plant" }
+PANEL.GroundActions[ "Berries" ] = { cmd = "gms_plantbush", name = "Plant" }
+
+PANEL.NormalActions = {}
+PANEL.NormalActions[ "Berries" ] = { cmd = "gms_EatBerry", name = "Eat" }
+PANEL.NormalActions[ "Medicine" ] = { cmd = "gms_TakeMedicine", name = "Take" }
+PANEL.NormalActions[ "Water_Bottles" ] = { cmd = "gms_DrinkBottle", name = "Drink" }
+
+function PANEL:Init()
+ self:SetText( "" )
+end
+
+function PANEL:Paint()
+ surface.SetDrawColor( 0, 0, 0, 178 ) -- Resource bar background
+ surface.DrawRect( 5, 0, self:GetWide() - 10, self:GetTall() )
+
+ local XP = math.floor( Resources[ self.Resource ] / MaxResources * ( self:GetWide() - 10 ) )
+ surface.SetDrawColor( 0, 128, 0, 200 ) -- Resource bar
+ surface.DrawRect( 5, 0, XP, self:GetTall() )
+
+ if ( self.Hovered ) then
+ surface.SetDrawColor( 255, 255, 255, 64 ) -- Resource bar background
+ surface.DrawRect( 5, 0, self:GetWide() - 10, self:GetTall() )
+ end
+
+ draw.SimpleText( self.TxtResource .. ": " .. Resources[ self.Resource ], "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+end
+
+function PANEL:DoRightClick()
+ local menu = DermaMenu()
+
+ if ( self.GroundActions[ self.Resource ] ) then
+ menu:AddOption( self.GroundActions[ self.Resource ].name, function()
+ if ( self.GroundActions ) then
+ RunConsoleCommand( self.GroundActions[ self.Resource ].cmd )
+ end
+ end )
+ end
+
+ if ( self.NormalActions[ self.Resource ] ) then
+ menu:AddOption( self.NormalActions[ self.Resource ].name, function()
+ if ( self.NormalActions ) then
+ RunConsoleCommand( self.NormalActions[ self.Resource ].cmd )
+ end
+ end )
+ end
+
+ menu:AddSpacer()
+
+ menu:AddOption( "Drop x1", function() RunConsoleCommand( "gms_DropResources", self.Resource, " 1" ) end )
+ menu:AddOption( "Drop x10", function() RunConsoleCommand( "gms_DropResources", self.Resource, " 10" ) end )
+ menu:AddOption( "Drop All", function() RunConsoleCommand( "gms_DropResources", self.Resource ) end )
+ menu:AddOption( "Cancel", function() end )
+ menu:Open()
+end
+
+function PANEL:DoClick()
+ local tr = util.TraceLine( {
+ start = LocalPlayer():GetShootPos(),
+ endpos = LocalPlayer():GetShootPos() + LocalPlayer():GetAimVector() * 150,
+ filter = LocalPlayer()
+ } )
+
+ if ( self.GroundActions && self.GroundActions[ self.Resource ] && tr.HitWorld ) then
+ RunConsoleCommand( self.GroundActions[ self.Resource ].cmd )
+ elseif ( self.NormalActions && self.NormalActions[ self.Resource ] ) then
+ RunConsoleCommand( self.NormalActions[ self.Resource ].cmd )
+ end
+end
+
+function PANEL:SetResource( str )
+ self.TxtResource = string.gsub( str, "_", " " )
+ self.Resource = str
+end
+
+vgui.Register( "gms_ResourcePanel", PANEL, "DButton" )
+
+/*---------------------------------------------------------
+ Resource Total Sub-Panel
+---------------------------------------------------------*/
+local PANEL = {}
+
+function PANEL:Init()
+ self.Res = 0
+end
+
+function PANEL:Paint()
+ surface.SetDrawColor( 0, 0, 0, 178 ) -- Resource bar background
+ surface.DrawRect( 5, 0, self:GetWide() - 10, self:GetTall() )
+
+ local XP = math.floor( self.Res / MaxResources * ( self:GetWide() - 10 ) )
+ surface.SetDrawColor( 0, 128, 176, 220 ) -- Resource bar
+ surface.DrawRect( 5, 0, XP, self:GetTall() )
+
+ draw.SimpleText( "Total: " .. self.Res .. " / " .. MaxResources, "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+end
+
+function PANEL:SetResources( num )
+ self.Res = num
+end
+
+vgui.Register( "gms_ResourcePanelTotal", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Command panel
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+
+ self:SetPos( ScrW() / 6 + 2, 33 )
+ self:SetSize( ScrW() / 6, 34 )
+ self:SetVisible( false )
+ self.Extended = true
+ self.CommandLabels = {}
+
+ self:RefreshCommands()
+
+end
+
+function PANEL:Paint()
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() )
+
+ surface.SetDrawColor( StrandedBorderColor )
+
+ surface.DrawLine( self:GetWide() - 1, 0, self:GetWide() - 1, self:GetTall() )
+ surface.DrawLine( 0, 0, 0, self:GetTall() )
+ surface.DrawLine( 0, self:GetTall() - 1, self:GetWide(), self:GetTall() - 1 )
+ if ( self.Extended ) then surface.DrawLine( 0, 33, self:GetWide(), 33 ) end
+
+ draw.SimpleText( "Commands", "ScoreboardSub", self:GetWide() / 2, 17, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+
+end
+
+function PANEL:CreateButton( x, y, w, h, cmd, txt, clr )
+ local line = vgui.Create( "gms_CommandPanel", self )
+ line:SetPos( x, y )
+ line:SetSize( w, h )
+ line:SetCommand( cmd, txt, clr )
+
+ if ( !self.Extended ) then line:SetVisible( false ) end
+ table.insert( self.CommandLabels, line )
+
+ return line
+end
+
+function PANEL:RefreshCommands()
+ for k, v in pairs( self.CommandLabels ) do v:Remove() end
+
+ self.CommandLabels = {}
+ self.Line = 39
+ self.Lines = 7
+
+ local halfsize = self:GetWide() / 2
+ local threesize = self:GetWide() / 4
+
+ local line1 = self:CreateButton( 0, self.Line, halfsize, 16, "gms_sleep", "Sleep", Color( 0, 128, 255, 176 ) )
+ local line1b = self:CreateButton( halfsize, self.Line, halfsize, 16, "gms_wakeup", "Wake up", Color( 0, 128, 255, 176 ) )
+
+ self.Line = self.Line + line1:GetTall() + 5
+
+ local line2 = self:CreateButton( 0, self.Line, halfsize, 16, "gms_combinations", "Combinations", Color( 200, 200, 0, 176 ) )
+ local line2b = self:CreateButton( halfsize, self.Line, halfsize, 16, "gms_structures", "Structures", Color( 200, 200, 0, 176 ) )
+
+ self.Line = self.Line + line2:GetTall() + 5
+
+ local line3 = self:CreateButton( 0, self.Line, halfsize, 16, "gms_dropweapon", "Drop: Weapon", Color( 255, 0, 0, 176 ) )
+ local line3b = self:CreateButton( halfsize, self.Line, halfsize, 16, "gms_dropall", "All resources", Color( 255, 0, 0, 176 ) )
+
+ self.Line = self.Line + line3:GetTall() + 5
+
+ local line4 = self:CreateButton( 0, self.Line, halfsize, 16, "gms_salvage", "Prop: Salvage", Color( 200, 0, 0, 176 ) )
+ local line4b = self:CreateButton( halfsize, self.Line, halfsize, 16, "gms_steal", "Steal", Color( 200, 0, 0, 176 ) )
+
+ self.Line = self.Line + line4:GetTall() + 5
+
+ local line5 = self:CreateButton( 0, self.Line, halfsize, 16, "gms_savecharacter", "Save", Color( 0, 200, 0, 176 ) )
+ local line5b = self:CreateButton( halfsize, self.Line, halfsize, 16, "gms_afk", "Toggle AFK", Color( 0, 200, 0, 176 ) )
+
+ self.Line = self.Line + line5:GetTall() + 5
+
+ local line6 = self:CreateButton( 0, self.Line, halfsize, 16, "gms_makefire", "Make Campfire", Color( 255, 128, 0, 176 ) )
+ local line6b = self:CreateButton( halfsize, self.Line, halfsize, 16, "gms_help", "Help", Color( 255, 128, 0, 176 ) )
+
+ self.Line = self.Line + line6:GetTall() + 5
+
+ local line7a = self:CreateButton( 0, self.Line, halfsize, 16, "gms_tribemenu", "Tribe: Create", Color( 200, 0, 200, 176 ) )
+ local line7b = self:CreateButton( halfsize, self.Line, threesize, 16, "gms_tribes", "Join", Color( 200, 0, 200, 176 ) )
+ local line7c = self:CreateButton( halfsize + threesize, self.Line, threesize, 16, "gms_leave", "Leave", Color( 200, 0, 200, 176 ) )
+
+ if ( self.Extended ) then
+ self:SetSize( ScrW() / 6, 40 + ( self.Lines * 21 ) )
+ end
+end
+
+function PANEL:ToggleExtend( b )
+ //self:SetExtended( !self.Extended, b )
+end
+
+function PANEL:SetExtended( bool ,b )
+ if ( bool ) then
+ self:SetSize( ScrW() / 6, 40 + ( self.Lines * 21 ) )
+ self.Extended = true
+ self:SetVisible( true )
+ for k,v in pairs( self.CommandLabels ) do v:SetVisible( true ) end
+ else
+ self:SetSize( ScrW() / 6, 34 )
+ self.Extended = false
+ self:SetVisible( false )
+ for k, v in pairs( self.CommandLabels ) do v:SetVisible( false ) end
+ end
+end
+
+vgui.Register( "gms_CommandsHud", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Command Sub-Panel
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetText( "" )
+ self.Cmd = ""
+ self.Text = ""
+ self.Clr = Color( 0, 128, 0, 178 )
+end
+
+function PANEL:Paint()
+ surface.SetDrawColor( self.Clr.r, self.Clr.g, self.Clr.b, self.Clr.a ) -- Resource bar background
+ surface.DrawRect( 5, 0, self:GetWide() - 10, self:GetTall() )
+
+ local colr = Color( 255, 255, 255, 255 )
+ if ( self.Clr.r >= 200 and self.Clr.g >= 200 and self.Clr.b >= 200 ) then colr = Color( 0, 0, 0, 255 ) end
+
+ draw.SimpleText( self.Text, "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, colr, 1, 1 )
+
+ if ( self.Hovered ) then
+ surface.SetDrawColor( 255, 255, 255, 64 )
+ surface.DrawRect( 5, 0, self:GetWide() - 10, self:GetTall() )
+ end
+
+ return true
+end
+
+function PANEL:DoClick()
+ RunConsoleCommand( self.Cmd )
+end
+
+function PANEL:SetCommand( str, text, clr )
+ self.Cmd = str
+ self.Text = text
+ self.Clr = clr
+end
+
+vgui.Register( "gms_CommandPanel", PANEL, "DButton" )
+
+/*---------------------------------------------------------
+ Loading bar
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetSize( ScrW() / 2.7, ScrH() / 10 )
+ self:SetPos( ScrW() / 2 - ( self:GetWide() / 2 ), ScrH() / 2 - ( self:GetTall() / 2 ) )
+
+ self.Dots = "."
+ self.Message = ""
+end
+
+function PANEL:Paint()
+ draw.RoundedBox( 8, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 100, 150 ) ) //Background
+
+ //Text
+ draw.SimpleText( "Loading" .. self.Dots, "ScoreboardHead", self:GetWide() / 2, self:GetTall() / 2, Color( 255, 255, 255, 255 ), 1, 1 )
+ draw.SimpleText( self.Text, "ScoreboardText", self:GetWide() / 2, self:GetTall() / 1.2, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+end
+
+function PANEL:Show( msg )
+ self.IsStopped = false
+
+ self.Text = msg
+ timer.Simple( 0.5, function() self:UpdateDots() end )
+ self:SetVisible( true )
+end
+
+function PANEL:Hide()
+ self.IsStopped = true
+ self:SetVisible( false )
+end
+
+function PANEL:UpdateDots()
+ if ( self.IsStopped ) then return end
+
+ if self.Dots == "...." then
+ self.Dots = "."
+ else
+ self.Dots = self.Dots .. "."
+ end
+
+ timer.Simple( 0.5, function() self:UpdateDots() end )
+end
+
+vgui.Register( "gms_LoadingBar", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Saving bar
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetSize( ScrW() / 2.7, ScrH() / 10 )
+ self:SetPos( ScrW() / 2 - ( self:GetWide() / 2 ), ScrH() / 2 - ( self:GetTall() / 2 ) )
+
+ self.Dots = "."
+ self.Message = ""
+end
+
+function PANEL:Paint()
+ //Background
+ draw.RoundedBox( 8, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 100, 150 ) )
+
+ //Text
+ draw.SimpleText( "Saving" .. self.Dots, "ScoreboardHead", self:GetWide() / 2, self:GetTall() / 2, Color( 255, 255, 255, 255 ), 1, 1 )
+ draw.SimpleText( self.Text, "ScoreboardText", self:GetWide() / 2, self:GetTall() / 1.2, Color( 255, 255, 255, 255 ), 1, 1 )
+ return true
+end
+
+function PANEL:Show( msg )
+ self.IsStopped = false
+
+ self.Text = msg
+ timer.Simple( 0.5, function() self:UpdateDots() end )
+ self:SetVisible( true )
+end
+
+function PANEL:Hide()
+ self.IsStopped = true
+ self:SetVisible( false )
+end
+
+function PANEL:UpdateDots()
+ if ( self.IsStopped ) then return end
+
+ if ( self.Dots == "...." ) then
+ self.Dots = "."
+ else
+ self.Dots = self.Dots .. "."
+ end
+
+ timer.Simple( 0.5, function() self:UpdateDots() end )
+end
+
+vgui.Register( "gms_SavingBar", PANEL, "Panel" )
+
+/*---------------------------------------------------------
+ Command button
+---------------------------------------------------------*/
+local PANEL = {}
+
+function PANEL:Init()
+end
+
+function PANEL:DoClick()
+ LocalPlayer():ConCommand( self.Command .. "\n" )
+ surface.PlaySound( Sound( "ui/buttonclickrelease.wav" ) )
+end
+
+function PANEL:SetConCommand( cmd )
+ self.Command = cmd
+end
+
+function PANEL:OnCursorEntered()
+ surface.PlaySound( Sound( "ui/buttonrollover.wav" ) )
+end
+
+vgui.Register( "gms_CommandButton", PANEL, "DButton" )
+
+/*---------------------------------------------------------
+ Combination Window
+---------------------------------------------------------*/
+
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetSize( ScrW() / 1.3, ScrH() / 1.4 )
+ self:SetDeleteOnClose( false )
+ self:MakePopup()
+ self:Center()
+
+ self.CombiList = vgui.Create( "DPanelList", self )
+ self.CombiList:SetPos( 5, 25 )
+ self.CombiList:SetSize( self:GetWide() - 10, self:GetTall() * 0.55 )
+ self.CombiList:SetSpacing( 5 )
+ self.CombiList:SetPadding( 5 )
+ self.CombiList:EnableHorizontal( true )
+ self.CombiList:EnableVerticalScrollbar( true )
+
+ self.Info = vgui.Create( "DPanel", self )
+ self.Info:SetPos( 5, self.CombiList:GetTall() + 30 )
+ self.Info:SetSize( self:GetWide() - 10, self:GetTall() - self.CombiList:GetTall() - 70 )
+
+ self.Info.NameLabel = vgui.Create( "DLabel", self.Info )
+ self.Info.NameLabel:SetPos( 5, 5 )
+ self.Info.NameLabel:SetSize( self.Info:GetWide(), 20 )
+ self.Info.NameLabel:SetFont( "ScoreboardSub" )
+ self.Info.NameLabel:SetDark( true )
+ self.Info.NameLabel:SetText( "Select a recipe" )
+
+ self.Info.DescLabel = vgui.Create( "DLabel", self.Info )
+ self.Info.DescLabel:SetPos( 5, 25 )
+ self.Info.DescLabel:SetSize( self.Info:GetWide(), self.Info:GetTall() - 30 )
+ self.Info.DescLabel:SetDark( true )
+ self.Info.DescLabel:SetText( "" )
+
+ self.button = vgui.Create( "gms_CommandButton", self )
+ self.button:SetPos( 5, self:GetTall() - 35 )
+ self.button:SetSize( self:GetWide() - 10, 30 )
+ self.button:SetText( "Make" )
+ self.button:SetDisabled( true )
+ function self.button:DoClick()
+ local p = self:GetParent()
+ local combi = p.CombiGroupName or ""
+ local active = p.ActiveCombi or ""
+ p:Close()
+ LocalPlayer():ConCommand( "gms_MakeCombination " .. combi .. " " .. active .. "\n" )
+ end
+
+ self.IconSize = 86
+ self.CombiPanels = {}
+end
+
+function PANEL:SetTable( str )
+ self:SetTitle( "#" .. str )
+ self.CombiGroupName = str
+ self.CombiGroup = GMS.Combinations[ str ]
+ self:Clear()
+ for name, tbl in SortedPairs( self.CombiGroup or {} ) do
+ local icon = vgui.Create( "GMS_CombiIcon", self.CombiList )
+ icon:SetSize( self.IconSize, self.IconSize )
+ icon:SetInfo( name, tbl )
+ self.CombiList:AddItem( icon )
+ table.insert( self.CombiPanels, icon )
+ end
+ self:ClearActive()
+end
+
+function PANEL:SetActive( combi, tbl )
+ self.ActiveCombi = combi
+ self.ActiveTable = tbl
+ self.Info.NameLabel:SetText( tbl.Name )
+
+ local desc = tbl.Description
+
+ if ( tbl.Req or tbl.SkillReq ) then
+ desc = desc .. "\n\nYou need:"
+ end
+
+ if ( tbl.Req and table.Count( tbl.Req ) > 0 ) then
+ for res, num in pairs( tbl.Req ) do
+ if ( tbl.AllSmelt ) then
+ desc = desc .. "\n" .. string.Replace( res, "_", " " ) .. " ( " .. tbl.Max .. " max )"
+ else
+ desc = desc .. "\n" .. string.Replace( res, "_", " " ) .. ": " .. num
+ end
+ end
+ end
+
+ if ( tbl.SkillReq and table.Count( tbl.SkillReq ) > 0 ) then
+ for skill, num in pairs( tbl.SkillReq ) do
+ desc = desc .. "\n" .. string.Replace( skill, "_", " " ) .. " level " .. num
+ end
+ end
+
+ if ( tbl.FoodValue ) then
+ desc = desc .. "\n\nFood initial quality: " .. math.floor( tbl.FoodValue / 10 ) .. "%"
+ end
+
+ self.Info.DescLabel:SetText( desc )
+end
+
+function PANEL:ClearActive()
+ self.ActiveCombi = nil
+ self.ActiveTable = nil
+ self.Info.NameLabel:SetText( "Select a recipe" )
+ self.Info.DescLabel:SetText( "" )
+end
+
+function PANEL:Clear()
+ for k, v in pairs( self.CombiPanels ) do
+ v:Remove()
+ end
+ self.CombiPanels = {}
+end
+vgui.Register( "GMS_CombinationWindow", PANEL, "DFrame" )
+
+/*---------------------------------------------------------
+ Combi Icon
+---------------------------------------------------------*/
+
+local PANEL = {}
+PANEL.TexID = Material( "gms_icons/gms_none.png" )
+PANEL.BGTexID = Material( "gms_icons/gms_none_bg.png" )
+
+function PANEL:Paint( w, h )
+
+ surface.SetDrawColor( 200, 200, 200, 255 )
+ //surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() )*/
+
+ surface.SetMaterial( self.BGTexID )
+ surface.DrawTexturedRect( -( 128 - w ) / 2, -( 128 - h ) / 2, 128, 128 )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( 0, 0, self:GetWide(), self:GetTall() )
+
+ local hasskill = true
+ if ( self.CombiTable.SkillReq ) then
+ for k, v in pairs( self.CombiTable.SkillReq ) do
+ if ( GetSkill( k ) < v ) then hasskill = false end
+ end
+ end
+
+ local hasres = true
+ if ( self.CombiTable.Req ) then
+ for k, v in pairs( self.CombiTable.Req ) do
+ if ( GetResource( k ) < v ) then hasres = false end
+ end
+ end
+
+ if ( !hasskill ) then
+ surface.SetDrawColor( 200, 200, 0, 150 )
+ surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() )
+ elseif ( !hasres ) then
+ surface.SetDrawColor( 200, 0, 0, 100 )
+ surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() )
+ end
+
+ surface.SetDrawColor( 255, 255, 255, 255 )
+
+ surface.SetMaterial( self.TexID )
+ surface.DrawTexturedRect( -( 128 - w ) / 2, -( 128 - h ) / 2, 128, 128 )
+
+ local y = self:GetTall() / 2 + self:GetTall() / 4
+ draw.SimpleTextOutlined( self.CombiTable.Name, "DefaultSmall", self:GetWide() / 2, y, Color( 255, 255, 255, 255 ), 1, 1, 0.5, Color( 100, 100, 100, 140 ) )
+ return true
+
+end
+
+function PANEL:SetInfo( name, tbl )
+ if ( tbl.Texture && Material( tbl.Texture ) ) then self.TexID = Material( tbl.Texture ) end
+ self.Combi = name
+ self.CombiTable = tbl
+end
+
+function PANEL:OnMousePressed( mc )
+ if ( mc != 107 ) then return end
+ surface.PlaySound( Sound( "ui/buttonclickrelease.wav" ) )
+ self:GetParent():GetParent():GetParent():SetActive( self.Combi, self.CombiTable )
+ self:GetParent():GetParent():GetParent().button:SetDisabled( false )
+end
+
+function PANEL:OnCursorEntered()
+ surface.PlaySound( Sound( "ui/buttonrollover.wav" ) )
+end
+
+vgui.Register( "GMS_CombiIcon", PANEL, "DPanel" )
+
+/* Resource Pack GUI */
+
+local PANEL = {}
+
+function PANEL:Init()
+ self.Text = ""
+ self.Num = 0
+
+ self.TakeX = vgui.Create( "gms_takeButton", self )
+ self.TakeAll = vgui.Create( "gms_takeButton", self )
+end
+
+function PANEL:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 176, 176, 176, 255 ) )
+ draw.SimpleText( self.Text .. ": " .. self.Num, "DefaultBold", 5, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 0, 1 )
+end
+
+function PANEL:SetRes( str, num, isResPack )
+ self.Text = str
+ self.Num = num
+
+ if ( isResPack ) then
+ self.TakeX:SetRes( str, nil, false )
+ self.TakeAll:SetRes( str, num, true, false )
+ else
+ self.TakeX:Remove()
+ self.TakeX = nil
+ self.TakeAll:SetRes( str, 1, true, true )
+ end
+end
+
+function PANEL:PerformLayout()
+ self.TakeAll:SetSize( 64, self:GetTall() - 4 )
+ self.TakeAll:SetPos( self:GetWide() - 66, 2 )
+
+ if ( self.TakeX and self.TakeX != NULL ) then
+ self.TakeX:SetSize( 64, self:GetTall() - 4 )
+ self.TakeX:SetPos( self:GetWide() - 132, 2 )
+ end
+end
+
+vgui.Register( "gms_resourceLine", PANEL, "Panel" )
+
+// Take button
+local PANEL = {}
+
+function PANEL:Init()
+ self.Text = ""
+ self.Num = 0
+ self.IsAll = false
+ self.IsFridge = false
+ self:SetText( "" )
+end
+
+function PANEL:Paint()
+ if ( self:GetDisabled() ) then
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 50, 50, 50, 255 ) )
+ elseif ( self.Depressed /*|| self:GetSelected()*/ ) then
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 50, 50, 176, 255 ) )
+ elseif ( self.Hovered ) then
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 255, 255 ) )
+ else
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 100, 255 ) )
+ end
+
+ if ( self.IsFridge ) then
+ draw.SimpleText( "Take", "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ elseif ( self.IsAll ) then
+ draw.SimpleText( "Take All", "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ else
+ draw.SimpleText( "Take X", "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ end
+end
+
+function PANEL:DoClick()
+ if ( self.IsAll ) then
+ RunConsoleCommand( "gms_TakeResources", string.gsub( self.Text, " ", "_" ), self.Num )
+ if ( self.IsFridge ) then self:GetParent():GetParent():GetParent():GetParent():Close() return end
+ else
+ local res = self.Text
+ Derma_StringRequest( "Please enter amount", "Please enter amount of " .. res .. " to take.", "", function( text )
+ RunConsoleCommand( "gms_TakeResources", string.gsub( res, " ", "_" ), text )
+ end )
+ end
+end
+
+function PANEL:SetRes( str, num, isAll, isFridge )
+ self.Text = str
+ self.Num = num
+ self.IsAll = isAll
+ self.IsFridge = isFridge
+end
+
+vgui.Register( "gms_takeButton", PANEL, "DButton" )
+
+// Store Line
+local PANEL = {}
+
+function PANEL:Init()
+ self.Text = ""
+ self.Num = 0
+
+ self.StoreX = vgui.Create( "gms_StoreButton", self )
+ self.StoreAll = vgui.Create( "gms_StoreButton", self )
+end
+
+function PANEL:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 176, 176, 176, 255 ) )
+ draw.SimpleText( string.Replace( self.Text, "_", " " ) .. ": " .. self.Num, "DefaultBold", 5, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 0, 1 )
+end
+
+function PANEL:SetRes( str, num )
+ self.Text = str
+ self.Num = num
+
+ self.StoreX:SetRes( str, nil )
+ self.StoreAll:SetRes( str, num, true )
+end
+
+function PANEL:PerformLayout()
+ self.StoreAll:SetSize( 64, self:GetTall() - 4 )
+ self.StoreAll:SetPos( self:GetWide() - 66, 2 )
+
+ self.StoreX:SetSize( 64, self:GetTall() - 4 )
+ self.StoreX:SetPos( self:GetWide() - 132, 2 )
+end
+
+vgui.Register( "gms_resourceLineStore", PANEL, "Panel" )
+
+// Store button
+local PANEL = {}
+
+function PANEL:Init()
+ self.Text = ""
+ self.Num = 0
+ self.IsAll = false
+ self:SetText( "" )
+end
+
+function PANEL:Paint()
+ if ( self:GetDisabled() ) then
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 50, 50, 50, 255 ) )
+ elseif ( self.Depressed /*|| self:GetSelected()*/ ) then
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 50, 50, 176, 255 ) )
+ elseif ( self.Hovered ) then
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 255, 255 ) )
+ else
+ draw.RoundedBox( 0, 0, 0, self:GetWide(), self:GetTall(), Color( 100, 100, 100, 255 ) )
+ end
+
+ if ( self.IsAll ) then
+ draw.SimpleText( "Store All", "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ else
+ draw.SimpleText( "Store X", "DefaultBold", self:GetWide() / 2, self:GetTall() / 2 - 1, Color( 255, 255, 255, 255 ), 1, 1 )
+ end
+end
+
+function PANEL:DoClick()
+ if ( self.IsAll ) then
+ RunConsoleCommand( "gms_DropResources", string.gsub( self.Text, " ", "_" ), self.Num )
+ else
+ local res = self.Text
+ Derma_StringRequest( "Please enter amount", "Please enter amount of " .. res .. " to store.", "", function( text )
+ RunConsoleCommand( "gms_DropResources", string.gsub( res, " ", "_" ), text )
+ end )
+ end
+end
+function PANEL:SetRes( str, num, isAll )
+ self.Text = str
+ self.Num = num
+ self.IsAll = isAll
+end
+
+vgui.Register( "gms_StoreButton", PANEL, "DButton" ) \ No newline at end of file
diff --git a/ftp_gmstranded/gamemode/cl_qmenu.lua b/ftp_gmstranded/gamemode/cl_qmenu.lua
new file mode 100644
index 0000000..2a6d248
--- /dev/null
+++ b/ftp_gmstranded/gamemode/cl_qmenu.lua
@@ -0,0 +1,989 @@
+
+/* ToolMenuButton */
+local PANEL = {}
+
+AccessorFunc( PANEL, "m_bAlt", "Alt" )
+AccessorFunc( PANEL, "m_bSelected", "Selected" )
+
+function PANEL:Init()
+ self:SetContentAlignment( 4 )
+ self:SetTextInset( 5, 0 )
+ self:SetTall( 15 )
+end
+
+function PANEL:Paint()
+ if ( !self.m_bSelected ) then
+ if ( !self.m_bAlt ) then
+ surface.SetDrawColor( Color( 255, 255, 255, 200 ) )
+ else
+ surface.SetDrawColor( Color( 255, 255, 255, 150 ) )
+ end
+ else
+ surface.SetDrawColor( Color( 50, 150, 255, 250 ) )
+ end
+
+ self:DrawFilledRect()
+end
+
+function PANEL:OnMousePressed( mcode )
+ if ( mcode == MOUSE_LEFT ) then
+ self:OnSelect()
+ end
+end
+
+function PANEL:OnCursorMoved( x, y )
+ if ( input.IsMouseDown( MOUSE_LEFT ) ) then
+ self:OnSelect()
+ end
+end
+
+function PANEL:OnSelect()
+end
+
+function PANEL:PerformLayout()
+ if ( self.Checkbox ) then
+ self.Checkbox:AlignRight( 4 )
+ self.Checkbox:CenterVertical()
+ end
+end
+
+function PANEL:AddCheckBox( strConVar )
+ if ( !self.Checkbox ) then
+ self.Checkbox = vgui.Create( "DCheckBox", self )
+ end
+
+ self.Checkbox:SetConVar( strConVar )
+ self:InvalidateLayout()
+end
+
+vgui.Register( "ToolMenuButton", PANEL, "DButton" )
+
+/* DPropSpawnMenu */
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetSpacing( 5 )
+ self:SetPadding( 5 )
+ self:EnableHorizontal( false )
+ self:EnableVerticalScrollbar( true )
+ function self:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ for k, v in SortedPairs( GMS_SpawnLists ) do
+ local cat = vgui.Create( "DCollapsibleCategory", self )
+ cat:SetExpanded( 0 )
+ cat:SetLabel( k )
+
+ local IconList = vgui.Create( "DPanelList", cat )
+ IconList:EnableVerticalScrollbar( true )
+ IconList:EnableHorizontal( true )
+ IconList:SetAutoSize( true )
+ IconList:SetSpacing( 5 )
+ IconList:SetPadding( 5 )
+
+ cat:SetContents( IconList )
+ self:AddItem( cat )
+
+ for key, value in pairs( v ) do
+ local Icon = vgui.Create( "SpawnIcon", IconList )
+ Icon:SetModel( value )
+ Icon.DoClick = function( Icon ) RunConsoleCommand( "gm_spawn", value, 0 ) end
+ --Icon:SetIconSize( 64 )
+ Icon:InvalidateLayout( true )
+ Icon:SetToolTip( Format( "%s", value ) )
+ IconList:AddItem( Icon )
+ end
+ end
+end
+
+vgui.Register( "stranded_propspawn", PANEL, "DPanelList" )
+
+/* DToolMenu */
+local PANEL = {}
+
+function PANEL:Init()
+ self.Tools = vgui.Create( "DPanelList", self )
+ self.Tools:EnableVerticalScrollbar( true )
+ self.Tools:SetAutoSize( false )
+ self.Tools:SetSpacing( 5 )
+ self.Tools:SetPadding( 5 )
+ function self.Tools:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ self.ContextPanel = vgui.Create( "DPanelList", self )
+ self.ContextPanel:EnableVerticalScrollbar( false )
+ self.ContextPanel:SetSpacing( 0 )
+ self.ContextPanel:SetPadding( 5 )
+ function self.ContextPanel:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 255, 255, 255, 150 ) )
+ end
+
+ if ( ToolsLoad == false || ToolsLoad == nil || ToolsLoad == NULL || ToolsLoad == "" ) then
+ AllTools = spawnmenu.GetTools()
+ local ToolsLoad = true
+ end
+
+ local ToolTables = AllTools
+
+ if ( !ToolTables ) then LocalPlayer():ChatPrint( "ERROR: Tools List could not be loaded." ) return end
+
+ for k, v in pairs( ToolTables[1].Items ) do
+ if ( type( v ) == "table" ) then
+ local Name = v.ItemName
+ local Label = v.Text
+ v.ItemName = nil
+ v.Text = nil
+ self:AddCategory( Name, Label, v )
+ end
+ end
+end
+
+function PANEL:AddCategory( Name, Label, ToolItems )
+ self.Category = vgui.Create( "DCollapsibleCategory" )
+ self.Tools:AddItem( self.Category )
+ self.Category:SetLabel( Label )
+ self.Category:SetCookieName( "ToolMenu." .. tostring( Name ) )
+
+ self.CategoryContent = vgui.Create( "DPanelList" )
+ self.CategoryContent:SetAutoSize( true )
+ self.CategoryContent:SetDrawBackground( false )
+ self.CategoryContent:SetSpacing( 0 )
+ self.CategoryContent:SetPadding( 0 )
+ self.Category:SetContents( self.CategoryContent )
+
+ local bAlt = true
+ local NumTools = 0
+
+ for k, v in pairs( ToolItems ) do
+ if ( table.HasValue( GMS.ProhibitedStools, v.ItemName ) && !LocalPlayer():IsAdmin() ) then continue end
+ NumTools = NumTools + 1
+
+ local Item = vgui.Create( "ToolMenuButton", self )
+ Item:SetText( v.Text )
+ Item.OnSelect = function( button ) self:EnableControlPanel( button ) end
+ concommand.Add( Format( "tool_%s", v.ItemName ), function() Item:OnSelect() end )
+
+ if ( v.SwitchConVar ) then
+ Item:AddCheckBox( v.SwitchConVar )
+ end
+
+ Item.ControlPanelBuildFunction = v.CPanelFunction
+ Item.Command = v.Command
+ Item.Name = v.ItemName
+ Item.Controls = v.Controls
+ Item.Text = v.Text
+
+ Item:SetAlt( bAlt )
+ bAlt = !bAlt
+
+ self.CategoryContent:AddItem( Item )
+ end
+
+ if ( NumTools <= 0 ) then
+ self.Category:Remove()
+ self.CategoryContent:Remove()
+ end
+end
+
+function PANEL:EnableControlPanel( button )
+ if ( self.LastSelected ) then
+ self.LastSelected:SetSelected( false )
+ end
+
+ button:SetSelected( true )
+ self.LastSelected = button
+
+ local cp = controlpanel.Get( button.Name )
+ if ( !cp:GetInitialized() ) then
+ cp:FillViaTable( button )
+ end
+
+ self.ContextPanel:Clear()
+ self.ContextPanel:AddItem( cp )
+ self.ContextPanel:Rebuild()
+
+ g_ActiveControlPanel = cp
+
+ if ( button.Command ) then
+ LocalPlayer():ConCommand( button.Command )
+ end
+end
+
+function PANEL:Paint()
+end
+
+function PANEL:PerformLayout()
+ self:StretchToParent( 0, 21, 0, 5 )
+ self.Tools:SetPos( 5, 5 )
+ self.Tools:SetSize( self:GetWide() * 0.35, self:GetTall() - 5 )
+ self.ContextPanel:SetPos( self:GetWide() * 0.35 + 10, 5 )
+ self.ContextPanel:SetSize( self:GetWide() - ( self:GetWide() * 0.35 ) - 14, self:GetTall() - 5 )
+end
+
+vgui.Register( "stranded_toolmenu", PANEL, "DPanel" )
+
+/* DCommandsMenu */
+local PANEL = {}
+
+PANEL.SmallButs = {}
+PANEL.SmallButs["Sleep"] = "gms_sleep"
+PANEL.SmallButs["Wake up"] = "gms_wakeup"
+PANEL.SmallButs["Drop weapon"] = "gms_dropweapon"
+PANEL.SmallButs["Steal"] = "gms_steal"
+PANEL.SmallButs["Make campfire"] = "gms_makefire"
+PANEL.SmallButs["Drink bottle of water"] = "gms_drinkbottle"
+PANEL.SmallButs["Take medicine"] = "gms_takemedicine"
+PANEL.SmallButs["Combinations"] = "gms_combinations"
+PANEL.SmallButs["Structures"] = "gms_structures"
+PANEL.SmallButs["Help"] = "gms_help"
+PANEL.SmallButs["Drop all resources"] = "gms_dropall"
+PANEL.SmallButs["Salvage prop"] = "gms_salvage"
+PANEL.SmallButs["Eat some berries"] = "gms_eatberry"
+PANEL.SmallButs["RESET CHARACTER"] = "gms_resetcharacter"
+
+PANEL.BigButs = {}
+PANEL.BigButs["Tribe: Create"] = "gms_tribemenu"
+PANEL.BigButs["Tribe: Join"] = "gms_tribes"
+PANEL.BigButs["Tribe: Leave"] = "gms_leave"
+PANEL.BigButs["Save character"] = "gms_savecharacter"
+
+PANEL.Plantables = {}
+PANEL.Plantables["Plant Melon"] = "gms_plantmelon"
+PANEL.Plantables["Plant Banana"] = "gms_plantbanana"
+PANEL.Plantables["Plant Orange"] = "gms_plantorange"
+PANEL.Plantables["Plant Tree"] = "gms_planttree"
+PANEL.Plantables["Plant Grain"] = "gms_plantgrain"
+PANEL.Plantables["Plant BerryBush"] = "gms_plantbush"
+
+function PANEL:Init()
+
+ self.SmallButtons = vgui.Create( "DPanelList", self )
+ self.SmallButtons:EnableVerticalScrollbar( true )
+ self.SmallButtons:SetSpacing( 5 )
+ self.SmallButtons:SetPadding( 5 )
+ function self.SmallButtons:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ for txt, cmd in SortedPairs( self.SmallButs ) do
+ local button = vgui.Create( "gms_CommandButton" )
+ button:SetConCommand( cmd )
+ button:SetText( txt )
+ button:SetTall( 26 )
+ self.SmallButtons:AddItem( button )
+ end
+
+ self.BigButtons = vgui.Create( "DPanelList", self )
+ self.BigButtons:EnableVerticalScrollbar( false )
+ self.BigButtons:SetAutoSize( false )
+ self.BigButtons:SetSpacing( 5 )
+ self.BigButtons:SetPadding( 5 )
+ function self.BigButtons:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ for txt, cmd in SortedPairs( self.BigButs ) do
+ local button = vgui.Create( "gms_CommandButton" )
+ button:SetConCommand( cmd )
+ button:SetText( txt )
+ button:SetTall( 64 )
+ self.BigButtons:AddItem( button )
+ end
+
+ self.Planting = vgui.Create( "DPanelList", self )
+ self.Planting:EnableVerticalScrollbar( false )
+ self.Planting:SetSpacing( 5 )
+ self.Planting:SetPadding( 5 )
+ function self.Planting:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ for txt, cmd in SortedPairs( self.Plantables ) do
+ local button = vgui.Create( "gms_CommandButton" )
+ button:SetConCommand( cmd )
+ button:SetText( txt )
+ button:SetTall( 26 )
+ self.Planting:AddItem( button )
+ end
+end
+
+function PANEL:Paint()
+end
+
+function PANEL:PerformLayout()
+ self:StretchToParent( 0, 21, 0, 5 )
+ self.SmallButtons:SetPos( 5, 5 )
+ self.SmallButtons:SetSize( self:GetWide() * 0.45, self:GetTall() - 5 )
+
+ self.BigButtons:SetPos( self:GetWide() * 0.45 + 10, 5 )
+ self.BigButtons:SetSize( self:GetWide() - ( self:GetWide() * 0.45 ) - 14, self:GetTall() / 2 - 5 )
+
+ self.Planting:SetPos( self:GetWide() * 0.45 + 10, self:GetTall() / 2 + 5 )
+ self.Planting:SetSize( self:GetWide() - ( self:GetWide() * 0.45 ) - 14, self:GetTall() / 2 - 5 )
+end
+
+vgui.Register( "stranded_commands", PANEL, "DPanel" )
+
+/* DSPP Menu */
+local PANEL = {}
+
+PANEL.LastThink = CurTime()
+PANEL.Settings = {
+ { text = "Enable Prop Protection", elem = "DCheckBoxLabel", cmd = "spp_enabled" },
+ { text = "Enable use key protection", elem = "DCheckBoxLabel", cmd = "spp_use" },
+ { text = "Enable entity damage protection", elem = "DCheckBoxLabel", cmd = "spp_entdmg" },
+ { text = "", elem = "DLabel" },
+ { text = "Admins can touch other player props", elem = "DCheckBoxLabel", cmd = "spp_admin" },
+ { text = "Admins can touch world props", elem = "DCheckBoxLabel", cmd = "spp_admin_wp" },
+ { text = "", elem = "DLabel" },
+ { text = "Delete disconnected admins entities", elem = "DCheckBoxLabel", cmd = "spp_del_adminprops" },
+ { text = "Delete disconnected players entities", elem = "DCheckBoxLabel", cmd = "spp_del_disconnected" },
+ { text = "Deletion delay in seconds", elem = "DNumSlider", cmd = "spp_del_delay", min = 10, max = 600 },
+}
+
+function PANEL:Init()
+ if ( !LocalPlayer():IsAdmin() ) then
+ self.Settings = {
+ { text = "You are not an admin.", elem = "DLabel" }
+ }
+ end
+
+ self.Buddies = vgui.Create( "DPanelList", self )
+ self.Buddies:EnableVerticalScrollbar( true )
+ self.Buddies:SetSpacing( 5 )
+ self.Buddies:SetPadding( 5 )
+ function self.Buddies:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ self.AdminSettings = vgui.Create( "DPanelList", self )
+ self.AdminSettings:EnableVerticalScrollbar( true )
+ self.AdminSettings:SetSpacing( 5 )
+ self.AdminSettings:SetPadding( 5 )
+ function self.AdminSettings:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ self.AdminCleanUp = vgui.Create( "DPanelList", self )
+ self.AdminCleanUp:EnableVerticalScrollbar( true )
+ self.AdminCleanUp:SetSpacing( 5 )
+ self.AdminCleanUp:SetPadding( 5 )
+ function self.AdminCleanUp:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ /* Admin settings */
+ for txt, t in pairs( self.Settings ) do
+ local item = vgui.Create( t.elem )
+ item:SetText( t.text )
+
+ if ( t.elem != "DLabel" ) then
+ item:SetConVar( t.cmd )
+ end
+
+ if ( t.elem == "DNumSlider" ) then
+ item:SetMin( t.min )
+ item:SetMax( t.max )
+ item:SetDecimals( 0 )
+ item.TextArea:SetTextColor( Color( 200, 200, 200 ) )
+ end
+
+ self.AdminSettings:AddItem( item )
+ end
+
+ /* Admin cleanup */
+ for i, p in pairs( player.GetAll() ) do
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_cleanup_props", p:GetNWString( "SPPSteamID" ) )
+ item:SetText( p:Name() )
+ item:SetTall( 26 )
+ self.AdminCleanUp:AddItem( item )
+ end
+
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_cleanup_props_left" )
+ item:SetText( "Cleanup disconnected players props" )
+ item:SetTall( 26 )
+ self.AdminCleanUp:AddItem( item )
+
+ /* Client */
+ for i, p in pairs( player.GetAll() ) do
+ if ( p != LocalPlayer() ) then
+ local item = vgui.Create( "DCheckBoxLabel" )
+
+ local BCommand = "spp_buddy_" .. p:GetNWString( "SPPSteamID" )
+ if ( !LocalPlayer():GetInfo( BCommand ) ) then CreateClientConVar( BCommand, 0, false, true ) end
+ item:SetConVar( BCommand )
+ item:SetText( p:Name() )
+ item:SetTextColor( Color( 255, 255, 255, 255 ) )
+ self.Buddies:AddItem( item )
+ end
+ end
+
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_apply_buddies" )
+ item:SetText( "Apply settings" )
+ item:SetTall( 26 )
+ self.Buddies:AddItem( item )
+
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_clear_buddies" )
+ item:SetText( "Clear all buddies" )
+ item:SetTall( 26 )
+ self.Buddies:AddItem( item )
+end
+
+function PANEL:Paint()
+end
+
+function PANEL:Think()
+ if ( CurTime() >= self.LastThink + 3 )then
+ self.LastThink = CurTime()
+ self.AdminCleanUp:Clear( true )
+ self.Buddies:Clear( true )
+
+ /* Admin cleanup */
+ if ( LocalPlayer():IsAdmin() ) then
+ for i, p in pairs( player.GetAll() ) do
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_cleanup_props", p:GetNWString( "SPPSteamID" ) )
+ item:SetTall( 26 )
+ item:SetText( p:Name() )
+ self.AdminCleanUp:AddItem( item )
+ end
+
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_cleanup_props_left" )
+ item:SetTall( 26 )
+ item:SetText( "Cleanup disconnected players props" )
+ self.AdminCleanUp:AddItem( item )
+
+ self.AdminSettings:SetVisible( true )
+ self.AdminCleanUp:SetVisible( true )
+ else
+ local item = vgui.Create( "DLabel" )
+ item:SetText( "You are not an admin." )
+ self.AdminCleanUp:AddItem( item )
+
+ self.AdminSettings:SetVisible( false )
+ self.AdminCleanUp:SetVisible( false )
+ end
+
+ /* Client */
+ for i, p in pairs( player.GetAll() ) do
+ if ( p != LocalPlayer() ) then
+ local item = vgui.Create( "DCheckBoxLabel" )
+
+ local BCommand = "spp_buddy_" .. p:GetNWString( "SPPSteamID" )
+ if ( !LocalPlayer():GetInfo( BCommand ) ) then CreateClientConVar( BCommand, 0, false, true ) end
+ item:SetConVar( BCommand )
+ item:SetText( p:Name() )
+ self.Buddies:AddItem( item )
+ end
+ end
+
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_apply_buddies" )
+ item:SetText( "Apply settings" )
+ item:SetTall( 26 )
+ self.Buddies:AddItem( item )
+
+ local item = vgui.Create( "DButton" )
+ item:SetConsoleCommand( "spp_clear_buddies" )
+ item:SetText( "Clear all buddies" )
+ item:SetTall( 26 )
+ self.Buddies:AddItem( item )
+ end
+end
+
+function PANEL:PerformLayout()
+ self:StretchToParent( 0, 21, 0, 5 )
+
+ self.Buddies:SetPos( 5, 5 )
+ self.Buddies:SetSize( self:GetWide() * 0.45, self:GetTall() - 5 )
+
+ self.AdminSettings:SetPos( self:GetWide() * 0.45 + 10, 5 )
+ self.AdminSettings:SetSize( self:GetWide() - ( self:GetWide() * 0.45 ) - 14, self:GetTall() / 2 - 5 )
+
+ self.AdminCleanUp:SetPos( self:GetWide() * 0.45 + 10, self:GetTall() / 2 + 5 )
+ self.AdminCleanUp:SetSize( self:GetWide() - ( self:GetWide() * 0.45 ) - 14, self:GetTall() / 2 - 5 )
+end
+
+vgui.Register( "stranded_sppmenu", PANEL, "DPanel" )
+
+/* Admin Menu */
+local PANEL = {}
+
+PANEL.SpawningCmds = {
+ { text = "Spawn tree", cmd = "gms_admin_maketree" },
+ { text = "Spawn rock", cmd = "gms_admin_makerock" },
+ { text = "Spawn food", cmd = "gms_admin_makefood" },
+ { text = "Save all characters", cmd = "gms_admin_saveallcharacters" },
+ { text = "Plant random plant", cmd = "gms_admin_makeplant" },
+ { text = "Plant melons", cmd = "gms_admin_makeplant 1" },
+ { text = "Plant banana tree", cmd = "gms_admin_makeplant 2" },
+ { text = "Plant oranges", cmd = "gms_admin_makeplant 3" },
+ { text = "Plant berry bush", cmd = "gms_admin_makeplant 4" },
+ { text = "Plant grain", cmd = "gms_admin_makeplant 5" }
+}
+
+PANEL.Settings = {
+ { text = "Force players to use Tribe color", elem = "DCheckBoxLabel", cmd = "gms_TeamColors" },
+ { text = "Allow players to damage each other with tools", elem = "DCheckBoxLabel", cmd = "gms_PVPDamage" },
+ { text = "Enable free build for everyone", elem = "DCheckBoxLabel", cmd = "gms_FreeBuild" },
+ { text = "Enable free build for super admins", elem = "DCheckBoxLabel", cmd = "gms_FreeBuildSa" },
+ { text = "Give all players all tools", elem = "DCheckBoxLabel", cmd = "gms_AllTools" },
+ //{ text = "Enable low needs alerts ( coughing, etc )", elem = "DCheckBoxLabel", cmd = "gms_alerts" },
+ { text = "Spread fire", elem = "DCheckBoxLabel", cmd = "gms_SpreadFire" },
+ { text = "Fadeout rocks, just like trees", elem = "DCheckBoxLabel", cmd = "gms_FadeRocks" },
+ { text = "Enable campfires", elem = "DCheckBoxLabel", cmd = "gms_campfire" },
+ { text = "Spawn zombies at night", elem = "DCheckBoxLabel", cmd = "gms_zombies" },
+ { text = "Enable day/night cycle", elem = "DCheckBoxLabel", cmd = "gms_daynight" },
+ //{ text = "Costs scale", elem = "DNumSlider", decimals = 1, cmd = "gms_CostsScale", min = 1, max = 4 },
+ { text = "Plant limit per player", elem = "DNumSlider", cmd = "gms_PlantLimit", min = 10, max = 35 },
+ { text = "", elem = "DLabel" },
+ { text = "Reproduce trees", elem = "DCheckBoxLabel", cmd = "gms_ReproduceTrees" },
+ { text = "Max reproduced trees", elem = "DNumSlider", cmd = "gms_MaxReproducedTrees", min = 1, max = 60 },
+ { text = "", elem = "DLabel" },
+ { text = "Autosave user profiles", elem = "DCheckBoxLabel", cmd = "gms_AutoSave" },
+ { text = "Autosave delay ( minutes )", elem = "DNumSlider", cmd = "gms_AutoSaveTime", min = 1, max = 30 },
+}
+
+function PANEL:Init()
+
+ self.MapSaving = vgui.Create( "DPanelList", self )
+ self.MapSaving:EnableVerticalScrollbar( true )
+ self.MapSaving:SetSpacing( 5 )
+ self.MapSaving:SetPadding( 5 )
+ function self.MapSaving:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ self.Populating = vgui.Create( "DPanelList", self )
+ self.Populating:EnableVerticalScrollbar( true )
+ self.Populating:SetSpacing( 5 )
+ self.Populating:SetPadding( 5 )
+ function self.Populating:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ self.AdminSettings = vgui.Create( "DPanelList", self )
+ self.AdminSettings:EnableVerticalScrollbar( true )
+ self.AdminSettings:SetSpacing( 5 )
+ self.AdminSettings:SetPadding( 5 )
+ function self.AdminSettings:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ self.Spawning = vgui.Create( "DPanelList", self )
+ self.Spawning:EnableVerticalScrollbar( true )
+ self.Spawning:SetSpacing( 5 )
+ self.Spawning:SetPadding( 5 )
+ function self.Spawning:Paint()
+ draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 75, 75, 75 ) )
+ end
+
+ for txt, t in pairs( self.Settings ) do
+ local item = vgui.Create( t.elem )
+ item:SetText( t.text )
+
+ if ( t.elem == "DNumSlider" ) then
+ item:SetMin( t.min )
+ item:SetMax( t.max )
+ item:SetDecimals( t.decimals or 0 )
+ item.TextArea:SetTextColor( Color( 200, 200, 200 ) )
+ end
+
+ if ( t.elem != "DLabel" ) then item:SetConVar( t.cmd ) end
+
+ self.AdminSettings:AddItem( item )
+ end
+
+ for txt, t in pairs( self.SpawningCmds ) do
+ local item = vgui.Create( "DButton" )
+ item:SetText( t.text )
+ item:SetTall( 26 )
+ item:SetConsoleCommand( t.cmd )
+ self.Spawning:AddItem( item )
+ end
+
+ // POPULATE AREA
+ local populatearea = vgui.Create( "DPanel", self )
+ populatearea:SetTall( 100 )
+
+ local label = vgui.Create( "DLabel", populatearea )
+ label:SetPos( 10, 5 )
+ label:SetDark( true )
+ label:SetText( "Amount" )
+ label:SizeToContents()
+
+ self.PopulateAmount = vgui.Create( "DTextEntry", populatearea )
+ self.PopulateAmount:SetPos( 10, 20 )
+ self.PopulateAmount:SetTall( 24 )
+ self.PopulateAmount:SetValue( "10" )
+ populatearea.PopulateAmount = self.PopulateAmount
+
+ local label = vgui.Create( "DLabel", populatearea )
+ label:SetDark( true )
+ label:SetText( "Max radius" )
+ label:SizeToContents()
+
+ self.PopulateRadius = vgui.Create( "DTextEntry", populatearea )
+ self.PopulateRadius:SetValue( "1000" )
+ self.PopulateRadius:SetTall( 24 )
+ self.PopulateRadius.Label = label
+ populatearea.PopulateRadius = self.PopulateRadius
+
+ local label = vgui.Create( "DLabel", populatearea )
+ label:SetPos( 10, 49 )
+ label:SetDark( true )
+ label:SetText( "Type" )
+ label:SizeToContents()
+
+ local typ = "Trees"
+ self.PopulateType = vgui.Create( "DComboBox", populatearea )
+ self.PopulateType:SetTall( 24 )
+ self.PopulateType:SetPos( 10, 64 )
+ self.PopulateType:AddChoice( "Trees", "Trees" )
+ self.PopulateType:AddChoice( "Rocks", "Rocks" )
+ self.PopulateType:AddChoice( "Random plants", "Random_Plant" )
+ self.PopulateType:ChooseOptionID( 1 )
+ function self.PopulateType:OnSelect( index, value, data ) typ = data end
+
+ self.PopulateArea = vgui.Create( "gms_CommandButton", populatearea )
+ self.PopulateArea:SetTall( 24 )
+ self.PopulateArea:SetText( "Populate Area" )
+ function self.PopulateArea:DoClick()
+ local p = self:GetParent()
+ RunConsoleCommand( "gms_admin_PopulateArea", typ, string.Trim( p.PopulateAmount:GetValue() ), string.Trim( p.PopulateRadius:GetValue() ) )
+ end
+
+ self.Populating:AddItem( populatearea )
+
+ // POPULATE AREA: Antlions
+ local populatearea = vgui.Create( "DPanel", self )
+ populatearea:SetTall( 54 )
+
+ local label = vgui.Create( "DLabel", populatearea )
+ label:SetPos( 10, 5 )
+ label:SetDark( true )
+ label:SetText( "Amount" )
+ label:SizeToContents()
+
+ self.PopulateAmountAnt = vgui.Create( "DTextEntry", populatearea )
+ self.PopulateAmountAnt:SetPos( 10, 20 )
+ self.PopulateAmountAnt:SetTall( 24 )
+ self.PopulateAmountAnt:SetValue( "5" )
+ populatearea.PopulateAmountAnt = self.PopulateAmountAnt
+
+ self.PopulateAreaAnt = vgui.Create( "gms_CommandButton", populatearea )
+ self.PopulateAreaAnt:SetTall( 24 )
+ self.PopulateAreaAnt:SetText( "Make Antlion Barrow" )
+ function self.PopulateAreaAnt:DoClick()
+ RunConsoleCommand( "gms_admin_MakeAntlionBarrow", string.Trim( self:GetParent().PopulateAmountAnt:GetValue() ) )
+ end
+
+ self.Populating:AddItem( populatearea )
+
+ // Save map
+ local populatearea = vgui.Create( "DPanel", self )
+ populatearea:SetTall( 64 )
+
+ self.MapName = vgui.Create( "DTextEntry", populatearea )
+ self.MapName:SetPos( 5, 5 )
+ self.MapName:SetTall( 24 )
+ self.MapName:SetValue( "savename" )
+ populatearea.MapName = self.MapName
+
+ self.SaveMap = vgui.Create( "gms_CommandButton", populatearea )
+ self.SaveMap:SetPos( 5, 34 )
+ self.SaveMap:SetTall( 24 )
+ self.SaveMap:SetText( "Save" )
+ function self.SaveMap:DoClick()
+ RunConsoleCommand( "gms_admin_savemap", string.Trim( self:GetParent().MapName:GetValue() ) )
+ end
+
+ self.MapSaving:AddItem( populatearea )
+
+ // Load/delete map
+ local populatearea = vgui.Create( "DPanel", self )
+ populatearea:SetTall( 64 )
+
+ local map = ""
+ self.MapNameL = vgui.Create( "DComboBox", populatearea )
+ self.MapNameL:SetTall( 24 )
+ self.MapNameL:SetPos( 5, 5 )
+ function self.MapNameL:OnSelect( index, value, data ) map = data end
+ populatearea.MapNameL = self.MapNameL
+
+ self.LoadMap = vgui.Create( "gms_CommandButton", populatearea )
+ self.LoadMap:SetPos( 5, 34 )
+ self.LoadMap:SetTall( 24 )
+ self.LoadMap:SetText( "Load" )
+ function self.LoadMap:DoClick()
+ RunConsoleCommand( "gms_admin_loadmap", string.Trim( map ) )
+ end
+
+ self.DeleteMap = vgui.Create( "gms_CommandButton", populatearea )
+ self.DeleteMap:SetTall( 24 )
+ self.DeleteMap:SetText( "Delete" )
+ function self.DeleteMap:DoClick()
+ RunConsoleCommand( "gms_admin_deletemap", map )
+ end
+
+ self.MapSaving:AddItem( populatearea )
+
+end
+
+function PANEL:Paint()
+end
+
+function PANEL:PerformLayout()
+ self:StretchToParent( 0, 21, 0, 5 )
+
+ self.MapSaving:SetPos( 5, 5 )
+ self.MapSaving:SetSize( self:GetWide() * 0.45, self:GetTall() / 2 - 5 )
+
+ self.Populating:SetPos( 5, self:GetTall() / 2 + 5 )
+ self.Populating:SetSize( self:GetWide() - ( self:GetWide() * 0.45 ) - 14, self:GetTall() / 2 - 5 )
+
+ self.AdminSettings:SetPos( self:GetWide() * 0.45 + 10, 5 )
+ self.AdminSettings:SetSize( self:GetWide() - ( self:GetWide() * 0.45 ) - 14, self:GetTall() / 2 - 5 )
+
+ self.Spawning:SetPos( self:GetWide() - ( self:GetWide() * 0.45 ) - 4, self:GetTall() / 2 + 5 )
+ self.Spawning:SetSize( self:GetWide() * 0.45, self:GetTall() / 2 - 5 )
+
+ /* POPULATION */
+ self.PopulateAmount:SetWide( self.Populating:GetWide() / 2 - 20 )
+ self.PopulateRadius:SetWide( self.Populating:GetWide() / 2 - 20 )
+ self.PopulateRadius.Label:SetPos( self.Populating:GetWide() / 2, 5 )
+ self.PopulateRadius:SetPos( self.Populating:GetWide() / 2, 20 )
+
+ self.PopulateType:SetWide( self.Populating:GetWide() / 2 - 20 )
+ self.PopulateArea:SetWide( self.Populating:GetWide() / 2 - 20 )
+ self.PopulateArea:SetPos( self.Populating:GetWide() / 2, 64 )
+
+ /* ANTLIONS */
+ self.PopulateAmountAnt:SetWide( self.Populating:GetWide() / 2 - 20 )
+ self.PopulateAreaAnt:SetWide( self.Populating:GetWide() / 2 - 20 )
+ self.PopulateAreaAnt:SetPos( self.Populating:GetWide() / 2, 20 )
+
+ // Save map
+ self.MapName:SetWide( self.MapSaving:GetWide() - 20 )
+ self.SaveMap:SetWide( self.MapSaving:GetWide() - 20 )
+
+ // Load/delete map
+ self.MapNameL:SetSize( self.MapSaving:GetWide() - 20, 24 )
+ self.LoadMap:SetWide( self.MapSaving:GetWide() / 2 - 20 )
+ self.DeleteMap:SetWide( self.MapSaving:GetWide() / 2 - 20 )
+ self.DeleteMap:SetPos( self.MapSaving:GetWide() / 2 + 5, 34 )
+end
+
+vgui.Register( "stranded_adminmenu", PANEL, "DPanel" )
+
+/* Spawnpanel */
+local PANEL = {}
+
+function PANEL:Init()
+ self:SetTitle( "" )
+ self:ShowCloseButton( false )
+
+ self.m_bHangOpen = false
+
+ self.ContentPanel = vgui.Create( "DPropertySheet", self )
+ self.ContentPanel:AddSheet( "Props", vgui.Create( "stranded_propspawn", self.ContentPanel ), "icon16/brick.png", false, false )
+ self.ContentPanel:AddSheet( "Tools", vgui.Create( "stranded_toolmenu", self.ContentPanel ), "icon16/wrench.png", true, true )
+ self.ContentPanel:AddSheet( "Commands", vgui.Create( "stranded_commands", self.ContentPanel ), "icon16/application.png", true, true )
+ self.ContentPanel:AddSheet( "Prop Protection", vgui.Create( "stranded_sppmenu", self.ContentPanel ), "icon16/shield.png", true, true )
+
+ self.AdminMenu = vgui.Create( "stranded_adminmenu", self.ContentPanel )
+ local tab = self.ContentPanel:AddSheet( "Admin menu", self.AdminMenu, "icon16/shield_add.png", true, true )
+ self.AdminTab = tab.Tab
+end
+
+function PANEL:Paint()
+end
+
+function PANEL:Think()
+ if ( !LocalPlayer():IsAdmin() ) then
+ /*self.AdminMenu.MapSaving:SetVisible( false )
+ self.AdminMenu.Populating:SetVisible( false )
+ self.AdminMenu.AdminSettings:SetVisible( false )
+ self.AdminMenu.Spawning:SetVisible( false )*/
+ self.AdminTab:SetVisible( false )
+ else
+ /*self.AdminMenu.MapSaving:SetVisible( true )
+ self.AdminMenu.Populating:SetVisible( true )
+ self.AdminMenu.AdminSettings:SetVisible( true )
+ self.AdminMenu.Spawning:SetVisible( true )*/
+ self.AdminTab:SetVisible( true )
+ end
+end
+
+function PANEL:StartKeyFocus( pPanel )
+
+ self.m_pKeyFocus = pPanel
+ self:SetKeyboardInputEnabled( true )
+ self.m_bHangOpen = true
+
+ g_ContextMenu:StartKeyFocus( pPanel )
+
+end
+
+function PANEL:EndKeyFocus( pPanel )
+
+ if ( self.m_pKeyFocus != pPanel ) then return end
+ self:SetKeyboardInputEnabled( false )
+
+ g_ContextMenu:EndKeyFocus( pPanel )
+
+end
+
+function PANEL:PerformLayout()
+ self:SetSize( ScrW() / 2.2 - 10, ScrH() - 10 )
+ self:SetPos( ScrW() - ( ScrW() / 2.2 + 5 ), 5 )
+ self.ContentPanel:StretchToParent( 0, 0, 0, 0 )
+
+ DFrame.PerformLayout( self )
+end
+
+vgui.Register( "gms_menu", PANEL, "DFrame" )
+
+/* Spawn menu override */
+
+local ToAdd = {}
+local function UpdateSavegames()
+ gSpawnMenu.AdminMenu.MapNameL:Clear()
+ for id, st in pairs( ToAdd ) do
+ gSpawnMenu.AdminMenu.MapNameL:AddChoice( st, st, true )
+ end
+end
+
+usermessage.Hook( "gms_AddLoadGameToList", function( um )
+ local str = um:ReadString()
+ if ( table.HasValue( ToAdd, str ) ) then return end
+ table.insert( ToAdd, str )
+
+ if ( !IsValid( gSpawnMenu ) ) then return end
+ UpdateSavegames()
+end )
+
+usermessage.Hook( "gms_RemoveLoadGameFromList", function( um )
+ local str = um:ReadString()
+ for id, st in pairs( ToAdd ) do if ( st == str ) then table.remove( ToAdd, id ) break end end
+
+ if ( !IsValid( gSpawnMenu ) ) then return end
+ UpdateSavegames()
+end )
+
+function GM:OnSpawnMenuOpen()
+ if ( LocalPlayer():GetNWBool( "AFK" ) ) then return end
+
+ if ( !IsValid( gSpawnMenu ) ) then
+ gSpawnMenu = vgui.Create( "gms_menu" )
+ gSpawnMenu:SetVisible( false )
+
+ UpdateSavegames()
+ end
+
+ gSpawnMenu.m_bHangOpen = false
+
+ gSpawnMenu:MakePopup()
+ gSpawnMenu:SetVisible( true )
+ gSpawnMenu:SetKeyboardInputEnabled( false )
+ gSpawnMenu:SetMouseInputEnabled( true )
+ gSpawnMenu:SetAlpha( 255 )
+
+ GAMEMODE.SkillsHud:MakePopup()
+ GAMEMODE.ResourcesHud:MakePopup()
+ GAMEMODE.CommandsHud:MakePopup()
+
+ GAMEMODE.SkillsHud:SetKeyboardInputEnabled( false )
+ GAMEMODE.ResourcesHud:SetKeyboardInputEnabled( false )
+ GAMEMODE.CommandsHud:SetKeyboardInputEnabled( false )
+
+ GAMEMODE.CommandsHud:SetVisible( true )
+
+ gui.EnableScreenClicker( true )
+ RestoreCursorPosition()
+end
+
+function GM:OnSpawnMenuClose()
+ if ( gSpawnMenu.m_bHangOpen ) then
+ gSpawnMenu.m_bHangOpen = false
+ return
+ end
+
+ if ( IsValid( gSpawnMenu ) and gSpawnMenu:IsVisible() ) then
+ gSpawnMenu:SetVisible( false )
+ end
+
+ GAMEMODE.SkillsHud:SetMouseInputEnabled( false )
+ GAMEMODE.ResourcesHud:SetMouseInputEnabled( false )
+ GAMEMODE.CommandsHud:SetMouseInputEnabled( false )
+
+ GAMEMODE.CommandsHud:SetVisible( false )
+
+ RememberCursorPosition()
+ gui.EnableScreenClicker( false )
+end
+
+hook.Add( "OnTextEntryGetFocus", "GMSSpawnMenuKeyboardFocusOn", function( pnl )
+
+ if ( !IsValid( gSpawnMenu ) || !IsValid( g_ContextMenu ) ) then return end
+ if ( IsValid( pnl ) && pnl.HasParent && !pnl:HasParent( gSpawnMenu ) && !pnl:HasParent( g_ContextMenu ) ) then return end
+
+ gSpawnMenu:StartKeyFocus( pnl )
+
+end )
+
+hook.Add( "GUIMousePressed", "GMS_KindaFixWorldClicking", function()
+ GAMEMODE.SkillsHud:MakePopup()
+ GAMEMODE.ResourcesHud:MakePopup()
+ GAMEMODE.CommandsHud:MakePopup()
+
+ GAMEMODE.SkillsHud:SetKeyboardInputEnabled( false )
+ GAMEMODE.ResourcesHud:SetKeyboardInputEnabled( false )
+ GAMEMODE.CommandsHud:SetKeyboardInputEnabled( false )
+end )
+
+hook.Add( "OnTextEntryLoseFocus", "GMSSpawnMenuKeyboardFocusOff", function( pnl )
+
+ if ( !IsValid( gSpawnMenu ) || !IsValid( g_ContextMenu ) ) then return end
+ if ( IsValid( pnl ) && pnl.HasParent && !pnl:HasParent( gSpawnMenu ) && !pnl:HasParent( g_ContextMenu ) ) then return end
+
+ gSpawnMenu:EndKeyFocus( pnl )
+
+end )
+
+function GM:SpawnMenuEnabled()
+ return false
+end
+
+function GM:OnContextMenuOpen()
+ self.BaseClass.OnContextMenuOpen( self )
+ menubar.Control:SetVisible( false )
+
+ GAMEMODE.SkillsHud:MakePopup()
+ GAMEMODE.ResourcesHud:MakePopup()
+ GAMEMODE.CommandsHud:MakePopup()
+
+ GAMEMODE.SkillsHud:SetKeyboardInputEnabled( false )
+ GAMEMODE.ResourcesHud:SetKeyboardInputEnabled( false )
+ GAMEMODE.CommandsHud:SetKeyboardInputEnabled( false )
+
+ GAMEMODE.CommandsHud:SetVisible( true )
+end
+
+function GM:OnContextMenuClose()
+ self.BaseClass.OnContextMenuClose( self )
+ menubar.Control:SetVisible( false )
+
+ GAMEMODE.SkillsHud:SetMouseInputEnabled( false )
+ GAMEMODE.ResourcesHud:SetMouseInputEnabled( false )
+ GAMEMODE.CommandsHud:SetMouseInputEnabled( false )
+
+ GAMEMODE.CommandsHud:SetVisible( false )
+end
diff --git a/ftp_gmstranded/gamemode/cl_scoreboard.lua b/ftp_gmstranded/gamemode/cl_scoreboard.lua
new file mode 100644
index 0000000..e832a4a
--- /dev/null
+++ b/ftp_gmstranded/gamemode/cl_scoreboard.lua
@@ -0,0 +1,231 @@
+
+surface.CreateFont( "ScoreboardText", {
+ font = "Tahoma",
+ size = 16,
+ weight = 1000,
+ antialias = true,
+ additive = false,
+} )
+
+surface.CreateFont( "ScoreboardSub", {
+ font = "coolvetica",
+ size = 24,
+ weight = 500,
+ antialias = true,
+ additive = false,
+} )
+
+surface.CreateFont( "ScoreboardHead", {
+ font = "coolvetica",
+ size = 48,
+ weight = 500,
+ antialias = true,
+ additive = false,
+} )
+
+function GM:ScoreboardShow()
+ GAMEMODE.ShowScoreboard = true
+end
+
+function GM:ScoreboardHide()
+ GAMEMODE.ShowScoreboard = false
+end
+
+function GM:GetTeamScoreInfo()
+ local TeamInfo = {}
+
+ for id, pl in pairs(player.GetAll()) do
+ local _team = pl:Team()
+ local _frags = pl:Frags()
+ local _deaths = pl:Deaths()
+ local _ping = pl:Ping()
+
+ if (!TeamInfo[_team]) then
+ TeamInfo[_team] = {}
+ TeamInfo[_team].TeamName = team.GetName(_team)
+ TeamInfo[_team].Color = team.GetColor(_team)
+ TeamInfo[_team].Players = {}
+ end
+
+ local PlayerInfo = {}
+ PlayerInfo.Frags = _frags
+ PlayerInfo.Deaths = pl:GetNWInt("Survival")
+ PlayerInfo.Score = _frags
+ PlayerInfo.Ping = _ping
+ PlayerInfo.Name = pl:Nick()
+ PlayerInfo.PlayerObj = pl
+
+ if ( pl:IsAdmin() ) then PlayerInfo.Name = "[ADMIN] " .. PlayerInfo.Name end
+ if ( pl:IsDeveloper() ) then PlayerInfo.Name = "[DEVELOPER] " .. pl:Nick() end
+ if ( pl:GetNWBool( "AFK" ) ) then PlayerInfo.Name = PlayerInfo.Name .. " [AFK]" end
+
+ local insertPos = #TeamInfo[_team].Players + 1
+ for idx, info in pairs(TeamInfo[_team].Players) do
+ if (PlayerInfo.Frags > info.Frags) then
+ insertPos = idx
+ break
+ elseif (PlayerInfo.Frags == info.Frags) then
+ if (PlayerInfo.Deaths < info.Deaths) then
+ insertPos = idx
+ break
+ elseif (PlayerInfo.Deaths == info.Deaths) then
+ if (PlayerInfo.Name < info.Name) then
+ insertPos = idx
+ break
+ end
+ end
+ end
+ end
+
+ table.insert( TeamInfo[ _team ].Players, insertPos, PlayerInfo )
+ end
+
+ return TeamInfo
+end
+
+function GM:HUDDrawScoreBoard()
+ if ( !GAMEMODE.ShowScoreboard ) then return end
+
+ if ( !GAMEMODE.ScoreDesign ) then
+ GAMEMODE.ScoreDesign = {}
+ GAMEMODE.ScoreDesign.HeaderY = 0
+ GAMEMODE.ScoreDesign.Height = ScrH() / 2
+ end
+
+ local alpha = 255
+ local ScoreboardInfo = self:GetTeamScoreInfo()
+ local xOffset = ScrW() / 8
+ local yOffset = 32
+ local scrWidth = ScrW()
+ local scrHeight = ScrH() - 64
+ local boardWidth = scrWidth - ( 2 * xOffset )
+ local boardHeight = scrHeight
+ local colWidth = 75
+
+ boardWidth = math.Clamp( boardWidth, 400, 600 )
+ boardHeight = GAMEMODE.ScoreDesign.Height
+
+ xOffset = (ScrW() - boardWidth) / 2.0
+ yOffset = (ScrH() - boardHeight) / 2.0
+ yOffset = yOffset - ScrH() / 4.0
+ yOffset = math.Clamp( yOffset, 32, ScrH() )
+
+ surface.SetDrawColor( 0, 0, 0, 200 )
+ surface.DrawRect( xOffset, yOffset, boardWidth, boardHeight )
+
+ surface.SetDrawColor( 0, 0, 0, 150 )
+ surface.DrawOutlinedRect( xOffset, yOffset, boardWidth, boardHeight )
+
+ surface.SetDrawColor( 0, 0, 0, 50 )
+ //surface.DrawOutlinedRect( xOffset - 1, yOffset - 1, boardWidth + 2, boardHeight + 2 )
+
+ local hostname = GetGlobalString( "ServerName" )
+ local gamemodeName = GAMEMODE.Name .. " - " .. GAMEMODE.Author
+
+ if ( string.len( hostname ) > 32 ) then
+ surface.SetFont("ScoreboardSub")
+ else
+ surface.SetFont("ScoreboardHead")
+ end
+
+ surface.SetTextColor(255, 255, 255, 255)
+ local txWidth, txHeight = surface.GetTextSize( hostname )
+ local y = yOffset + 5
+ surface.SetTextPos(xOffset + (boardWidth / 2) - (txWidth / 2), y)
+ surface.DrawText(hostname)
+
+ /*y = y + txHeight + 2
+
+ surface.SetTextColor(255, 255, 255, 255)
+ surface.SetFont("ScoreboardSub")
+ local txWidth, txHeight = surface.GetTextSize(gamemodeName)
+ surface.SetTextPos(xOffset + (boardWidth / 2) - (txWidth / 2), y)
+ surface.DrawText(gamemodeName)*/
+
+ y = y + txHeight + 4
+ GAMEMODE.ScoreDesign.HeaderY = y - yOffset
+
+ surface.SetDrawColor(0, 0, 0, 100)
+ surface.DrawRect(xOffset, y - 1, boardWidth, 1)
+
+ surface.SetDrawColor(255, 255, 255, 20)
+ surface.DrawRect(xOffset + boardWidth - (colWidth * 1), y, colWidth, boardHeight - y + yOffset)
+
+ surface.SetDrawColor(255, 255, 255, 20)
+ surface.DrawRect(xOffset + boardWidth - (colWidth * 3), y, colWidth, boardHeight - y + yOffset)
+
+ surface.SetFont("ScoreboardText")
+ local txWidth, txHeight = surface.GetTextSize("W")
+
+ surface.SetDrawColor(0, 0, 0, 100)
+ surface.DrawRect(xOffset, y, boardWidth, txHeight + 6)
+
+ y = y + 2
+
+ surface.SetTextPos(xOffset + 16, y)
+ surface.DrawText("#Name")
+ surface.SetTextPos(xOffset + boardWidth - (colWidth * 3) + 8, y)
+ surface.DrawText("#Score")
+ surface.SetTextPos(xOffset + boardWidth - (colWidth * 2) + 8, y)
+ surface.DrawText("Level")
+ surface.SetTextPos(xOffset + boardWidth - (colWidth * 1) + 8, y)
+ surface.DrawText("#Ping")
+
+ y = y + txHeight + 4
+
+ local yPosition = y
+ for team, info in pairs(ScoreboardInfo) do
+ local teamText = info.TeamName .. " (" .. #info.Players .. " Players)"
+
+ surface.SetFont("ScoreboardText")
+ if (info.Color.r < 50 and info.Color.g < 50 and info.Color.b < 50) then surface.SetTextColor(255, 255, 255, 255) else surface.SetTextColor(0, 0, 0, 255) end
+
+ txWidth, txHeight = surface.GetTextSize(teamText)
+ surface.SetDrawColor(info.Color.r, info.Color.g, info.Color.b, 255)
+ surface.DrawRect(xOffset + 1, yPosition, boardWidth - 2, txHeight + 4)
+ yPosition = yPosition + 2
+ surface.SetTextPos(xOffset + boardWidth / 2 - txWidth / 2, yPosition)
+
+ surface.DrawText(teamText)
+ yPosition = yPosition + txHeight + 4
+
+ for index, plinfo in pairs(info.Players) do
+ surface.SetFont("ScoreboardText")
+ surface.SetTextColor(info.Color.r, info.Color.g, info.Color.b, 200)
+ surface.SetTextPos(xOffset + 16, yPosition)
+ txWidth, txHeight = surface.GetTextSize(plinfo.Name)
+
+ if (plinfo.PlayerObj == LocalPlayer()) then
+ surface.SetDrawColor(info.Color.r, info.Color.g, info.Color.b, 64)
+ surface.DrawRect(xOffset + 1, yPosition, boardWidth - 2, txHeight + 2)
+ surface.SetTextColor(info.Color.r, info.Color.g, info.Color.b, 255)
+ end
+
+ local px, py = xOffset + 16, yPosition
+ local textcolor = Color(info.Color.r, info.Color.g, info.Color.b, alpha)
+ local shadowcolor = Color(0, 0, 0, alpha * 0.8)
+
+ draw.SimpleText(plinfo.Name, "ScoreboardText", px + 1, py + 1, shadowcolor)
+ draw.SimpleText(plinfo.Name, "ScoreboardText", px, py, textcolor)
+
+ px = xOffset + boardWidth - (colWidth * 3) + 8
+ draw.SimpleText(plinfo.Frags, "ScoreboardText", px + 1, py + 1, shadowcolor)
+ draw.SimpleText(plinfo.Frags, "ScoreboardText", px, py, textcolor)
+
+ px = xOffset + boardWidth - (colWidth * 2) + 8
+ draw.SimpleText(plinfo.Deaths, "ScoreboardText", px + 1, py + 1, shadowcolor)
+ draw.SimpleText(plinfo.Deaths, "ScoreboardText", px, py, textcolor)
+
+ px = xOffset + boardWidth - (colWidth * 1) + 8
+ draw.SimpleText(plinfo.Ping, "ScoreboardText", px + 1, py + 1, shadowcolor)
+ draw.SimpleText(plinfo.Ping, "ScoreboardText", px, py, textcolor)
+
+ yPosition = yPosition + txHeight + 3
+ end
+ end
+
+ yPosition = yPosition + 1
+
+ GAMEMODE.ScoreDesign.Height = (GAMEMODE.ScoreDesign.Height * 2) + (yPosition - yOffset)
+ GAMEMODE.ScoreDesign.Height = GAMEMODE.ScoreDesign.Height / 3
+end
diff --git a/ftp_gmstranded/gamemode/combinations.lua b/ftp_gmstranded/gamemode/combinations.lua
new file mode 100644
index 0000000..9409f3c
--- /dev/null
+++ b/ftp_gmstranded/gamemode/combinations.lua
@@ -0,0 +1,3358 @@
+
+
+
+GMS.Combinations = {}
+function GMS.RegisterCombi( tbl, group )
+ if ( !GMS.Combinations[ group ] ) then GMS.Combinations[ group ] = {} end
+ GMS.Combinations[ group ][ string.Replace( tbl.Name, " ", "_" ) ] = tbl
+end
+
+/* ------------------------ Combinations ------------------------*/
+
+/* Flour */
+local COMBI = {}
+
+COMBI.Name = "Flour"
+COMBI.Description = "Flour can be used for making dough."
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 1
+COMBI.Req["Grain_Seeds"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Flour"] = 1
+COMBI.Results["Stone"] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Spice */
+local COMBI = {}
+
+COMBI.Name = "Spices"
+COMBI.Description = "Spice can be used for various meals."
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 1
+COMBI.Req["Herbs"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Spices"] = 1
+COMBI.Results["Stone"] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Dough */
+local COMBI = {}
+
+COMBI.Name = "Dough"
+COMBI.Description = "Dough is used for baking."
+
+COMBI.Req = {}
+COMBI.Req["Water_Bottles"] = 1
+COMBI.Req["Flour"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Dough"] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Dough x10 */
+local COMBI = {}
+
+COMBI.Name = "Dough 10x"
+COMBI.Description = "Dough is used for baking."
+
+COMBI.Req = {}
+COMBI.Req["Water_Bottles"] = 7
+COMBI.Req["Flour"] = 15
+
+COMBI.Results = {}
+COMBI.Results["Dough"] = 10
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Rope */
+local COMBI = {}
+
+COMBI.Name = "Rope"
+COMBI.Description = "Allows you to use Rope tool ( Using Rope Tool will consume the Rope ) and used in fishing rod crafting."
+
+COMBI.Req = {}
+COMBI.Req["Herbs"] = 5
+COMBI.Req["Wood"] = 2
+COMBI.Req["Water_Bottles"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Rope"] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Welder */
+local COMBI = {}
+
+COMBI.Name = "Welder"
+COMBI.Description = "Allows you to use Weld Tool. You still need the Tool Gun though."
+
+COMBI.Req = {}
+COMBI.Req[ "Wood" ] = 10
+COMBI.Req[ "Stone" ] = 10
+COMBI.Req[ "Water_Bottles" ] = 1
+
+COMBI.Results = {}
+COMBI.Results[ "Welder" ] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Concrete */
+local COMBI = {}
+
+COMBI.Name = "Concrete"
+COMBI.Description = "Concrete can be used for spawning concrete props."
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 5
+COMBI.Req["Water_Bottles"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Concrete"] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Urine */
+local COMBI = {}
+
+COMBI.Name = "Urine"
+COMBI.Description = "Drink some water and wait, used in gunpowder production."
+
+COMBI.Req = {}
+COMBI.Req["Water_Bottles"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Urine_Bottles"] = 1
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Urine 10x */
+local COMBI = {}
+
+COMBI.Name = "Urine 10x"
+COMBI.Description = "Drink loads of water and wait, messy, but used in gunpowder production."
+
+COMBI.Req = {}
+COMBI.Req["Water_Bottles"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Urine_Bottles"] = 10
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+/* Medicine */
+local COMBI = {}
+
+COMBI.Name = "Medicine"
+COMBI.Description = "To restore your health."
+
+COMBI.Req = {}
+COMBI.Req["Herbs"] = 7
+COMBI.Req["Urine_Bottles"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Medicine"] = 5
+
+GMS.RegisterCombi( COMBI, "Combinations" )
+
+
+/* ------------------------ Structures ------------------------*/
+
+/* Resource Pack */
+local COMBI = {}
+
+COMBI.Name = "Resource Pack"
+COMBI.Description = "You can use the resource pack to store multiple resources in it. Highly recommended."
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 20
+COMBI.Req["Stone"] = 10
+
+COMBI.Results = "gms_resourcepack"
+COMBI.Texture = "gms_icons/gms_resourcepack.png"
+COMBI.BuildSiteModel = "models/items/item_item_crate.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Clock"
+COMBI.Description = "Shows you world time."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 10
+COMBI.Req["Glass"] = 10
+
+COMBI.Results = "gms_clock_big"
+COMBI.Texture = "gms_icons/gms_clock_big.png"
+COMBI.BuildSiteModel = "models/props_trainstation/trainstation_clock001.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Fridge */
+local COMBI = {}
+
+COMBI.Name = "Fridge"
+COMBI.Description = "You can use the fridge to store food in it. It will not spoil inside. Highly recommended."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+
+COMBI.Results = "gms_fridge"
+COMBI.Texture = "gms_icons/gms_fridge.png"
+COMBI.BuildSiteModel = "models/props_c17/FurnitureFridge001a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Stone Workbench */
+local COMBI = {}
+
+COMBI.Name = "Stone Workbench"
+COMBI.Description = "This stone table has various fine specialized equipment used in crafting basic items."
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 15
+COMBI.Req["Stone"] = 25
+
+COMBI.Results = "gms_stoneworkbench"
+COMBI.Texture = "gms_icons/gms_stoneworkbench.png"
+COMBI.BuildSiteModel = "models/props/de_piranesi/pi_merlon.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Copper Workbench */
+local COMBI = {}
+
+COMBI.Name = "Copper Workbench"
+COMBI.Description = "This Copper table has various fine specialized equipment used in crafting quality items."
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 30
+COMBI.Req["Stone"] = 10
+COMBI.Req["Wood"] = 20
+
+COMBI.Results = "gms_copperworkbench"
+COMBI.Texture = "gms_icons/gms_copperworkbench.png"
+COMBI.BuildSiteModel = "models/props_combine/breendesk.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Iron Workbench */
+local COMBI = {}
+
+COMBI.Name = "Iron Workbench"
+COMBI.Description = "This iron table has various fine specialized equipment used in crafting advanced items."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 30
+COMBI.Req["Stone"] = 20
+COMBI.Req["Wood"] = 10
+
+COMBI.Results = "gms_ironworkbench"
+COMBI.Texture = "gms_icons/gms_ironworkbench.png"
+COMBI.BuildSiteModel = "models/props_wasteland/controlroom_desk001b.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Tech Workbench */
+local COMBI = {}
+
+COMBI.Name = "Tech Workbench"
+COMBI.Description = "This tech workbench will help you with all your electronic needs."
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 30
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = "gms_techworkbench"
+COMBI.Texture = "gms_icons/gms_techworkbench.png"
+COMBI.BuildSiteModel = "models/props_lab/reciever_cart.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Silver Workbench */
+local COMBI = {}
+
+COMBI.Name = "Silver Workbench"
+COMBI.Description = "This iron table has various fine specialized equipment used in crafting advanced items."
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = "gms_silverworkbench"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props/de_inferno/bench_concrete.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Gold Workbench */
+local COMBI = {}
+
+COMBI.Name = "Gold Workbench"
+COMBI.Description = "This iron table has various fine specialized equipment used in crafting advanced items."
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 30
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = "gms_goldworkbench"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props/cs_office/file_cabinet1.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Steel Workbench */
+local COMBI = {}
+
+COMBI.Name = "Steel Workbench"
+COMBI.Description = "This iron table has various fine specialized equipment used in crafting advanced items."
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 30
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = "gms_steelworkbench"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props/de_nuke/equipment1.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Platinum Workbench */
+local COMBI = {}
+
+COMBI.Name = "Platinum Workbench"
+COMBI.Description = "This iron table has various fine specialized equipment used in crafting advanced items."
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 30
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = "gms_platinumworkbench"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/xqm/boxfull.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Drinking Fountain */
+local COMBI = {}
+
+COMBI.Name = "Drinking Fountain"
+COMBI.Description = "PORTABLE WATER?!"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 50
+COMBI.Req["Iron"] = 50
+COMBI.Req["Water_Bottles"] = 50
+
+COMBI.Results = "gms_waterfountain"
+COMBI.Texture = "gms_icons/gms_waterfountain.png"
+COMBI.BuildSiteModel = "models/props/de_inferno/fountain.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Stove */
+local COMBI = {}
+
+COMBI.Name = "Stove"
+COMBI.Description = "Using a stove, you can cook without having to light a fire."
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 35
+COMBI.Req["Iron"] = 35
+COMBI.Req["Wood"] = 35
+
+COMBI.Results = "gms_stove"
+COMBI.Texture = "gms_icons/gms_stove.png"
+COMBI.BuildSiteModel = "models/props_c17/furniturestove001a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Stone Furnace */
+local COMBI = {}
+
+COMBI.Name = "Stone Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Copper Ore into Copper."
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 35
+
+COMBI.Results = "gms_stonefurnace"
+COMBI.Texture = "gms_icons/gms_stonefurnace.png"
+COMBI.BuildSiteModel = "models/props/de_inferno/ClayOven.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Copper Furnace */
+local COMBI = {}
+
+COMBI.Name = "Copper Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Iron Ore into Iron."
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 35
+
+COMBI.Results = "gms_copperfurnace"
+COMBI.Texture = "gms_icons/gms_copperfurnace.png"
+COMBI.BuildSiteModel = "models/props/cs_militia/furnace01.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Iron Furnace */
+local COMBI = {}
+
+COMBI.Name = "Iron Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Sand into Glass."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 35
+
+COMBI.Results = "gms_ironfurnace"
+COMBI.Texture = "gms_icons/gms_ironfurnace.png"
+COMBI.BuildSiteModel = "models/props_c17/furniturefireplace001a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Tech Furnace */
+local COMBI = {}
+
+COMBI.Name = "Tech Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Silver Ore into Silver."
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 35
+COMBI.Req["Cedar"] = 35
+
+COMBI.Results = "gms_techfurnace"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props/cs_militia/dryer.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Silver Furnace */
+local COMBI = {}
+
+COMBI.Name = "Silver Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Gold Ore into Gold."
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 35
+COMBI.Req["Maple"] = 35
+
+COMBI.Results = "gms_silverfurnace"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_wasteland/laundry_basket001.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Gold Furnace */
+local COMBI = {}
+
+COMBI.Name = "Gold Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Steel Ore into Steel."
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 35
+
+COMBI.Results = "gms_goldfurnace"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_industrial/oil_storage.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Steel Furnace */
+local COMBI = {}
+
+COMBI.Name = "Steel Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another, such as Platinum Ore into Platinum."
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 35
+COMBI.Req["Mahogany"] = 35
+
+COMBI.Results = "gms_steelfurnace"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_industrial/winch_deck.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Platinum Furnace */
+local COMBI = {}
+
+COMBI.Name = "Platinum Furnace"
+COMBI.Description = "You can use the furnace to smelt resources into another."
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 35
+COMBI.Req["Elm"] = 35
+
+COMBI.Results = "gms_platinumfurnace"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/xeon133/slider/slider_stand_12x12x24.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Grinding Stone */
+local COMBI = {}
+
+COMBI.Name = "Grinding Stone"
+COMBI.Description = "You can use the grinding stone to smash resources into smaller things, such as stone into sand."
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 40
+
+COMBI.Results = "gms_grindingstone"
+COMBI.Texture = "gms_icons/gms_grindingstone.png"
+COMBI.BuildSiteModel = "models/props_combine/combine_mine01.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Factory */
+local COMBI = {}
+
+COMBI.Name = "Factory"
+COMBI.Description = "You can use the factory to smelt resources into another and extract resources out of other resources."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 200
+COMBI.Req["Copper"] = 100
+COMBI.Req["Stone"] = 50
+
+COMBI.Results = "gms_factory"
+COMBI.Texture = "gms_icons/gms_factory.png"
+COMBI.BuildSiteModel = "models/props_c17/factorymachine01.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Pistol Gunlab */
+local COMBI = {}
+
+COMBI.Name = "Pistol Gun Lab"
+COMBI.Description = "For making pistols."
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 150
+COMBI.Req["Cedar"] = 150
+
+COMBI.Results = "gms_pistolgunlab"
+COMBI.Texture = "gms_icons/gms_gunlab.png"
+COMBI.BuildSiteModel = "models/props/cs_militia/gun_cabinet.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* SMG Gun Lab */
+local COMBI = {}
+
+COMBI.Name = "SMG Gun Lab"
+COMBI.Description = "For making Assault weapons."
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 200
+COMBI.Req["Maple"] = 200
+
+COMBI.Results = "gms_smggunlab"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_wasteland/controlroom_storagecloset001a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* High-Tech Lab */
+local COMBI = {}
+
+COMBI.Name = "High Tech Gun Lab"
+COMBI.Description = "For making snipers and misc. weapons."
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 250
+COMBI.Req["Teak"] = 250
+COMBI.Req["Steel"] = 150
+
+COMBI.Results = "gms_hightechgunlab"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_wasteland/laundry_washer003.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Transmutator */
+local COMBI = {}
+
+COMBI.Name = "Transmutator"
+COMBI.Description = "For transmutating wood."
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 35
+COMBI.Req["Wood"] = 30
+COMBI.Req["Iron"] = 10
+
+COMBI.Results = "gms_transmutator"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_wasteland/kitchen_stove002a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Advanced Transmutator */
+local COMBI = {}
+
+COMBI.Name = "Advanced Transmutator"
+COMBI.Description = "For transmutating wood."
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Maple"] = 30
+
+COMBI.Results = "gms_advancedtransmutator"
+COMBI.Texture = "gms_icons/gms_none.png"
+COMBI.BuildSiteModel = "models/props_wasteland/kitchen_fridge001a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* GunChunks */
+local COMBI = {}
+
+COMBI.Name = "Gun Chunks"
+COMBI.Description = "For making the components of guns with relative ease."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 50
+COMBI.Req["Copper"] = 25
+COMBI.Req["Wood"] = 25
+
+COMBI.Results = "gms_gunchunks"
+COMBI.Texture = "gms_icons/gms_gunchunks.png"
+COMBI.BuildSiteModel = "models/Gibs/airboat_broken_engine.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* ------------------------ Stone Furnace ------------------------*/
+
+/* Copper Ore to Copper*/
+local COMBI = {}
+
+COMBI.Name = "Copper"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_stonefurnace"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_stonefurnace" )
+
+/* Copper Ore to Copper x5 */
+local COMBI = {}
+
+COMBI.Name = "Copper 5x"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_stonefurnace"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_stonefurnace" )
+
+/* Copper Ore to Copper x10 */
+local COMBI = {}
+
+COMBI.Name = "Copper 10x"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_stonefurnace"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_stonefurnace" )
+
+/* Copper Ore to Copper x25 */
+local COMBI = {}
+
+COMBI.Name = "Copper 25x"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_stonefurnace"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_stonefurnace" )
+
+/* Allsmelt Copper */
+local COMBI = {}
+
+COMBI.Name = "All Copper"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_stonefurnace"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 35
+
+GMS.RegisterCombi( COMBI, "gms_stonefurnace" )
+
+/* ------------------------ Copper Furnace ------------------------*/
+
+/* Iron Ore to Iron */
+local COMBI = {}
+
+COMBI.Name = "Iron"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* Iron Ore to Iron x5 */
+local COMBI = {}
+
+COMBI.Name = "Iron 5x"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* Iron Ore to Iron x10 */
+local COMBI = {}
+
+COMBI.Name = "Iron 10x"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* Iron Ore to Iron x25 */
+local COMBI = {}
+
+COMBI.Name = "Iron 25x"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* Allsmelt Iron */
+local COMBI = {}
+
+COMBI.Name = "All Iron"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* Sulphur */
+local COMBI = {}
+
+COMBI.Name = "Sulphur 5x"
+COMBI.Description = "Used in the production of gunpowder, refine from rocks."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Sulphur"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* Sulphur 10 */
+local COMBI = {}
+
+COMBI.Name = "Sulphur 10x"
+COMBI.Description = "Used in the production of gunpowder, refine from rocks."
+COMBI.Entity = "gms_copperfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Sulphur"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_copperfurnace" )
+
+/* ------------------------ Iron Furnace ------------------------*/
+
+/* All Tech */
+local COMBI = {}
+
+COMBI.Name = "All Tech"
+COMBI.Description = "Tech can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Tech"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* 1 Tech */
+local COMBI = {}
+
+COMBI.Name = "Tech"
+COMBI.Description = "Tech can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Tech"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* 5 Tech */
+local COMBI = {}
+
+COMBI.Name = "Tech 5x"
+COMBI.Description = "Tech can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Tech"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* 10 Tech */
+local COMBI = {}
+
+COMBI.Name = "Tech 10x"
+COMBI.Description = "Tech can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Tech"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* 25 Tech */
+local COMBI = {}
+
+COMBI.Name = "Tech 25x"
+COMBI.Description = "Tech can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Tech"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+
+/* Glass */
+local COMBI = {}
+
+COMBI.Name = "Glass"
+COMBI.Description = "Glass can be used for making bottles and lighting."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Glass"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* Charcoal */
+local COMBI = {}
+
+COMBI.Name = "Charcoal"
+COMBI.Description = "Used in the production of gunpowder."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Charcoal"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* Charcoal 10x */
+local COMBI = {}
+
+COMBI.Name = "Charcoal 10x"
+COMBI.Description = "Used in the production of gunpowder."
+COMBI.Entity = "gms_ironfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 50
+
+COMBI.Results = {}
+COMBI.Results["Charcoal"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_ironfurnace" )
+
+/* ------------------------ Tech Furnace ------------------------*/
+
+/* All Silver */
+local COMBI = {}
+
+COMBI.Name = "All Silver"
+COMBI.Description = "Silver can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_techfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Silver"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_techfurnace" )
+
+/* 1 Silver */
+local COMBI = {}
+
+COMBI.Name = "Silver"
+COMBI.Description = "Silver can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_techfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Silver"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_techfurnace" )
+
+/* 5 Silver */
+local COMBI = {}
+
+COMBI.Name = "Silver 5x"
+COMBI.Description = "Silver can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_techfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Silver"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_techfurnace" )
+
+/* 10 Silver */
+local COMBI = {}
+
+COMBI.Name = "Silver 10x"
+COMBI.Description = "Silver can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_techfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Silver"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_techfurnace" )
+
+/* 25 Silver */
+local COMBI = {}
+
+COMBI.Name = "Silver 25x"
+COMBI.Description = "Silver can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_techfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Silver"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_techfurnace" )
+
+/* ------------------------ Silver Furnace ------------------------*/
+
+/* 1 Gold */
+local COMBI = {}
+
+COMBI.Name = "Gold"
+COMBI.Description = "Gold can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_silverfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Gold"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_silverfurnace" )
+
+/* 5 Gold */
+local COMBI = {}
+
+COMBI.Name = "Gold 5x"
+COMBI.Description = "Gold can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_silverfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Gold"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_silverfurnace" )
+
+/* 10 Gold */
+local COMBI = {}
+
+COMBI.Name = "Gold 10x"
+COMBI.Description = "Gold can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_silverfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Gold"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_silverfurnace" )
+
+/* 25 Gold */
+local COMBI = {}
+
+COMBI.Name = "Gold 25x"
+COMBI.Description = "Gold can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_silverfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Gold"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_silverfurnace" )
+
+/* All Gold */
+local COMBI = {}
+
+COMBI.Name = "Gold"
+COMBI.Description = "Gold can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_silverfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Gold"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_silverfurnace" )
+
+/* ------------------------ Gold Furnace ------------------------*/
+
+/* 1 Steel */
+local COMBI = {}
+
+COMBI.Name = "Steel"
+COMBI.Description = "Steel can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_goldfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Steel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_goldfurnace" )
+
+/* 5 Steel */
+local COMBI = {}
+
+COMBI.Name = "Steel 5x"
+COMBI.Description = "Steel can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_goldfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Steel"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_goldfurnace" )
+
+/* 10 Steel */
+local COMBI = {}
+
+COMBI.Name = "Steel 10x"
+COMBI.Description = "Steel can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_goldfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Steel"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_goldfurnace" )
+
+/* 25 Steel */
+local COMBI = {}
+
+COMBI.Name = "Steel 25x"
+COMBI.Description = "Steel can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_goldfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Steel"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_goldfurnace" )
+
+/* All Steel */
+local COMBI = {}
+
+COMBI.Name = "Steel"
+COMBI.Description = "Steel can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_goldfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Steel"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_goldfurnace" )
+
+/* ------------------------ Steel Furnace ------------------------*/
+
+/* 1 Platinum */
+local COMBI = {}
+
+COMBI.Name = "Platinum"
+COMBI.Description = "Platinum can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_steelfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Platinum"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_steelfurnace" )
+
+/* 5 Platinum */
+local COMBI = {}
+
+COMBI.Name = "Platinum 5x"
+COMBI.Description = "Platinum can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_steelfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Platinum"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_steelfurnace" )
+
+/* 10 Platinum */
+local COMBI = {}
+
+COMBI.Name = "Platinum 10x"
+COMBI.Description = "Platinum can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_steelfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Platinum"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_steelfurnace" )
+
+/* 25 Platinum */
+local COMBI = {}
+
+COMBI.Name = "Platinum 25x"
+COMBI.Description = "Platinum can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_steelfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Platinum"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_steelfurnace" )
+
+/* All Platinum */
+local COMBI = {}
+
+COMBI.Name = "Platinum"
+COMBI.Description = "Platinum can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_steelfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Platinum"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_steelfurnace" )
+
+/*------------------------ Factory ------------------------*/
+
+/* Glass ( 10 ) */
+local COMBI = {}
+
+COMBI.Name = "Glass 10x"
+COMBI.Description = "Heats 25 sand together to form 10 glass."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Glass"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Glass ( 25 ) */
+local COMBI = {}
+
+COMBI.Name = "Glass 25x"
+COMBI.Description = "Heats 50 sand together to form 25 glass."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 50
+
+COMBI.Results = {}
+COMBI.Results["Glass"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Glass ( 50 ) */
+local COMBI = {}
+
+COMBI.Name = "Glass 50x"
+COMBI.Description = "Heats 75 sand together to form 50 glass."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 75
+
+COMBI.Results = {}
+COMBI.Results["Glass"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Iron from Stone ( 10 ) */
+local COMBI = {}
+
+COMBI.Name = "Iron 10x"
+COMBI.Description = "Smelting together 25 stone forms 10 iron."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Iron from Stone ( 25 ) */
+local COMBI = {}
+
+COMBI.Name = "Iron 25x"
+COMBI.Description = "Smelting together 50 stone forms 25 iron."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 50
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Iron from Stone ( 50 ) */
+local COMBI = {}
+
+COMBI.Name = "Iron 50x"
+COMBI.Description = "Smelting together 75 stone forms 50 iron."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 75
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Allsmelt Iron */
+local COMBI = {}
+
+COMBI.Name = "All Iron"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Allsmelt Copper */
+local COMBI = {}
+
+COMBI.Name = "All Copper"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Stone to Sand ( 10 ) */
+local COMBI = {}
+
+COMBI.Name = "Sand 10x"
+COMBI.Description = "Crushes 10 stone to 10 sand."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Sand"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Stone to Sand ( 25 ) */
+local COMBI = {}
+
+COMBI.Name = "Sand 25x"
+COMBI.Description = "Crushes 20 stone to 25 sand."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Sand"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Stone to Sand ( 50 ) */
+local COMBI = {}
+
+COMBI.Name = "Sand 50x"
+COMBI.Description = "Crushes 30 stone to 50 sand."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Sand"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Resin ( 5 ) */
+local COMBI = {}
+
+COMBI.Name = "Resin 5x"
+COMBI.Description = "Extracts the resin from the wood."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 15
+COMBI.Req["Water_Bottles"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Resin"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Resin ( 10 ) */
+local COMBI = {}
+
+COMBI.Name = "Resin 10x"
+COMBI.Description = "Extracts the resin from the wood."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 25
+COMBI.Req["Water_Bottles"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Resin"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Resin ( 25 ) */
+local COMBI = {}
+
+COMBI.Name = "Resin 25x"
+COMBI.Description = "Extracts the resin from the wood."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 50
+COMBI.Req["Water_Bottles"] = 4
+
+COMBI.Results = {}
+COMBI.Results["Resin"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Plastic ( 10 ) */
+local COMBI = {}
+
+COMBI.Name = "Plastic 10x"
+COMBI.Description = "Solidifies the Resin, creating a natural plastic."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Resin"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Plastic"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* Plastic ( 25 ) */
+local COMBI = {}
+
+COMBI.Name = "Plastic 25x"
+COMBI.Description = "Solidifies the Resin, creating a natural plastic."
+COMBI.Entity = "gms_factory"
+
+COMBI.Req = {}
+COMBI.Req["Resin"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Plastic"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_factory" )
+
+/* ------------------------ Grinding Stone ------------------------*/
+
+/* Stone to Sand x1 */
+local COMBI = {}
+
+COMBI.Name = "Sand"
+COMBI.Description = "Converts 1 stone to 1 sand."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Sand"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/* Stone to Sand x5 */
+local COMBI = {}
+
+COMBI.Name = "Sand 5x"
+COMBI.Description = "Converts 5 stone to 5 sand."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Sand"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/* Stone to Sand x10 */
+local COMBI = {}
+
+COMBI.Name = "Sand10"
+COMBI.Description = "Converts 10 stone to 10 sand."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Sand"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/* Grain to Flour x1 */
+local COMBI = {}
+
+COMBI.Name = "Flour"
+COMBI.Description = "Converts 2 Grain Seeds to 1 Flour."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Grain_Seeds"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Flour"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/* Grain to Flour x5 */
+local COMBI = {}
+
+COMBI.Name = "Flour 5x"
+COMBI.Description = "Converts 5 Grain Seeds to 3 Flour."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Grain_Seeds"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Flour"] = 3
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/* Grain to Flour x10 */
+local COMBI = {}
+
+COMBI.Name = "Flour 10x"
+COMBI.Description = "Converts 10 Grain Seeds to 7 Flour."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Grain_Seeds"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Flour"] = 7
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/* All Grain to Flour*/
+local COMBI = {}
+
+COMBI.Name = "All Flour"
+COMBI.Description = "Converts Grain Seeds to Flour ( 10:6 )."
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Grain_Seeds"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Flour"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 25
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+/*------------------------ Cooking ------------------------*/
+
+/* Casserole */
+local COMBI = {}
+
+COMBI.Name = "Casserole"
+COMBI.Description = "Put a little spiced trout over the fire to make this delicious casserole."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Trout"] = 1
+COMBI.Req["Herbs"] = 3
+COMBI.FoodValue = 400
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Fried meat */
+local COMBI = {}
+
+COMBI.Name = "Fried Meat"
+COMBI.Description = "Simple fried meat."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Meat"] = 1
+
+COMBI.FoodValue = 250
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Sushi */
+local COMBI = {}
+
+COMBI.Name = "Sushi"
+COMBI.Description = "For when you like your fish raw."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Bass"] = 2
+
+COMBI.FoodValue = 300
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Fish soup */
+local COMBI = {}
+
+COMBI.Name = "Fish Soup"
+COMBI.Description = "Fish soup, pretty good!"
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Bass"] = 1
+COMBI.Req["Trout"] = 1
+COMBI.Req["Spices"] = 2
+COMBI.Req["Water_Bottles"] = 2
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 2
+
+COMBI.FoodValue = 400
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Meatballs */
+local COMBI = {}
+
+COMBI.Name = "Meatballs"
+COMBI.Description = "Processed meat."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Meat"] = 1
+COMBI.Req["Spices"] = 1
+COMBI.Req["Water_Bottles"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 2
+
+COMBI.FoodValue = 400
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Fried fish */
+local COMBI = {}
+
+COMBI.Name = "Fried Fish"
+COMBI.Description = "Simple fried fish."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Bass"] = 1
+COMBI.FoodValue = 200
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Berry Pie */
+local COMBI = {}
+
+COMBI.Name = "Berry Pie"
+COMBI.Description = "Yummy, berry pie reminds me of home!"
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Dough"] = 2
+COMBI.Req["Water_Bottles"] = 2
+COMBI.Req["Berries"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 5
+
+COMBI.FoodValue = 700
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Rock cake */
+local COMBI = {}
+
+COMBI.Name = "Rock Cake"
+COMBI.Description = "Crunchy!"
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 2
+COMBI.Req["Herbs"] = 1
+COMBI.FoodValue = 50
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Salad */
+local COMBI = {}
+
+COMBI.Name = "Salad"
+COMBI.Description = "Everything for survival, I guess."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Herbs"] = 2
+COMBI.FoodValue = 100
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Meal */
+local COMBI = {}
+
+COMBI.Name = "Meal"
+COMBI.Description = "The ultimate meal. Delicious!"
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Herbs"] = 5
+COMBI.Req["Salmon"] = 1
+COMBI.Req["Meat"] = 2
+COMBI.Req["Spices"] = 3
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 20
+
+COMBI.FoodValue = 1000
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Shark soup */
+local COMBI = {}
+
+COMBI.Name = "Shark Soup"
+COMBI.Description = "Man this is good."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Shark"] = 2
+COMBI.Req["Herbs"] = 3
+COMBI.Req["Spices"] = 2
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 15
+
+COMBI.FoodValue = 850
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Bread */
+local COMBI = {}
+
+COMBI.Name = "Bread"
+COMBI.Description = "Good old bread."
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Dough"] = 2
+COMBI.Req["Water_Bottles"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 5
+
+COMBI.FoodValue = 800
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* Hamburger */
+local COMBI = {}
+
+COMBI.Name = "Hamburger"
+COMBI.Description = "A hamburger! Yummy!"
+COMBI.Entity = "gms_stove"
+
+COMBI.Req = {}
+COMBI.Req["Dough"] = 2
+COMBI.Req["Water_Bottles"] = 1
+COMBI.Req["Meat"] = 2
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Cooking"] = 3
+
+COMBI.FoodValue = 850
+
+GMS.RegisterCombi( COMBI, "Cooking" )
+
+/* ------------------------ Stone Workbench ------------------------*/
+
+/* Stone Hatchet */
+local COMBI = {}
+
+COMBI.Name = "Stone Hatchet"
+COMBI.Description = "This small stone axe is ideal for chopping down trees."
+COMBI.Entity = "gms_stoneworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 10
+COMBI.Req["Wood"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_stonehatchet"
+
+GMS.RegisterCombi( COMBI, "gms_stoneworkbench" )
+
+/* Wooden Spoon */
+local COMBI = {}
+
+COMBI.Name = "Wooden Spoon"
+COMBI.Description = "Allows you to salvage more seeds from consumed fruit."
+COMBI.Entity = "gms_stoneworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 12
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 3
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_woodenspoon"
+
+GMS.RegisterCombi( COMBI, "gms_stoneworkbench" )
+
+/* Stone Pickaxe */
+local COMBI = {}
+
+COMBI.Name = "Stone Pickaxe"
+COMBI.Description = "This stone pickaxe is used for effectively mining stone and copper ore."
+COMBI.Entity = "gms_stoneworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 10
+COMBI.Req["Wood"] = 10
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_stonepickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_stoneworkbench" )
+
+/* Fishing rod */
+local COMBI = {}
+
+COMBI.Name = "Wooden Fishing Rod"
+COMBI.Description = "This rod of wood can be used to fish from a lake."
+COMBI.Entity = "gms_stoneworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Rope"] = 1
+COMBI.Req["Wood"] = 20
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 4
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_woodenfishingrod"
+
+GMS.RegisterCombi( COMBI, "gms_stoneworkbench" )
+
+/* ------------------------ Copper Workbench ------------------------*/
+
+/* Copper Hatchet */
+local COMBI = {}
+
+COMBI.Name = "Copper Hatchet"
+COMBI.Description = "This copper axe is ideal for chopping down trees."
+COMBI.Entity = "gms_copperworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_copperhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_copperworkbench" )
+
+/* Copper Hammer */
+local COMBI = {}
+
+COMBI.Name = "Wrench"
+COMBI.Description = "This wrench is ideal for crafting weapons."
+COMBI.Entity = "gms_copperworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 10
+COMBI.Req["Wood"] = 10
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 5
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_wrench"
+
+GMS.RegisterCombi( COMBI, "gms_copperworkbench" )
+
+/* Copper Pickaxe */
+local COMBI = {}
+
+COMBI.Name = "Copper Pickaxe"
+COMBI.Description = "This copper pickaxe is used for effectively mining stone, copper ore and iron ore."
+COMBI.Entity = "gms_copperworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_copperpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_copperworkbench" )
+
+/* Frying pan */
+local COMBI = {}
+
+COMBI.Name = "Frying Pan"
+COMBI.Description = "This kitchen tool is used for more effective cooking."
+COMBI.Entity = "gms_copperworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 20
+COMBI.Req["Wood"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 5
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_fryingpan"
+
+GMS.RegisterCombi( COMBI, "gms_copperworkbench" )
+
+/* Shovel */
+local COMBI = {}
+
+COMBI.Name = "Shovel"
+COMBI.Description = "This tool can dig up rocks, and decreases forage times."
+COMBI.Entity = "gms_copperworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 15
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 8
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_shovel"
+
+GMS.RegisterCombi( COMBI, "gms_copperworkbench" )
+
+/* Crowbar */
+local COMBI = {}
+
+COMBI.Name = "Crowbar"
+COMBI.Description = "This weapon is initially a tool, but pretty useless for it's original purpose on a stranded Island."
+COMBI.Entity = "gms_copperworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 20
+COMBI.Req["Iron"] = 20
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 6
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "weapon_crowbar"
+
+GMS.RegisterCombi( COMBI, "gms_copperworkbench" )
+
+/* ------------------------ Iron Workbench ------------------------*/
+
+/* Sickle */
+local COMBI = {}
+
+COMBI.Name = "Sickle"
+COMBI.Description = "This tool effectivizes harvesting."
+COMBI.Entity = "gms_ironworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 5
+COMBI.Req["Wood"] = 15
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 7
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_sickle"
+
+GMS.RegisterCombi( COMBI, "gms_ironworkbench" )
+
+/* Strainer */
+local COMBI = {}
+
+COMBI.Name = "Strainer"
+COMBI.Description = "This tool can filter the earth for resources."
+COMBI.Entity = "gms_ironworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 5
+COMBI.Req["Wood"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_strainer"
+
+GMS.RegisterCombi( COMBI, "gms_ironworkbench" )
+
+/* Advanced Fishing rod */
+local COMBI = {}
+
+COMBI.Name = "Advanced Fishing rod"
+COMBI.Description = "With this Fishing rod you can catch rare fish even faster. You might even catch something big."
+COMBI.Entity = "gms_ironworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 25
+COMBI.Req["Wood"] = 30
+COMBI.Req["Rope"] = 2
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 15
+COMBI.SkillReq["Fishing"] = 5
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_advancedfishingrod"
+
+GMS.RegisterCombi( COMBI, "gms_ironworkbench" )
+
+/* Iron Pickaxe */
+local COMBI = {}
+
+COMBI.Name = "Iron Pickaxe"
+COMBI.Description = "This iron pickaxe is used for effectively mining stone, copper ore, iron ore, and tech ore."
+COMBI.Entity = "gms_ironworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+COMBI.Req["Wood"] = 10
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_ironpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_ironworkbench" )
+
+/* Iron Hatchet */
+local COMBI = {}
+
+COMBI.Name = "Iron Hatchet"
+COMBI.Description = "This iron axe is ideal for chopping down trees."
+COMBI.Entity = "gms_ironworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+COMBI.Req["Wood"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_ironhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_ironworkbench" )
+
+
+/*------------------------ Gun Lab ------------------------*/
+
+/*HL2 Smg */
+local COMBI = {}
+
+COMBI.Name = "HL2 Machine Gun"
+COMBI.Description = "Just a simple Machine Gun."
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Copper Gunslide"] = 1
+COMBI.Req["Copper Gungrip"] = 1
+COMBI.Req["Copper Gunbarrel"] = 1
+COMBI.Req["Copper Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 15
+COMBI.SkillReq["Hunting"] = 15
+
+COMBI.Texture = "gms_icons/weapon_smg1.png"
+COMBI.SwepClass = "weapon_smg1"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* HL2 Pistol */
+local COMBI = {}
+
+COMBI.Name = "Pistol"
+COMBI.Description = "It's not great, but it does the job. Your first ordinary Pistol."
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Copper Gunslide"] = 1
+COMBI.Req["Copper Gungrip"] = 1
+COMBI.Req["Copper Gunbarrel"] = 1
+COMBI.Req["Copper Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 10
+COMBI.SkillReq["Hunting"] = 8
+
+COMBI.Texture = "gms_icons/weapon_pistol.png"
+COMBI.SwepClass = "weapon_pistol"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+local COMBI = {}
+
+COMBI.Name = "HL2 Shotgun"
+COMBI.Description = "Just a simple Shotgun. Left click for single shot, right click for double shots"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron Gunslide"] = 1
+COMBI.Req["Iron Gungrip"] = 1
+COMBI.Req["Iron Gunbarrel"] = 1
+COMBI.Req["Iron Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 25
+COMBI.SkillReq["Hunting"] = 20
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "weapon_shotgun"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+local COMBI = {}
+
+COMBI.Name = "HL2 Crossbow"
+COMBI.Description = "A very Medieval weapon, shoots bolts with left click and zooms in with right click"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+COMBI.Req["Tech WeaponScope"] = 1
+COMBI.Req["Rope"] = 2
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 75
+COMBI.SkillReq["Hunting"] = 70
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "weapon_crossbow"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/*------------------------ Gun Chunks ------------------------*/
+
+/* Copper Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Copper Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Copper Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Copper Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Copper Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Copper Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Copper Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Copper Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Copper Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Copper Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Copper Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 15
+COMBI.Req["Wood"] = 20
+COMBI.Req["Gunpowder"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Copper Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Copper Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Copper Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Copper"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Copper Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Copper Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Copper Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Copper"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Copper Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Iron Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Iron Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+COMBI.Req["Oak"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Iron Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Iron Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Iron Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+COMBI.Req["Oak"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Iron Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Iron Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Iron Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+COMBI.Req["Oak"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Iron Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Iron Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Iron Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 20
+COMBI.Req["Oak"] = 20
+COMBI.Req["Gunpowder"] = 15
+
+COMBI.Results = {}
+COMBI.Results["Iron Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Iron Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Iron Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Iron"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Iron Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Iron Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Iron Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Iron"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Iron Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Tech Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Tech Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 25
+COMBI.Req["Cedar"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Tech Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Tech Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Tech Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 25
+COMBI.Req["Cedar"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Tech Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Tech Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Tech Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 25
+COMBI.Req["Cedar"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Tech Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Tech Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Tech Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 25
+COMBI.Req["Cedar"] = 15
+COMBI.Req["Gunpowder"] = 15
+
+COMBI.Results = {}
+COMBI.Results["Tech Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Tech Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Tech Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Tech"] = 35
+
+COMBI.Results = {}
+COMBI.Results["Tech Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Tech Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Tech Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Tech"] = 35
+
+COMBI.Results = {}
+COMBI.Results["Tech Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Silver Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Silver Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Maple"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Silver Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Silver Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Silver Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Maple"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Silver Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Silver Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Silver Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Maple"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Silver Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Silver Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Silver Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Maple"] = 20
+COMBI.Req["Gunpowder"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Silver Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Silver Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Silver Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Silver"] = 40
+
+COMBI.Results = {}
+COMBI.Results["Silver Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Silver Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Silver Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Silver"] = 40
+
+COMBI.Results = {}
+COMBI.Results["Silver Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Gold Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Gold Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Gold Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Gold Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Gold Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Gold Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Gold Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Gold Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Gold Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Gold Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Gold Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 25
+COMBI.Req["Gunpowder"] = 25
+
+COMBI.Results = {}
+COMBI.Results["Gold Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Gold Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Gold Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Gold"] = 45
+
+COMBI.Results = {}
+COMBI.Results["Gold Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Gold Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Gold Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Gold"] = 45
+
+COMBI.Results = {}
+COMBI.Results["Gold Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Steel Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Steel Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 40
+COMBI.Req["Mahogany"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Steel Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Steel Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Steel Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 40
+COMBI.Req["Mahogany"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Steel Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Steel Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Steel Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 40
+COMBI.Req["Mahogany"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Steel Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Steel Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Steel Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 40
+COMBI.Req["Mahogany"] = 30
+COMBI.Req["Gunpowder"] = 30
+
+COMBI.Results = {}
+COMBI.Results["Steel Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Steel Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Steel Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Steel"] = 50
+
+COMBI.Results = {}
+COMBI.Results["Steel Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Steel Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Steel Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Steel"] = 50
+
+COMBI.Results = {}
+COMBI.Results["Steel Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Platinum Gunslide */
+local COMBI = {}
+
+COMBI.Name = "Platinum Gunslide"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 45
+COMBI.Req["Elm"] = 35
+
+COMBI.Results = {}
+COMBI.Results["Platinum Gunslide"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Platinum Gunbarrel */
+local COMBI = {}
+
+COMBI.Name = "Platinum Gunbarrel"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 45
+COMBI.Req["Elm"] = 35
+
+COMBI.Results = {}
+COMBI.Results["Platinum Gunbarrel"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Platinum Gungrip */
+local COMBI = {}
+
+COMBI.Name = "Platinum Gungrip"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 45
+COMBI.Req["Elm"] = 35
+
+COMBI.Results = {}
+COMBI.Results["Platinum Gungrip"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Platinum Gunmagazine */
+local COMBI = {}
+
+COMBI.Name = "Platinum Gunmagazine"
+COMBI.Description = "A piece of a gun"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 45
+COMBI.Req["Elm"] = 35
+COMBI.Req["Gunpowder"] = 35
+
+COMBI.Results = {}
+COMBI.Results["Platinum Gunmagazine"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Platinum Weapon Scope */
+local COMBI = {}
+
+COMBI.Name = "Platinum Weapon Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Platinum"] = 55
+
+COMBI.Results = {}
+COMBI.Results["Platinum Weapon Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+
+/* Platinum Reflex Scope */
+local COMBI = {}
+
+COMBI.Name = "Platinum Reflex Scope"
+COMBI.Description = "A weapon scope"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 20
+COMBI.Req["Platinum"] = 55
+
+COMBI.Results = {}
+COMBI.Results["Platinum Reflex Scope"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Saltpetre */
+local COMBI = {}
+
+COMBI.Name = "Saltpetre"
+COMBI.Description = "Used in making gunpowder"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Urine_Bottles"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Saltpetre"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Saltpetre x10 */
+local COMBI = {}
+
+COMBI.Name = "Saltpetre 10x"
+COMBI.Description = "Used in making gunpowder"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Urine_Bottles"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Saltpetre"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* Gunpowder */
+local COMBI = {}
+
+COMBI.Name = "Gunpowder"
+COMBI.Description = "Explosive!"
+COMBI.Entity = "gms_gunchunks"
+
+COMBI.Req = {}
+COMBI.Req["Sulphur"] = 5
+COMBI.Req["Charcoal"] = 10
+COMBI.Req["Saltpetre"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Gunpowder"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_gunchunks" )
+
+/* ------------------------------------------------------------------------
+ Tech workbench
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "Batteries"
+COMBI.Description = "These self-rechargeable batteries are used to craft stunstick, toolgun and flashlight.\nAlso the more batteries you have, the longer you can use your flashlight."
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 3
+COMBI.Req["Iron"] = 3
+
+COMBI.Results = {}
+COMBI.Results["Batteries"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Toolgun"
+COMBI.Description = "Vital to long term survival, it allows you to easily build complex structures."
+COMBI.Entity = "gms_techworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 30
+COMBI.Req["Wood"] = 20
+COMBI.Req["Glass"] = 5
+COMBI.Req["Batteries"] = 2
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gmod_tool"
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Flashlight"
+COMBI.Description = "Grants ability to use flashlight."
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 15
+COMBI.Req["Glass"] = 5
+COMBI.Req["Batteries"] = 3
+
+COMBI.Results = {}
+COMBI.Results["Flashlight"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Stunstick"
+COMBI.Description = "This highly advanced, effective melee weapon is useful for hunting down animals and fellow stranded alike."
+COMBI.Entity = "gms_techworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 40
+COMBI.Req["Batteries"] = 4
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 11
+COMBI.SkillReq["Hunting"] = 5
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "weapon_stunstick"
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Wrist Watch"
+COMBI.Description = "See the time whereever you go."
+COMBI.Entity = "gms_techworkbench"
+
+COMBI.Results = {}
+COMBI.Results["Wrist_Watch"] = 1
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 5
+COMBI.Req["Glass"] = 5
+COMBI.Req["Batteries"] = 2
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Tech Pickaxe"
+COMBI.Description = "This tech pickaxe is used for effectively mining stone, copper ore, iron ore, tech ore, and silver ore."
+COMBI.Entity = "gms_techworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 25
+COMBI.Req["Cedar"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_techpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Tech Hatchet"
+COMBI.Description = "This tech axe is ideal for chopping down trees."
+COMBI.Entity = "gms_techworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 25
+COMBI.Req["Cedar"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_techhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_techworkbench" )
+
+------------------------------------------------------------------------
+
+/* ------------------------------------------------------------------------
+ Silver workbench
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "Silver Pickaxe"
+COMBI.Description = "This silver pickaxe is used for effectively mining stone, copper ore, iron ore, tech ore, silver ore, and gold ore."
+COMBI.Entity = "gms_silverworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Maple"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_silverpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_silverworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Silver Hatchet"
+COMBI.Description = "This silver axe is ideal for chopping down trees."
+COMBI.Entity = "gms_silverworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 30
+COMBI.Req["Maple"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_silverhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_silverworkbench" )
+
+------------------------------------------------------------------------
+
+/* ------------------------------------------------------------------------
+ Gold workbench
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "Gold Pickaxe"
+COMBI.Description = "This gold pickaxe is used for effectively mining stone, copper ore, iron ore, tech ore, silver ore, gold ore, and steel ore."
+COMBI.Entity = "gms_goldworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_goldpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_goldworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Gold Hatchet"
+COMBI.Description = "This gold axe is ideal for chopping down trees."
+COMBI.Entity = "gms_goldworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 35
+COMBI.Req["Teak"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_goldhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_goldworkbench" )
+
+------------------------------------------------------------------------
+
+/* ------------------------------------------------------------------------
+ Steel workbench
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "Steel Pickaxe"
+COMBI.Description = "This steel pickaxe is used for effectively mining stone, copper ore, iron ore, tech ore, silver ore, gold ore, steel ore, and platinum ore."
+COMBI.Entity = "gms_steelworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 40
+COMBI.Req["Mahogany"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_steelpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_steelworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Steel Hatchet"
+COMBI.Description = "This Steel axe is ideal for chopping down trees."
+COMBI.Entity = "gms_steelworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 40
+COMBI.Req["Mahogany"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_steelhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_steelworkbench" )
+
+------------------------------------------------------------------------
+
+/* ------------------------------------------------------------------------
+ Platinum workbench
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "Platinum Pickaxe"
+COMBI.Description = "This platinum pickaxe is used for effectively mining stone, copper ore, iron ore, tech ore, silver ore, gold ore, steel ore, and platinum ore."
+COMBI.Entity = "gms_platinumworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 45
+COMBI.Req["Elm"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_platinumpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_platinumworkbench" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Platinum Hatchet"
+COMBI.Description = "This Platinum axe is ideal for chopping down trees."
+COMBI.Entity = "gms_platinumworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 45
+COMBI.Req["Elm"] = 10
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_platinumhatchet"
+
+GMS.RegisterCombi( COMBI, "gms_platinumworkbench" )
+
+------------------------------------------------------------------------
+
+/* ------------------------------------------------------------------------
+ Basic Transmutator
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "All Oak"
+COMBI.Description = "This type of wood can be used to make more advanced machinery."
+COMBI.Entity = "gms_transmutator"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 1
+COMBI.Req["Iron"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Oak"] = 2
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_transmutator" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "All Cedar"
+COMBI.Description = "This type of wood can be used to make more advanced machinery."
+COMBI.Entity = "gms_transmutator"
+
+COMBI.Req = {}
+COMBI.Req["Oak"] = 1
+COMBI.Req["Tech"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Cedar"] = 2
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_transmutator" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "All Maple"
+COMBI.Description = "This type of wood can be used to make more advanced machinery."
+COMBI.Entity = "gms_transmutator"
+
+COMBI.Req = {}
+COMBI.Req["Cedar"] = 1
+COMBI.Req["Silver"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Maple"] = 2
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_transmutator" )
+
+------------------------------------------------------------------------
+
+/* ------------------------------------------------------------------------
+ Advanced Transmutator
+------------------------------------------------------------------------ */
+
+local COMBI = {}
+
+COMBI.Name = "All Teak"
+COMBI.Description = "This type of wood can be used to make more advanced machinery."
+COMBI.Entity = "gms_advancedtransmutator"
+
+COMBI.Req = {}
+COMBI.Req["Maple"] = 1
+COMBI.Req["Gold"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Teak"] = 2
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_advancedtransmutator" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "All Mahogany"
+COMBI.Description = "This type of wood can be used to make more advanced machinery."
+COMBI.Entity = "gms_advancedtransmutator"
+
+COMBI.Req = {}
+COMBI.Req["Teak"] = 1
+COMBI.Req["Steel"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Mahogany"] = 2
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_advancedtransmutator" )
+
+------------------------------------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "All Elm"
+COMBI.Description = "This type of wood can be used to make more advanced machinery."
+COMBI.Entity = "gms_advancedtransmutator"
+
+COMBI.Req = {}
+COMBI.Req["Mahogany"] = 1
+COMBI.Req["Platinum"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Elm"] = 2
+
+COMBI.AllSmelt = true
+COMBI.Max = 200
+
+GMS.RegisterCombi( COMBI, "gms_advancedtransmutator" )
+
+------------------------------------------------------------------------ \ No newline at end of file
diff --git a/ftp_gmstranded/gamemode/combinations2.lua b/ftp_gmstranded/gamemode/combinations2.lua
new file mode 100644
index 0000000..bf31327
--- /dev/null
+++ b/ftp_gmstranded/gamemode/combinations2.lua
@@ -0,0 +1,1196 @@
+
+/* ------------------------ Pistol Gun Lab ------------------------*/
+
+/* M9k USP */
+local COMBI = {}
+
+COMBI.Name = "USP Pistol"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 16
+COMBI.SkillReq["Hunting"] = 12
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_usp"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* M9k Luger */
+local COMBI = {}
+
+COMBI.Name = "Luger"
+COMBI.Description = "A refined version of a pistol, Also German made!"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 17
+COMBI.SkillReq["Hunting"] = 13
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_luger"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* M9k Colt1911 */
+local COMBI = {}
+
+COMBI.Name = "Colt Pistol"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 16
+COMBI.SkillReq["Hunting"] = 12
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_colt1911"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+
+/* M9k Glock */
+local COMBI = {}
+
+COMBI.Name = "Glock Pistol"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 20
+COMBI.SkillReq["Hunting"] = 16
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_glock"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+
+/* M9k Remington 1858 */
+local COMBI = {}
+
+COMBI.Name = "Remington 1858"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Silver Gunslide"] = 1
+COMBI.Req["Silver Gungrip"] = 1
+COMBI.Req["Silver Gunbarrel"] = 1
+COMBI.Req["Silver Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 25
+COMBI.SkillReq["Hunting"] = 20
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_remington1858"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* M9k S W Model 3 Russian */
+local COMBI = {}
+
+COMBI.Name = "S W Model 3 Russian"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Silver Gunslide"] = 1
+COMBI.Req["Silver Gungrip"] = 1
+COMBI.Req["Silver Gunbarrel"] = 1
+COMBI.Req["Silver Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 20
+COMBI.SkillReq["Hunting"] = 17
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_model3russian"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+
+/* M9k Satan */
+local COMBI = {}
+
+COMBI.Name = "Satan Revolver"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Silver Gunslide"] = 1
+COMBI.Req["Silver Gungrip"] = 1
+COMBI.Req["Silver Gunbarrel"] = 1
+COMBI.Req["Silver Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 30
+COMBI.SkillReq["Hunting"] = 25
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_m29satan"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+
+/* M9k Deagle */
+local COMBI = {}
+
+COMBI.Name = "Deagle"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Gold Gunslide"] = 1
+COMBI.Req["Gold Gungrip"] = 1
+COMBI.Req["Gold Gunbarrel"] = 1
+COMBI.Req["Gold Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 35
+COMBI.SkillReq["Hunting"] = 28
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_deagle"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+
+/* M9k Raging Bull */
+local COMBI = {}
+
+COMBI.Name = "Raging Bull"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Steel Gunslide"] = 1
+COMBI.Req["Steel Gungrip"] = 1
+COMBI.Req["Steel Gunbarrel"] = 1
+COMBI.Req["Steel Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 40
+COMBI.SkillReq["Hunting"] = 32
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_ragingbull"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+
+/* M9k Scoped Raging Bull */
+local COMBI = {}
+
+COMBI.Name = "Scoped Raging Bull"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Platinum Gunslide"] = 1
+COMBI.Req["Platinum Gungrip"] = 1
+COMBI.Req["PLatinum Gunbarrel"] = 1
+COMBI.Req["Platinum Gunmagazine"] = 1
+COMBI.Req["Platinum Weapon Scope"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 50
+COMBI.SkillReq["Hunting"] = 32
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_scoped_taurus"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* ------------------------ SMG Gun Lab ------------------------*/
+
+/* M9k P90 */
+local COMBI = {}
+
+COMBI.Name = "P90"
+COMBI.Description = "A refined version of an SMG"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 25
+COMBI.SkillReq["Hunting"] = 20
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_smgp90"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* M9k Magdul PDR */
+local COMBI = {}
+
+COMBI.Name = "Magdul PDR"
+COMBI.Description = "A refined version of an SMG"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Silver Gunslide"] = 1
+COMBI.Req["Silver Gungrip"] = 1
+COMBI.Req["Silver Gunbarrel"] = 1
+COMBI.Req["Silver Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 35
+COMBI.SkillReq["Hunting"] = 30
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_magpulpdr"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+
+
+/* M9k MP90 */
+local COMBI = {}
+
+COMBI.Name = "MP90"
+COMBI.Description = "A refined version of an SMG"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Gold Gunslide"] = 1
+COMBI.Req["Gold Gungrip"] = 1
+COMBI.Req["Gold Gunbarrel"] = 1
+COMBI.Req["Gold Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 45
+COMBI.SkillReq["Hunting"] = 40
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_mp9"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+ /*FN FAL*/
+local COMBI = {}
+
+COMBI.Name = "FN FAL"
+COMBI.Description = "Fairly advanced Assault rifle, Pressing E and R at the same time will turn the gun between Automatic and Single shot."
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Steel Gunslide"] = 1
+COMBI.Req["Steel Gungrip"] = 1
+COMBI.Req["Steel Gunbarrel"] = 1
+COMBI.Req["Steel Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 60
+COMBI.SkillReq["Hunting"] = 50
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_fal"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* M9k KRISS Vector */
+local COMBI = {}
+
+COMBI.Name = "KRISS Vector"
+COMBI.Description = "A refined version of an SMG"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Steel Gunslide"] = 1
+COMBI.Req["Steel Gungrip"] = 1
+COMBI.Req["Steel Gunbarrel"] = 1
+COMBI.Req["Steel Gunmagazine"] = 1
+COMBI.Req["Steel Reflex Scope"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 50
+COMBI.SkillReq["Hunting"] = 45
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_vector"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* M9k MP7 */
+local COMBI = {}
+
+COMBI.Name = "MP7"
+COMBI.Description = "A refined version of an SMG"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Steel Gunslide"] = 1
+COMBI.Req["Steel Gungrip"] = 1
+COMBI.Req["Steel Gunbarrel"] = 1
+COMBI.Req["Steel Gunmagazine"] = 1
+COMBI.Req["Steel Weapon Scope"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 60
+COMBI.SkillReq["Hunting"] = 50
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_mp7"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* M9k Honey Badger */
+local COMBI = {}
+
+COMBI.Name = "Honey Badger"
+COMBI.Description = "A refined version of an SMG"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Platinum Gunslide"] = 1
+COMBI.Req["Platinum Gungrip"] = 1
+COMBI.Req["Platinum Gunbarrel"] = 1
+COMBI.Req["Platinum Gunmagazine"] = 1
+COMBI.Req["Platinum Weapon Scope"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 70
+COMBI.SkillReq["Hunting"] = 60
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_honeybadger"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* ------------------------ High Tech Gun Lab ------------------------*/
+
+/* M9k Winchester */
+local COMBI = {}
+
+COMBI.Name = "Winchester Rifle"
+COMBI.Description = "A refined version of an Assault Rifle"
+COMBI.Entity = "gms_hightechgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Platinum Gunslide"] = 1
+COMBI.Req["Platinum Gungrip"] = 1
+COMBI.Req["Platinum Gunbarrel"] = 1
+COMBI.Req["Platinum Gunmagazine"] = 1
+COMBI.Req["Platinum Weapon Scope"] = 1
+COMBI.Req["Steel"] = 100
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 90
+COMBI.SkillReq["Hunting"] = 70
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_winchester73"
+
+GMS.RegisterCombi( COMBI, "gms_hightechgunlab" )
+
+
+/* M9k Vikhr */
+local COMBI = {}
+
+COMBI.Name = "Vikhr Rifle"
+COMBI.Description = "A refined version of an Assault Rifle"
+COMBI.Entity = "gms_hightechgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Platinum Gunslide"] = 1
+COMBI.Req["Platinum Gungrip"] = 1
+COMBI.Req["Platinum Gunbarrel"] = 1
+COMBI.Req["Platinum Gunmagazine"] = 1
+COMBI.Req["Platinum Weapon Scope"] = 1
+COMBI.Req["Steel"] = 100
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 100
+COMBI.SkillReq["Hunting"] = 70
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_vikhr"
+
+GMS.RegisterCombi( COMBI, "gms_hightechgunlab" )
+
+
+/* M9k Remington Sniper */
+local COMBI = {}
+
+COMBI.Name = "Remington Sniper"
+COMBI.Description = "A refined version of a Sniper Rifle"
+COMBI.Entity = "gms_hightechgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Platinum Gunslide"] = 1
+COMBI.Req["Platinum Gungrip"] = 1
+COMBI.Req["Platinum Gunbarrel"] = 1
+COMBI.Req["Platinum Gunmagazine"] = 1
+COMBI.Req["Platinum Weapon Scope"] = 1
+COMBI.Req["Platinum"] = 150
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 150
+COMBI.SkillReq["Hunting"] = 70
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_remington7615p"
+
+GMS.RegisterCombi( COMBI, "gms_hightechgunlab" )
+
+
+/* M9k SVT Sniper */
+local COMBI = {}
+
+COMBI.Name = "SVT Sniper"
+COMBI.Description = "A refined version of a Sniper Rifle"
+COMBI.Entity = "gms_hightechgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Platinum Gunslide"] = 1
+COMBI.Req["Platinum Gungrip"] = 1
+COMBI.Req["Platinum Gunbarrel"] = 1
+COMBI.Req["Platinum Gunmagazine"] = 1
+COMBI.Req["Platinum Weapon Scope"] = 1
+COMBI.Req["Platinum"] = 200
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 180
+COMBI.SkillReq["Hunting"] = 100
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_svt40"
+
+GMS.RegisterCombi( COMBI, "gms_hightechgunlab" )
+
+/* ------------------------ Ammo ------------------------*/
+
+/* Pistol ammo */
+local COMBI = {}
+
+COMBI.Name = "Pistol ammo"
+COMBI.Description = "If you wanna keep using the pistol, you'll need this"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 25
+COMBI.Req["Gunpowder"] = 15
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 10
+
+COMBI.Texture = "gms_icons/item_ammo_pistol.png"
+COMBI.SwepClass = "item_ammo_pistol_large"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* Crossbow Bolts */
+local COMBI = {}
+
+COMBI.Name = "Crossbow Bolts"
+COMBI.Description = "If you wanna keep using your Crossbow, you'll need this"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 50
+COMBI.Req["Stone"] = 25
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 50
+
+COMBI.Texture = "gms_icons/item_ammo_pistol.png"
+COMBI.SwepClass = "item_ammo_crossbow "
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* Smg ammo */
+local COMBI = {}
+
+COMBI.Name = "SMG Ammo"
+COMBI.Description = "If you wanna keep using the smg, you'll need this"
+COMBI.Entity = "gms_smggunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 50
+COMBI.Req["Gunpowder"] = 25
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 15
+
+COMBI.Texture = "gms_icons/item_ammo_smg1.png"
+COMBI.SwepClass = "item_ammo_smg1_large"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* Revolver Ammo */
+local COMBI = {}
+
+COMBI.Name = "Revolver Ammo"
+COMBI.Description = "If you wanna keep using the revolvers, you'll need this"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 50
+COMBI.Req["Gunpowder"] = 25
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 10
+
+COMBI.Texture = "gms_icons/item_ammo_pistol.png"
+COMBI.SwepClass = "item_ammo_357_large"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* Assault Rifle Ammo */
+local COMBI = {}
+
+COMBI.Name = "Assault Rifle Ammo"
+COMBI.Description = "If you wanna keep using your Assault Rifle weapons you'll need this"
+COMBI.Entity = "gms_cedargunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 10
+COMBI.Req["Gunpowder"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 50
+
+COMBI.Texture = "gms_icons/item_ammo_smg1.png"
+COMBI.SwepClass = "item_ammo_ar2_large"
+
+GMS.RegisterCombi( COMBI, "gms_smggunlab" )
+
+/* Winchester Ammo */
+local COMBI = {}
+
+COMBI.Name = "Winchester Ammo"
+COMBI.Description = "If you wanna keep using your Winchester you'll need this"
+COMBI.Entity = "gms_hightechgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 10
+COMBI.Req["Gunpowder"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 50
+
+COMBI.Texture = "gms_icons/item_ammo_smg1.png"
+COMBI.SwepClass = "m9k_ammo_winchester"
+
+GMS.RegisterCombi( COMBI, "gms_hightechgunlab" )
+
+/* Shotgun Ammo (HL2) */
+local COMBI = {}
+
+COMBI.Name = "Shotgun Ammo"
+COMBI.Description = "If you want to keep using your Shotgun weapons you'll need this"
+COMBI.Entity = "gms_pistolgunlab"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 5
+COMBI.Req["Gunpowder"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 25
+
+COMBI.Texture = "gms_icons/item_ammo_smg1.png"
+COMBI.SwepClass = "item_box_buckshot"
+
+GMS.RegisterCombi( COMBI, "gms_pistolgunlab" )
+
+/* ------------------------------------------------------------------------Platinum workbench------------------------------------------------------------------------ */
+local COMBI = {}
+
+COMBI.Name = "Pickaxe of Djarex"
+COMBI.Description = "A strange pickaxe that has a tendency to only mine a weird type of stone"
+COMBI.Entity = "gms_platinumworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 25
+COMBI.Req ["Steel"] = 25
+COMBI.Req ["Gold"] = 25
+COMBI.Req["Elm"] = 50
+COMBI.Req["Mahogany"] = 50
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 50
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_pickaxeofdjarex"
+
+GMS.RegisterCombi( COMBI, "gms_platinumworkbench" )
+-------------------------------------------------------------Platinum Furnace------------------------------------
+local COMBI = {}
+
+COMBI.Name = "Pure Mithril"
+COMBI.Description = "The purest form of mithril able to be made"
+COMBI.Entity = "gms_platinumfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Mithril_Ore"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Pure_Mithril"] = 1
+
+GMS.RegisterCombi ( COMBI, "gms_platinumfurnace" )
+
+local COMBI = {}
+
+COMBI.Name = "Pure Mithril x5"
+COMBI.Description = "The purest form of mithril able to be made"
+COMBI.Entity = "gms_platinumfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Mithril_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Pure_Mithril"] = 5
+
+GMS.RegisterCombi ( COMBI, "gms_platinumfurnace" )
+
+local COMBI = {}
+
+COMBI.Name = "Pure Mithril x10"
+COMBI.Description = "The purest form of mithril able to be made"
+COMBI.Entity = "gms_platinumfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Mithril_Ore"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Pure_Mithril"] = 10
+
+GMS.RegisterCombi ( COMBI, "gms_platinumfurnace" )
+
+local COMBI = {}
+
+COMBI.Name = "All Pure Mithril"
+COMBI.Description = "Pure Mithril can be used to start of you industrial needs"
+COMBI.Entity = "gms_platinumfurnace"
+
+COMBI.Req = {}
+COMBI.Req["Mithril_Ore"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Pure_Mithril"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_platinumfurnace" )
+
+
+----------------------------------------------------------------------Steel Workbench-----------------------------------------------
+local COMBI = {}
+
+COMBI.Name = "Bucket"
+COMBI.Description = "a simple bucket for simple needs"
+COMBI.Entity = "gms_steelworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 30
+COMBI.Req["Wood"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 30
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_bucket"
+
+GMS.RegisterCombi ( COMBI, "gms_steelworkbench")
+
+
+---------------------------------------------------------------------------Obelisk----------------------------------
+/*Obelisk*/
+local COMBI = {}
+
+COMBI.Name = "Obelisk"
+COMBI.Description = "A broken down obelisk used to make basic runes"
+
+COMBI.Req = {}
+COMBI.Req["Strange_Stone"] = 50
+
+COMBI.Results = "gms_obelisk"
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.BuildSiteModel = "models/props_c17/gravestone_cross001b.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+
+local COMBI = {}
+
+COMBI.Name = "Basic Rune"
+COMBI.Description = "the most basic rune used for inscribing"
+COMBI.Entity = "gms_obelisk"
+
+COMBI.Req = {}
+COMBI.Req["Strange_Stone"] = 5
+
+COMBI.Results = {}
+COMBI.Results["Basic_Rune"] = 1
+
+GMS.RegisterCombi ( COMBI, "gms_obelisk")
+
+local COMBI = {}
+
+COMBI.Name = "Chisel"
+COMBI.Description = "Effective in cutting stone"
+COMBI.Entity = "gms_obelisk"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 30
+COMBI.Req["Wood"] = 5
+COMBI.Req["Strange_Stone"] = 5
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 40
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_chisel"
+
+GMS.RegisterCombi ( COMBI, "gms_obelisk")
+
+
+
+----------------------------------------------------------Mithril Factory-----------------------------------------------
+/*Mithril Factory*/
+local COMBI = {}
+
+COMBI.Name = "Mithril Factory"
+COMBI.Description = "A advanced factor for faster smelting"
+
+COMBI.Req = {}
+COMBI.Req["Pure_Mithril"] = 400
+COMBI.Req["Teak"] = 50
+
+COMBI.Results = "gms_mithrilfactory"
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.BuildSiteModel = "models/props_wasteland/laundry_washer001a.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+/* Allsmelt Copper */
+local COMBI = {}
+
+COMBI.Name = "All Copper"
+COMBI.Description = "Copper can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Copper"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+/* Allsmelt Iron */
+local COMBI = {}
+
+COMBI.Name = "All Iron"
+COMBI.Description = "Iron can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Iron_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Iron"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+/* Allsmelt Tech */
+local COMBI = {}
+
+COMBI.Name = " All Tech "
+COMBI.Description = "Tech can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Tech"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+/* All Silver */
+local COMBI = {}
+
+COMBI.Name = "All Silver"
+COMBI.Description = "Silver can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Silver"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi ( COMBI, "gms_mithrilfactory" )
+
+/* All Gold */
+local COMBI = {}
+
+COMBI.Name = "All Gold"
+COMBI.Description = "Gold can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Gold"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+/* All Steel */
+local COMBI = {}
+
+COMBI.Name = "All Steel"
+COMBI.Description = "Steel can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Steel"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+/* All Platinum */
+local COMBI = {}
+
+COMBI.Name = "All Platinum"
+COMBI.Description = "Platinum can be used to create more advanced buildings and tools."
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Platinum"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+/* All Pure Mithrill */
+local COMBI = {}
+
+COMBI.Name = "Pure_Mithril"
+COMBI.Description = "Pure Mithril can be used to start of you industrial needs"
+COMBI.Entity = "gms_mithrilfactory"
+
+COMBI.Req = {}
+COMBI.Req["Mithril_Ore"] = 2
+
+COMBI.Results = {}
+COMBI.Results["Pure_Mithril"] = 1
+
+COMBI.AllSmelt = true
+COMBI.Max = 50
+
+GMS.RegisterCombi( COMBI, "gms_mithrilfactory" )
+
+------------------------------------------------------------Mythril Workbench-----------------------------------------------
+
+local COMBI = {}
+
+COMBI.Name = "Mithril WorkBench"
+COMBI.Description = "A very basic industrial crafting station"
+
+COMBI.Req = {}
+COMBI.Req["Pure_Mithril"] = 200
+COMBI.Req["Teak"] = 20
+
+COMBI.Results = "gms_mithrilworkbench"
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.BuildSiteModel = "models/props_wasteland/kitchen_counter001c.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+local COMBI = {}
+
+COMBI.Name = "Mithril Pickaxe"
+COMBI.Description = "A strange pickaxe that has a tendency to only mine a weird type of stone"
+COMBI.Entity = "gms_mithrilworkbench"
+
+COMBI.Req = {}
+COMBI.Req["Pure_Mithril"] = 50
+COMBI.Req["Teak"] = 25
+
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_mithrilpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_mithrilworkbench" )
+
+------------------------------------------------Rune Altar--------------------------------------
+local COMBI = {}
+
+COMBI.Name = "Rune Altar"
+COMBI.Description = "A basic Altar used for making runes"
+
+COMBI.Req = {}
+COMBI.Req["Strange_Stone"] = 100
+COMBI.Req["Stone"] = 500
+COMBI.Req["Basic_Rune"] = 10
+
+COMBI.Results = "gms_runealtar"
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.BuildSiteModel = "models/xqm/rails/cap.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+ local COMBI = {}
+
+COMBI.Name = "Fire Rune"
+COMBI.Description = "A rune infused with the element of fire"
+COMBI.Entity = "gms_runealtar"
+
+COMBI.Req = {}
+COMBI.Req["Basic_Rune"] = 1
+COMBI.Req["Charcoal"] = 10
+COMBI.Req["Strange_Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Fire_Rune"] = 1
+
+
+GMS.RegisterCombi( COMBI, "gms_runealtar" )
+
+local COMBI = {}
+
+COMBI.Name = "Water Rune"
+COMBI.Description = "A rune infused with the element of water"
+COMBI.Entity = "gms_runealtar"
+
+COMBI.Req = {}
+COMBI.Req["Basic_Rune"] = 1
+COMBI.Req["Water_Bottles"] = 10
+COMBI.Req["Strange_Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Water_Rune"] = 1
+
+
+GMS.RegisterCombi( COMBI, "gms_runealtar" )
+
+local COMBI = {}
+
+COMBI.Name = "Air Rune"
+COMBI.Description = "A rune infused with the element of air"
+COMBI.Entity = "gms_runealtar"
+
+COMBI.Req = {}
+COMBI.Req["Basic_Rune"] = 1
+COMBI.Req["Dust"] = 10
+COMBI.Req["Strange_Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Air_Rune"] = 1
+
+
+GMS.RegisterCombi( COMBI, "gms_runealtar" )
+
+local COMBI = {}
+
+COMBI.Name = "Earth Rune"
+COMBI.Description = "A rune infused with the element of earth"
+COMBI.Entity = "gms_runealtar"
+
+COMBI.Req = {}
+COMBI.Req["Basic_Rune"] = 1
+COMBI.Req["Wood"] = 10
+COMBI.Req["Strange_Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Earth_Rune"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_runealtar" )
+---------------------------------------------------Runic Infuser-----------------------------------
+local COMBI = {}
+
+COMBI.Name = "Runic Infuser"
+COMBI.Description = "A basic place for infusing tools"
+
+COMBI.Req = {}
+COMBI.Req["Strange_Stone"] = 200
+COMBI.Req["Stone"] = 200
+COMBI.Req["Basic_Rune"] = 20
+
+COMBI.Results = "gms_runicinfuser"
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.BuildSiteModel = "models/maxofs2d/hover_rings.mdl"
+
+GMS.RegisterCombi( COMBI, "Structures" )
+
+local COMBI = {}
+
+COMBI.Name = "Pickaxe Head"
+COMBI.Description = "it might be dull but it gets the job done"
+COMBI.Entity = "gms_runicinfuser"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 150
+COMBI.Req["Strange_Stone"] = 20
+
+COMBI.Results = {}
+COMBI.Results["Pickaxe_Head"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_runicinfuser" )
+
+local COMBI = {}
+
+COMBI.Name = "Pickaxe Handle"
+COMBI.Description = "a sturdy handle for a sturdy tool"
+COMBI.Entity = "gms_runicinfuser"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 100
+COMBI.Req["Strange_Stone"] = 15
+
+COMBI.Results = {}
+COMBI.Results["Pickaxe_Handle"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_runicinfuser" )
+
+local COMBI = {}
+
+COMBI.Name = "Air Rune Pickaxe"
+COMBI.Description = "A strange pickaxe that has a tendency to only mine a weird type of stone"
+COMBI.Entity = "gms_runicinfuser"
+
+COMBI.Req = {}
+COMBI.Req["Pickaxe_Head"] = 1
+COMBI.Req["Pickaxe_Handle"] = 1
+COMBI.Req["Air_Rune"] = 3
+COMBI.Req["Strange_Stone"] = 15
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_runeapickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_runicinfuser" )
+
+local COMBI = {}
+
+COMBI.Name = "Earth Rune Pickaxe"
+COMBI.Description = "A strange pickaxe that has a tendency to only mine a weird type of stone"
+COMBI.Entity = "gms_runicinfuser"
+
+COMBI.Req = {}
+COMBI.Req["Pickaxe_Head"] = 1
+COMBI.Req["Pickaxe_Handle"] = 1
+COMBI.Req["Earth_Rune"] = 3
+COMBI.Req["Strange_Stone"] = 15
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_runeepickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_runicinfuser" )
+
+local COMBI = {}
+
+COMBI.Name = "Fire Rune Pickaxe"
+COMBI.Description = "A strange pickaxe that has a tendency to only mine a weird type of stone"
+COMBI.Entity = "gms_runicinfuser"
+
+COMBI.Req = {}
+COMBI.Req["Pickaxe_Head"] = 1
+COMBI.Req["Pickaxe_Handle"] = 1
+COMBI.Req["Fire_Rune"] = 3
+COMBI.Req["Strange_Stone"] = 15
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_runefpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_runicinfuser" )
+
+local COMBI = {}
+
+COMBI.Name = "Water Rune Pickaxe"
+COMBI.Description = "A strange pickaxe that has a tendency to only mine a weird type of stone"
+COMBI.Entity = "gms_runicinfuser"
+
+COMBI.Req = {}
+COMBI.Req["Pickaxe_Head"] = 1
+COMBI.Req["Pickaxe_Handle"] = 1
+COMBI.Req["Water_Rune"] = 3
+COMBI.Req["Strange_Stone"] = 15
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "gms_runewpickaxe"
+
+GMS.RegisterCombi( COMBI, "gms_runicinfuser" )
+
+---------------------------------Grinding Stone--------------------
+local COMBI = {}
+
+COMBI.Name = "Dust x5"
+COMBI.Description = "A fine powder that floats through the wind"
+COMBI.Entity = "gms_grindingstone"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Dust"] = 5
+
+GMS.RegisterCombi( COMBI, "gms_grindingstone" )
+
+
+
+
+
+
+
+
+
diff --git a/ftp_gmstranded/gamemode/combirenbuy.lua b/ftp_gmstranded/gamemode/combirenbuy.lua
new file mode 100644
index 0000000..35d914f
--- /dev/null
+++ b/ftp_gmstranded/gamemode/combirenbuy.lua
@@ -0,0 +1,21 @@
+/* M9k USP */
+local COMBI = {}
+
+COMBI.Name = "Test"
+COMBI.Description = "A refined version of a pistol"
+COMBI.Entity = "gms_renbuyshop"
+
+COMBI.Req = {}
+COMBI.Req["Tech Gunslide"] = 1
+COMBI.Req["Tech Gungrip"] = 1
+COMBI.Req["Tech Gunbarrel"] = 1
+COMBI.Req["Tech Gunmagazine"] = 1
+
+COMBI.SkillReq = {}
+COMBI.SkillReq["Weapon_Crafting"] = 16
+COMBI.SkillReq["Hunting"] = 12
+
+COMBI.Texture = "gms_icons/gms_weapon.png"
+COMBI.SwepClass = "m9k_usp"
+
+GMS.RegisterCombi( COMBI, "gms_renbuyshop" ) \ No newline at end of file
diff --git a/ftp_gmstranded/gamemode/combirensell.lua b/ftp_gmstranded/gamemode/combirensell.lua
new file mode 100644
index 0000000..ea012bb
--- /dev/null
+++ b/ftp_gmstranded/gamemode/combirensell.lua
@@ -0,0 +1,1500 @@
+/* HolyRen */
+local COMBI = {}
+
+COMBI.Name = "HolyRen"
+COMBI.Description = "Converts Ren into HolyRen, an upgraded tier of Ren"
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Ren"] = 1000
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* RILL Ren */
+local COMBI = {}
+
+COMBI.Name = "RILL Ren"
+COMBI.Description = "Converts HolyRen into RILL Ren. RILL means Requiem Insignia Imprinted Ren"
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["HolyRen"] = 100
+
+COMBI.Results = {}
+COMBI.Results["RILLRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Stone */
+local COMBI = {}
+
+COMBI.Name = "Stone"
+COMBI.Description = "Converts an item into Ren, this will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Stone x10 */
+local COMBI = {}
+
+COMBI.Name = "Stone x10"
+COMBI.Description = "Converts an item into Ren, this will make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Stone"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Copper Ore*/
+local COMBI = {}
+
+COMBI.Name = "Copper Ore"
+COMBI.Description = "Converts an item into Ren, this will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Copper Ore x10 */
+local COMBI = {}
+
+COMBI.Name = "Copper Ore x10"
+COMBI.Description = "Converts an item into Ren, this will also make 250 Ren"
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Copper_Ore"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Copper Smelted */
+local COMBI = {}
+
+COMBI.Name = "Copper"
+COMBI.Description = "Converts an item into Ren, this will also make 50 Ren"
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Copper Smelted x10*/
+local COMBI = {}
+
+COMBI.Name = "Copper x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Copper"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Iron Smelted */
+local COMBI = {}
+
+COMBI.Name = "Iron"
+COMBI.Description = "Converts an item into Ren, this will also make 75 Ren"
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 75
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Iron Smelted x10 */
+local COMBI = {}
+
+COMBI.Name = "Iron x10"
+COMBI.Description = "Converts an item into Ren, This will also make 750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Iron"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Tech Smelted */
+local COMBI = {}
+
+COMBI.Name = "Tech"
+COMBI.Description = "Converts an item into Ren, This will also make 100 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 100
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Tech Smelted x10*/
+local COMBI = {}
+
+COMBI.Name = "Tech x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1 HolyRen."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Tech"] = 100
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Tech Ore */
+local COMBI = {}
+
+COMBI.Name = "Tech Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Tech Ore x10 */
+local COMBI = {}
+
+COMBI.Name = "Tech Ore x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Tech_Ore"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Silver */
+local COMBI = {}
+
+COMBI.Name = "Silver"
+COMBI.Description = "Converts an item into Ren, This will also make 125 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 125
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Silver x10 */
+local COMBI = {}
+
+COMBI.Name = "Silver x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Silver"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Silver Ore */
+local COMBI = {}
+
+COMBI.Name = "Silver Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 62 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 62
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Silver Ore x10 */
+local COMBI = {}
+
+COMBI.Name = "Silver Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 620 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Silver_Ore"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 620
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Gold */
+local COMBI = {}
+
+COMBI.Name = "Gold"
+COMBI.Description = "Converts an item into Ren, This will also make 150 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 150
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Gold x10*/
+local COMBI = {}
+
+COMBI.Name = "Gold x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Gold"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Gold Ore */
+local COMBI = {}
+
+COMBI.Name = "Gold Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 175 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 175
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Gold Ore x10*/
+local COMBI = {}
+
+COMBI.Name = "Gold Ore x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Gold_Ore"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Steel */
+local COMBI = {}
+
+COMBI.Name = "Steel"
+COMBI.Description = "Converts an item into Ren, This will also make 175 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 175
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Steel x10 */
+local COMBI = {}
+
+COMBI.Name = "Steel x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Steel"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Steel Ore */
+local COMBI = {}
+
+COMBI.Name = "Steel Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 87 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 87
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Steel Ore x10*/
+local COMBI = {}
+
+COMBI.Name = "Steel Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 870 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Steel_Ore"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 870
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Platinum */
+local COMBI = {}
+
+COMBI.Name = "Platinum"
+COMBI.Description = "Converts an item into Ren, This will also make 200 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 200
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Platinum x10*/
+local COMBI = {}
+
+COMBI.Name = "Platinum x10"
+COMBI.Description = "Converts an item into Ren, This will also make 2 HolyRen."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Platinum"] = 100
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 2
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Platinum Ore*/
+local COMBI = {}
+
+COMBI.Name = "Platinum Ore"
+COMBI.Description = "Converts an item into Ren, This will also make 100 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 100
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Platinum Ore x10*/
+local COMBI = {}
+
+COMBI.Name = "Platinum Ore x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1 HolyRen."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Platinum_Ore"] = 100
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Wood */
+local COMBI = {}
+
+COMBI.Name = "Wood"
+COMBI.Description = "Converts an item into Ren, This will also make 10 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 10
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Wood x10*/
+local COMBI = {}
+
+COMBI.Name = "Wood x10"
+COMBI.Description = "Converts an item into Ren, This will also make 10 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Wood"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 100
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Oak */
+local COMBI = {}
+
+COMBI.Name = "Oak"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Oak"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Oak x10*/
+local COMBI = {}
+
+COMBI.Name = "Oak x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Oak"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Cedar */
+local COMBI = {}
+
+COMBI.Name = "Cedar"
+COMBI.Description = "Converts an item into Ren, This will also make 75 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Cedar"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 75
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Cedar x10*/
+local COMBI = {}
+
+COMBI.Name = "Cedar x10"
+COMBI.Description = "Converts an item into Ren, This will also make 750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Cedar"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Maple */
+local COMBI = {}
+
+COMBI.Name = "Maple"
+COMBI.Description = "Converts an item into Ren, This will also make 100 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Maple"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 100
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Maple x10*/
+local COMBI = {}
+
+COMBI.Name = "Maple x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1 HolyRen."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Maple"] = 100
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Teak */
+local COMBI = {}
+
+COMBI.Name = "Teak"
+COMBI.Description = "Converts an item into Ren, This will also make 125 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Teak"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 125
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Teak x10*/
+local COMBI = {}
+
+COMBI.Name = "Teak x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Teak"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Mahogany */
+local COMBI = {}
+
+COMBI.Name = "Mahogany"
+COMBI.Description = "Converts an item into Ren, This will also make 150 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Mahogany"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 150
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Mahogany x10*/
+local COMBI = {}
+
+COMBI.Name = "Mahogany x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Mahogany"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Elm */
+local COMBI = {}
+
+COMBI.Name = "Elm"
+COMBI.Description = "Converts an item into Ren, This will also make 175 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Elm"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 175
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Elm x10*/
+local COMBI = {}
+
+COMBI.Name = "Elm x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Elm"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* WaterBottles */
+local COMBI = {}
+
+COMBI.Name = "Water Bottles"
+COMBI.Description = "Converts an item into Ren, This will also make 125 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Water_Bottles"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 125
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* WaterBottles x10*/
+local COMBI = {}
+
+COMBI.Name = "Water Bottles x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Water_Bottles"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Urine Bottles */
+local COMBI = {}
+
+COMBI.Name = "Urine Bottles"
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Urine_Bottles"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Urine Bottles x10*/
+local COMBI = {}
+
+COMBI.Name = "Urine Bottles x10"
+COMBI.Description = "Converts an item into Ren, This will also make 2500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Urine_Bottles"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+COMBI.Results["HolyRen"] = 2
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Saltpetre */
+local COMBI = {}
+
+COMBI.Name = "Saltpetre"
+COMBI.Description = "Converts an item into Ren, This will also make 150 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Saltpetre"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 150
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Saltpetre x10*/
+local COMBI = {}
+
+COMBI.Name = "Saltpetre x10"
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Saltpetre"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Charcoal */
+local COMBI = {}
+
+COMBI.Name = "Charcoal"
+COMBI.Description = "Converts an item into Ren, This will also make 150 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Charcoal"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 150
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Charcoal x10*/
+local COMBI = {}
+
+COMBI.Name = "Charcoal x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Charcoal"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 1500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Charcoal x10*/
+local COMBI = {}
+
+COMBI.Name = "Charcoal"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Charcoal 10"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Sulphur */
+local COMBI = {}
+
+COMBI.Name = "Sulphur"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Sulphur"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Sulphur x10*/
+local COMBI = {}
+
+COMBI.Name = "Sulphur x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Sulphur"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Gunpowder */
+local COMBI = {}
+
+COMBI.Name = "Gunpowder"
+COMBI.Description = "Converts an item into Ren, This will also make 325 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Gunpowder"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 325
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Gunpowder x10*/
+local COMBI = {}
+
+COMBI.Name = "Gunpowder x10"
+COMBI.Description = "Converts an item into Ren, This will also make 325 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Gunpowder"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+COMBI.Results["HolyRen"] = 3
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Herbs */
+local COMBI = {}
+
+COMBI.Name = "Herbs"
+COMBI.Description = "Converts an item into Ren, This will also make 325 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Herbs"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 325
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Herbs x10*/
+local COMBI = {}
+
+COMBI.Name = "Herbs x10"
+COMBI.Description = "Converts an item into Ren, This will also make 3250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Herbs"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+COMBI.Results["HolyRen"] = 3
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Spices */
+local COMBI = {}
+
+COMBI.Name = "Spices"
+COMBI.Description = "Converts an item into Ren, This will also make 650 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Spices"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 650
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Spices x10 */
+local COMBI = {}
+
+COMBI.Name = "Spices x10"
+COMBI.Description = "Converts an item into Ren, This will also make 6500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Spices"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+COMBI.Results["HolyRen"] = 6
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Banana Seeds */
+local COMBI = {}
+
+COMBI.Name = "Banana Seeds"
+COMBI.Description = "Converts an item into Ren, This will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Banana_Seeds"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Banana Seeds */
+local COMBI = {}
+
+COMBI.Name = "Banana Seeds x10"
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Banana_Seeds"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Watermelon Seeds */
+local COMBI = {}
+
+COMBI.Name = "Watermelon Seeds"
+COMBI.Description = "Converts an item into Ren, This will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Watermelon_Seeds"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Watermelon Seeds x10 */
+local COMBI = {}
+
+COMBI.Name = "Watermelon Seeds x10"
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Watermelon_Seeds"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+
+/* Orange Seeds */
+local COMBI = {}
+
+COMBI.Name = "Orange Seeds"
+COMBI.Description = "Converts an item into Ren, This will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Orange_Seeds"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Orange Seeds x10*/
+local COMBI = {}
+
+COMBI.Name = "Orange Seeds x10"
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Orange_Seeds"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Grain */
+local COMBI = {}
+
+COMBI.Name = "Grain Seeds"
+COMBI.Description = "Converts an item into Ren, This will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Grain_Seeds"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Grain x10*/
+local COMBI = {}
+
+COMBI.Name = "Grain Seeds x10"
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Grain_Seeds"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Berries */
+local COMBI = {}
+
+COMBI.Name = "Berries"
+COMBI.Description = "Converts an item into Ren, This will also make 30 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Berries"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 30
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Berries x10*/
+local COMBI = {}
+
+COMBI.Name = "Berries x10"
+COMBI.Description = "Converts an item into Ren, This will also make 300 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Berries"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 300
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Glass */
+local COMBI = {}
+
+COMBI.Name = "Glass"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Glass x10 */
+local COMBI = {}
+
+COMBI.Name = "Glass x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Glass"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Baits */
+local COMBI = {}
+
+COMBI.Name = "Baits"
+COMBI.Description = "Converts an item into Ren, This will also make 200 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Baits"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 200
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Baits x10*/
+local COMBI = {}
+
+COMBI.Name = "Baits x10"
+COMBI.Description = "Converts an item into Ren, This will also make 2 HolyRen."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Baits"] = 100
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 2
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Dough */
+local COMBI = {}
+
+COMBI.Name = "Dough"
+COMBI.Description = "Converts an item into Ren, This will also make 75 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Dough"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 75
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Dough x10 */
+local COMBI = {}
+
+COMBI.Name = "Dough x10"
+COMBI.Description = "Converts an item into Ren, This will also make 750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Dough"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Flour */
+local COMBI = {}
+
+COMBI.Name = "Flour"
+COMBI.Description = "Converts an item into Ren, This will also make 37 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Flour"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 37
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Flour x10 */
+local COMBI = {}
+
+COMBI.Name = "Flour x10"
+COMBI.Description = "Converts an item into Ren, This will also make 370 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Flour"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 370
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Meat */
+local COMBI = {}
+
+COMBI.Name = "Meat"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Meat"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Meat x10*/
+local COMBI = {}
+
+COMBI.Name = "Meat x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Meat"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Batteries */
+local COMBI = {}
+
+COMBI.Name = "Batteries"
+COMBI.Description = "Converts an item into Ren, This will also make 40 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Batteries"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 40
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Batteries x10*/
+local COMBI = {}
+
+COMBI.Name = "Batteries x10"
+COMBI.Description = "Converts an item into Ren, This will also make 400 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Batteries"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 400
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Sand */
+local COMBI = {}
+
+COMBI.Name = "Sand"
+COMBI.Description = "Converts an item into Ren, This will also make 25 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 25
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Sand x10 */
+local COMBI = {}
+
+COMBI.Name = "Sand x10 "
+COMBI.Description = "Converts an item into Ren, This will also make 250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Sand"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Bass */
+local COMBI = {}
+
+COMBI.Name = "Bass"
+COMBI.Description = "Converts an item into Ren, This will also make 50 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Bass"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 50
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Bass x10*/
+local COMBI = {}
+
+COMBI.Name = "Bass x10"
+COMBI.Description = "Converts an item into Ren, This will also make 500 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Bass"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 500
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Trout */
+local COMBI = {}
+
+COMBI.Name = "Trout"
+COMBI.Description = "Converts an item into Ren, This will also make 75 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Trout"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 75
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Trout x10*/
+local COMBI = {}
+
+COMBI.Name = "Trout x10"
+COMBI.Description = "Converts an item into Ren, This will also make 750 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Trout"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 750
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Salmon */
+local COMBI = {}
+
+COMBI.Name = "Salmon"
+COMBI.Description = "Converts an item into Ren, This will also make 100 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Salmon"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 100
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Salmon x10*/
+local COMBI = {}
+
+COMBI.Name = "Salmon x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1 HolyRen."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Salmon"] = 100
+
+COMBI.Results = {}
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Shark */
+local COMBI = {}
+
+COMBI.Name = "Shark"
+COMBI.Description = "Converts an item into Ren, This will also make 125 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Shark"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 125
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Shark x10*/
+local COMBI = {}
+
+COMBI.Name = "Shark x10"
+COMBI.Description = "Converts an item into Ren, This will also make 1250 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Shark"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 250
+COMBI.Results["HolyRen"] = 1
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Medicine */
+local COMBI = {}
+
+COMBI.Name = "Medicine"
+COMBI.Description = "Converts an item into Ren, This will also make 455 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Medicine"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 455
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Medicine x10 */
+local COMBI = {}
+
+COMBI.Name = "Medicine x10"
+COMBI.Description = "Converts an item into Ren, This will also make 4550 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Medicine"] = 100
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 550
+COMBI.Results["HolyRen"] = 4
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Flashlight */
+local COMBI = {}
+
+COMBI.Name = "Flash Light"
+COMBI.Description = "Converts an item into Ren, This will also make 140 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Flashlight"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 140
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Wrist Watch */
+local COMBI = {}
+
+COMBI.Name = "Wrist Watch"
+COMBI.Description = "Converts an item into Ren, This will also make 61 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Wrist Watch"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 61
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Welder */
+local COMBI = {}
+
+COMBI.Name = "Welder"
+COMBI.Description = "Converts an item into Ren, This will also make 455 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Welder"] = 1
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 35
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" )
+
+/* Medicine */
+local COMBI = {}
+
+COMBI.Name = "Medicine"
+COMBI.Description = "Converts an item into Ren, This will also make 455 Ren."
+COMBI.Entity = "gms_rensellshop"
+
+COMBI.Req = {}
+COMBI.Req["Medicine"] = 10
+
+COMBI.Results = {}
+COMBI.Results["Ren"] = 455
+
+GMS.RegisterCombi( COMBI, "gms_rensellshop" ) \ No newline at end of file
diff --git a/ftp_gmstranded/gamemode/init.lua b/ftp_gmstranded/gamemode/init.lua
new file mode 100644
index 0000000..5426d99
--- /dev/null
+++ b/ftp_gmstranded/gamemode/init.lua
@@ -0,0 +1,3256 @@
+
+-- Send clientside files
+AddCSLuaFile( "shared.lua" )
+AddCSLuaFile( "cl_init.lua" )
+AddCSLuaFile( "cl_scoreboard.lua" )
+AddCSLuaFile( "cl_qmenu.lua" )
+AddCSLuaFile( "cl_panels.lua" )
+AddCSLuaFile( "cl_hud.lua" )
+AddCSLuaFile( "unlocks.lua" )
+AddCSLuaFile( "combinations.lua" )
+AddCSLuaFile( "combinations2.lua" )
+AddCSLuaFile( "combirenbuy.lua" )
+AddCSLuaFile( "combirensell.lua" )
+AddCSLuaFile( "time_weather.lua" )
+AddCSLuaFile( "cl_deathmenu.lua" )
+
+include( "shared.lua" )
+include( "processes.lua" )
+include( "chatcommands.lua" )
+-- include( "resources.lua" )
+
+--Vars
+GM.NextSaved = 0
+GM.NextLoaded = 0
+
+--Locals
+local PlayerMeta = FindMetaTable( "Player" )
+local EntityMeta = FindMetaTable( "Entity" )
+
+--Tribes table
+if ( !GM.Tribes ) then
+ GM.Tribes = GM.Tribes or {}
+ table.insert( GM.Tribes, { name = "The Stranded", color = Color( 200, 200, 0 ), password = false } )
+ table.insert( GM.Tribes, { name = "Survivalists", color = Color( 225, 225, 225 ), password = false } )
+ table.insert( GM.Tribes, { name = "Anonymous", color = Color( 0, 145, 145 ), password = false } )
+ table.insert( GM.Tribes, { name = "The Gummies", color = Color( 255, 23, 0 ), password = false } )
+ table.insert( GM.Tribes, { name = "The Dynamics", color = Color( 0, 72, 255 ), password = false } )
+ table.insert( GM.Tribes, { name = "Scavengers", color = Color( 8, 255, 0 ), password = false } )
+end
+
+GM.AntlionBarrowSpawns = {}
+GM.AntlionBarrowSpawns[ "gm_construct" ] = { Vector( -4321.8149, -2551.3449, 257.5130 ) }
+GM.AntlionBarrowSpawns[ "gms_rollinghills" ] = { Vector( 3131.2876, -980.5972, 519.5605 ), Vector( -4225.0200, 6009.3516, 513.1411 ) }
+GM.AntlionBarrowSpawns[ "gms_rollinghills_daynight" ] = GM.AntlionBarrowSpawns[ "gms_rollinghills" ]
+GM.AntlionBarrowSpawns[ "gms_rollinghills_daynight_b1" ] = GM.AntlionBarrowSpawns[ "gms_rollinghills" ]
+
+GM.AntlionBarrowSpawns[ "gms_nowhere2" ] = { Vector( 3918.7753, 5111.8149, 7.5218 ), Vector( -2061.3061, 4842.8325, 7.6148 ) }
+GM.AntlionBarrowSpawns[ "gms_minisurvival_v2" ] = { Vector( -2818.7075, 3132.7507, -529.3529 ), Vector( -1423.5445, -1801.8461, -521.4026 ) }
+
+GM.AntlionBarrowSpawns[ "gms_coastal_outlands" ] = {
+
+Vector( 5682.056152, -504.173035, 181.781555 ),
+Vector( 5960.534180, 10054.454102, 83.857697 ),
+Vector( 2401.916504, 431.268372, -11125.555664 ),
+Vector( 3803.869141, 7341.371094, -11190.447266 ),
+Vector( 2804.810303, 12146.677734, -9125.259766 ),
+
+}
+
+GM.TreeSpawns = {}
+
+GM.TreeSpawns[ "gms_coastal_outlands" ] = {
+
+// The third coordinate is the height coordinate
+// Always subtract 70 to the height coord if it is positive so that the tree will be touching the floor
+
+Vector( 1462.160522, -3664.370361, -10941.564453 ),
+Vector( 3718.633545, -1710.644409, -11269.974609 ),
+Vector( 3159.402588, 145.593597, -11045.797852 ),
+Vector( 2519.847168, -547.534180, -11161.646484 ),
+Vector( 4932.186035, 4456.111328, -11258.104492 ),
+Vector( 4781.265137, 6047.670410, -11249.711914 ),
+Vector( 3673.399170, 5922.402832, -11243.965820 ),
+Vector( 3063.780273, 6409.881348, -11238.132813 ),
+Vector( 5274.083496, 8890.347656, -10530.000000 ),
+Vector( 5899.765137, 6888.799316, -10543.629883 ),
+Vector( 6781.679199, 6864.066895, -10404.078125 ),
+Vector( 7762.570313, 8027.228516, -9794.528320 ),
+Vector( 3582.199219, 8849.200195, -10587.720703 ),
+Vector( 2345.549072, 9190.130859, -9654.171875 ),
+Vector( -184.908630, 9758.339844, -9654.647461 ),
+Vector( -1548.173218, 10890.804688, -9306.844727 ),
+Vector( -791.436951, 11616.236328, -9311.025391 ),
+Vector( -1412.835571, 12691.185547, -9611.835938 ),
+Vector( 504.700775, 13039.500977, -9156.863281 ),
+Vector( 1297.606201, 12465.360352, -9147.304688 ),
+Vector( 2329.148193, 11747.046875, -9157.968750 ),
+Vector( 3458.504883, 9959.944336, -9299.968750 ),
+Vector( 5360.672363, 4706.935547, 344.907623 ),
+Vector( 4492.113281, 4696.718750, 319.830444 ),
+Vector( 4619.547852, 5449.032715, 407.463806 ),
+Vector( 5092.520508, 5595.101563, 535.216309 ),
+Vector( 5451.174805, 4665.181152, 354.842255 ),
+Vector( 4171.684570, 2509.103271, 370.570892 ),
+Vector( 5031.233398, 1786.687256, 311.406921 ),
+Vector( 4515.268555, 136.138535, 327.624390 ),
+Vector( 2986.565674, -3083.914551, 866.749268 ),
+Vector( 3086.577148, -7007.732910, 1510.264038 ),
+Vector( 3577.333252, -9913.345703, 1559.749146 ),
+Vector( 2075.320313, 9463.977539, 152.691238 ),
+Vector( 7145.083008, 8708.809570, -9852.012695 )
+
+}
+
+util.AddNetworkString('givePlayerWeapon')
+util.AddNetworkString('givePlayerResource')
+
+-- Give player weapons from grave
+net.Receive('givePlayerWeapon', function(len, ply)
+
+ local wepToGive = net.ReadString()
+ local wepSlot = net.ReadInt(32)
+ local weptbl = ply:GetEyeTrace().Entity.deathWeapons
+ table.remove(weptbl, wepSlot)
+
+ ply:Give(wepToGive)
+
+
+
+end)
+
+--Give player resource from grave
+net.Receive('givePlayerResource', function(len, ply)
+
+ local ResToGive = net.ReadString()
+ local Amount = net.ReadInt(32)
+ local resSlot = net.ReadInt(32)
+ local restbl = ply:GetEyeTrace().Entity.deathResources
+ local tbl1 = string.Split(restbl[resSlot], " ")
+ local tbl2 = string.Split(tbl1[2], "x")
+ local amt = tbl2[2]
+
+ ply:IncResource( ResToGive, Amount )
+
+ if (amt - Amount <= 0) then
+
+ table.remove(restbl, resSlot)
+ else
+ amt = amt - Amount
+ restbl[resSlot] = tbl1[1] .. " x" .. amt
+
+ end
+
+
+end)
+
+-- Custom anlion barrow auto placement
+hook.Add( "InitPostEntity", "gms_custom_antspawns", function()
+ if ( !GAMEMODE.AntlionBarrowSpawns[ game.GetMap() ] ) then return end
+ for id, pos in pairs( GAMEMODE.AntlionBarrowSpawns[ game.GetMap() ] ) do
+ local ent = ents.Create( "gms_antlionbarrow" )
+ ent:SetPos( pos )
+ ent:Spawn()
+ ent.GMSAutoSpawned = true
+ ent:SetNetworkedString( "Owner", "World" )
+ end
+
+end )
+
+-- Custom tree auto placement
+hook.Add( "InitPostEntity", "gms_custom_treespawns", function()
+
+ if ( !GAMEMODE.TreeSpawns[ game.GetMap() ] ) then return end
+ for id, pos in pairs( GAMEMODE.TreeSpawns[ game.GetMap() ] ) do
+ local ent = ents.Create( "gms_tree" )
+ ent:SetPos( pos )
+ ent:Spawn()
+ ent.GMSAutoSpawned = true
+ ent:SetNetworkedString( "Owner", "World" )
+ end
+end )
+
+-- Find tribe by ID
+function GM.FindTribeByID( id )
+ for tid, tabl in pairs( GAMEMODE.Tribes ) do
+ if ( tid == id ) then return tabl end
+ end
+ return false
+end
+
+-- Cancel process
+concommand.Add( "gms_cancelprocess", function( ply, cmd, args ) ply:CancelProcess() end )
+
+/* Menu toggles */
+function GM:ShowHelp( ply ) end
+function GM:ShowTeam( ply ) end
+function GM:ShowSpare1( ply ) end
+
+function GM:ShowSpare2( ply )
+ if ( ply:GetNWBool( "AFK" ) ) then
+ GAMEMODE.AFK( ply, "gms_afk", {} )
+ elseif ( ply:GetNWBool( "Sleeping" ) ) then
+ ply:Wakeup()
+ end
+ ply:CancelProcess()
+end
+
+
+/* ----------------------------------------------------------------------------------------------------
+ Player Functions
+---------------------------------------------------------------------------------------------------- */
+
+function PlayerMeta:SendMessage( text, duration, color )
+ if ( !IsValid( self ) ) then return end
+ local duration = duration or 3
+ local color = color or color_white
+
+ umsg.Start( "gms_sendmessage", self )
+ umsg.String( text )
+ umsg.Short( duration )
+ umsg.String( color.r .. "," .. color.g .. "," .. color.b .. "," .. color.a )
+ umsg.End()
+end
+
+function PlayerMeta:OpenCombiMenu( str )
+ umsg.Start( "gms_OpenCombiMenu", self )
+ umsg.String( str )
+ umsg.End()
+end
+
+util.AddNetworkString('deathmenu')
+
+function PlayerMeta:DeathMenu( res, wep )
+ net.Start('deathmenu')
+ net.WriteTable(res)
+ net.WriteTable(wep)
+ net.Send(self)
+end
+
+function PlayerMeta:SendAchievement( text )
+ umsg.Start( "gms_sendachievement", self )
+ umsg.String( text )
+ umsg.End()
+
+ local sound = CreateSound( self, Sound( "music/hl1_song11.mp3" ) )
+ sound:Play()
+ timer.Simple( 5.5, function() sound:Stop() end )
+end
+
+function PlayerMeta:SetSkill( skill, int )
+ skill = string.Capitalize( skill )
+ if ( !self.Skills[ skill ] ) then self.Skills[ skill ] = 0 end
+
+ if ( skill != "Survival" ) then
+ int = math.Clamp( int, 0, 200 )
+ else
+ self.MaxResources = ( int * 5 ) + 25
+ end
+ self.Skills[ skill ] = int
+
+ umsg.Start( "gms_SetSkill", self )
+ umsg.String( skill )
+ umsg.Short( self:GetSkill( skill ) )
+ umsg.End()
+end
+
+function PlayerMeta:GetSkill( skill )
+ skill = string.Capitalize( skill )
+ if ( skill == "Survival" ) then self:SetNWInt( skill, self.Skills[skill] ) end
+ return self.Skills[ skill ] or 0
+end
+
+function PlayerMeta:IncSkill( skill, int )
+ skill = string.Capitalize( skill )
+ if ( !self.Skills[ skill ] ) then self:SetSkill( skill, 0 ) end
+ if ( !self.Experience[ skill ] ) then self:SetXP( skill, 0 ) end
+
+ if ( skill != "Survival" ) then
+ int = math.Clamp( int, 0, 200 )
+ for id = 1, int do self:IncXP( "Survival", 20 ) end
+ self:SendMessage( string.Replace( skill, "_", " " ) .. " +" .. int, 3, Color( 10, 200, 10, 255 ) )
+ else
+ self.MaxResources = self.MaxResources + 5
+ self:SendAchievement( "Level Up!" )
+ end
+
+ self.Skills[skill] = self.Skills[skill] + int
+
+ umsg.Start( "gms_SetSkill", self )
+ umsg.String( skill )
+ umsg.Short( self:GetSkill( skill ) )
+ umsg.End()
+
+ self:CheckForUnlocks()
+end
+
+function PlayerMeta:DecSkill( skill, int )
+ skill = string.Capitalize( skill )
+ self.Skills[skill] = math.max( self.Skills[skill] - int, 0 )
+
+ umsg.Start( "gms_SetSkill", self )
+ umsg.String( skill )
+ umsg.Short( self:GetSkill( skill ) )
+ umsg.End()
+end
+
+function PlayerMeta:SetXP( skill, int )
+ skill = string.Capitalize( skill )
+ if ( !self.Skills[skill] ) then self:SetSkill( skill, 0 ) end
+ if ( !self.Experience[skill] ) then self.Experience[skill] = 0 end
+
+ self.Experience[skill] = int
+
+ umsg.Start( "gms_SetXP", self )
+ umsg.String( skill )
+ umsg.Short( self:GetXP( skill ) )
+ umsg.End()
+end
+
+function PlayerMeta:GetXP( skill )
+ skill = string.Capitalize( skill )
+ return self.Experience[skill] or 0
+end
+
+function PlayerMeta:IncXP( skill, int )
+ skill = string.Capitalize( skill )
+ if ( !self.Skills[skill] ) then self.Skills[skill] = 0 end
+ if ( !self.Experience[skill] ) then self.Experience[skill] = 0 end
+
+ if ( self.Experience[skill] + int >= 100 ) then
+ self.Experience[skill] = 0
+ self:IncSkill( skill, 1 )
+ else
+ self.Experience[skill] = self.Experience[skill] + int
+ end
+
+ umsg.Start( "gms_SetXP", self )
+ umsg.String( skill )
+ umsg.Short( self:GetXP( skill ) )
+ umsg.End()
+end
+
+function PlayerMeta:DecXP( skill, int )
+ skill = string.Capitalize( skill )
+ self.Experience[skill] = self.Experience[skill] - int
+
+ umsg.Start( "gms_SetXP", self )
+ umsg.String( skill )
+ umsg.Short( self:GetXP( skill ) )
+ umsg.End()
+end
+
+function PlayerMeta:SetResource( resource, int )
+ resource = string.Capitalize( resource )
+ if ( !self.Resources[resource] ) then self.Resources[resource] = 0 end
+
+
+ self.Resources[resource] = int
+
+ umsg.Start( "gms_SetResource", self )
+ umsg.String( resource )
+ umsg.Short( int )
+ umsg.End()
+end
+
+function PlayerMeta:GetResource( resource )
+ resource = string.Capitalize( resource )
+ return self.Resources[ resource ] or 0
+end
+
+function PlayerMeta:IncResource( resource, int )
+ resource = string.Capitalize( resource )
+
+ if ( !self.Resources[resource] ) then self.Resources[resource] = 0 end
+ local all = self:GetAllResources()
+ local max = self.MaxResources
+
+ if ( all + int > max ) then
+ self.Resources[resource] = self.Resources[resource] + ( max - all )
+ self:DropResource( resource, ( all + int ) - max )
+ self:SendMessage( "You can't carry anymore!", 3, Color( 200, 0, 0, 255 ) )
+ else
+ self.Resources[resource] = self.Resources[resource] + int
+ end
+
+ umsg.Start( "gms_SetResource", self )
+ umsg.String( resource )
+ umsg.Short( self:GetResource( resource ) )
+ umsg.End()
+end
+
+function PlayerMeta:DecResource( resource, int )
+ if ( !self.Resources[resource] ) then self.Resources[resource] = 0 end
+ self.Resources[resource] = self.Resources[resource] - int
+
+ local r = self.Resources[resource]
+ if ( resource == "Flashlight" and r < 1 ) then self:Flashlight( false ) end
+ if ( resource == "Batteries" ) then
+ local maxPow = 50
+ if ( r ) then maxPow = math.min( maxPow + r * 50, 500 ) end
+ self.Power = math.min( self.Power, maxPow )
+ self:UpdateNeeds()
+ end
+
+ umsg.Start( "gms_SetResource", self )
+ umsg.String( resource )
+ umsg.Short( self:GetResource( resource ) )
+ umsg.End()
+end
+
+function PlayerMeta:GetAllResources()
+ local num = 0
+
+ for k, v in pairs( self.Resources ) do
+ num = num + v
+ end
+
+ return num
+end
+
+function PlayerMeta:CreateBuildingSite( pos, angle, model, class, cost )
+ local rep = ents.Create( "gms_buildsite" )
+ rep:SetPos( pos )
+ rep:SetAngles( angle )
+ rep.Costs = cost
+ rep:Setup( model, class )
+ rep:Spawn()
+
+ rep.Player = self
+ rep.OwnerTable = { Team = self:Team(), SteamID = self:SteamID(), Name = self:Name(), EntIndex = self:EntIndex() }
+
+ self:SetNetworkedEntity( "Hasbuildingsite", rep )
+
+ SPropProtection.PlayerMakePropOwner( self , rep )
+ return rep
+end
+
+local NoDropModels = {
+ "models/props_c17/furniturefireplace001a.mdl",
+ "models/props_c17/factorymachine01.mdl",
+ "models/Gibs/airboat_broken_engine.mdl",
+ "models/props_c17/furniturestove001a.mdl",
+ "models/props_wasteland/controlroom_desk001b.mdl",
+ "models/props_c17/FurnitureFridge001a.mdl",
+ "models/props_lab/reciever_cart.mdl",
+ "models/props_trainstation/trainstation_clock001.mdl"
+}
+
+function PlayerMeta:CreateStructureBuildingSite( pos, angle, model, class, cost, name )
+ local rep = ents.Create( "gms_buildsite" )
+ local str = ":"
+ for k, v in pairs( cost ) do
+ str = str .. "\n" .. string.Replace( k, "_", " " ) .. " ( " .. v .. "x )"
+ end
+
+ rep:SetAngles( angle )
+ rep.Costs = cost
+ rep:Setup( model, class )
+ rep:SetPos( pos )
+ rep.Name = name
+ rep:SetNWString( "Name", name )
+ rep:SetNWString( "Resources", str )
+ rep:Spawn()
+
+ local cormin, cormax = rep:WorldSpaceAABB()
+ local offset = cormax - cormin
+
+ if ( model == "models/props_c17/FurnitureFridge001a.mdl" ) then pos = pos + Vector( 0, 0, 10 ) end
+ rep:SetPos( Vector( pos.x, pos.y, pos.z + ( offset.z / 2 ) ) )
+ if ( !table.HasValue( NoDropModels, model ) ) then
+ rep:DropToGround()
+ end
+
+ self:SetNWEntity( "Hasbuildingsite", rep )
+ rep.Player = self
+ rep.OwnerTable = { Team = self:Team(), SteamID = self:SteamID(), Name = self:Name(), EntIndex = self:EntIndex() }
+ SPropProtection.PlayerMakePropOwner( self, rep )
+ return rep
+end
+
+function PlayerMeta:GetBuildingSite()
+ return self:GetNWEntity( "Hasbuildingsite" )
+end
+
+function PlayerMeta:DropResource( resource, int )
+ local nearby = {}
+
+ for k, v in pairs( ents.FindByClass( "gms_resource*" ) ) do
+ if ( v:GetPos():Distance( self:GetPos() ) < 150 ) then
+ if ( v:GetClass() == "gms_resourcedrop" and v.Type != resource ) then
+ else
+ table.insert( nearby, v )
+ end
+ end
+ end
+
+ for id, ent in pairs( nearby ) do
+ if ( !SPropProtection.PlayerCanTouch( self, ent ) ) then continue end
+ if ( ent:GetClass() == "gms_resourcedrop" ) then
+ ent.Amount = ent.Amount + int
+ ent:SetResourceDropInfoInstant( ent.Type, ent.Amount )
+ return
+ else
+ if ( !ent.Resources ) then ent.Resources = {} end
+
+ if ( ent.Resources[ resource ] ) then
+ ent.Resources[ resource ] = ent.Resources[ resource ] + int
+ else
+ ent.Resources[ resource ] = int
+ end
+
+ ent:SetResPackInfo( resource, ent.Resources[ resource ] )
+ return
+ end
+ end
+
+ local ent = ents.Create( "gms_resourcedrop" )
+ ent:SetPos( self:TraceFromEyes( 60 ).HitPos + Vector( 0, 0, 15 ) )
+ ent:SetAngles( self:GetAngles() )
+ ent:Spawn()
+
+ ent:GetPhysicsObject():Wake()
+
+ ent.Type = resource
+ ent.Amount = int
+
+ ent:SetResourceDropInfo( ent.Type, ent.Amount )
+ SPropProtection.PlayerMakePropOwner( self, ent )
+end
+
+function PlayerMeta:SetFood( int )
+ if ( int > 1000 ) then
+ int = 1000
+ end
+
+ self.Hunger = int
+ self:UpdateNeeds()
+end
+
+function PlayerMeta:SetThirst( int )
+ if ( int > 1000 ) then
+ int = 1000
+ end
+
+ self.Thirst = int
+ self:UpdateNeeds()
+end
+
+function PlayerMeta:Heal( int )
+ self:SetHealth( math.min( self:Health() + int, self:GetMaxHealth() ) )
+end
+
+function PlayerMeta:AddUnlock( text )
+ self.FeatureUnlocks[text] = 1
+
+ umsg.Start( "gms_AddUnlock", self )
+ umsg.String( text )
+ umsg.End()
+
+ if ( GMS.FeatureUnlocks[text].OnUnlock ) then GMS.FeatureUnlocks[text].OnUnlock( self ) end
+end
+
+function PlayerMeta:HasUnlock( text )
+ if ( self.FeatureUnlocks and self.FeatureUnlocks[text] ) then return true end
+ return false
+end
+
+function PlayerMeta:CheckForUnlocks()
+ for k, unlock in pairs( GMS.FeatureUnlocks ) do
+ if ( !self:HasUnlock( k ) ) then
+ local NrReqs = 0
+
+ for skill, value in pairs( unlock.Req ) do
+ if ( self:GetSkill( skill ) >= value ) then
+ NrReqs = NrReqs + 1
+ end
+ end
+
+ if ( NrReqs == table.Count( unlock.Req ) ) then
+ self:AddUnlock( k )
+ end
+ end
+ end
+end
+
+function PlayerMeta:TraceFromEyes( dist )
+ return util.TraceLine( {
+ start = self:GetShootPos(),
+ endpos = self:GetShootPos() + ( self:GetAimVector() * dist ),
+ filter = self
+ } )
+end
+
+function PlayerMeta:UpdateNeeds()
+ umsg.Start( "gms_setneeds", self )
+ umsg.Short( self.Sleepiness )
+ umsg.Short( self.Hunger )
+ umsg.Short( self.Thirst )
+ umsg.Short( self.Oxygen )
+ umsg.Short( self.Power )
+ umsg.Short( Time )
+ umsg.End()
+end
+
+function PlayerMeta:PickupResourceEntity( ent )
+ if ( !SPropProtection.PlayerCanTouch( self, ent ) ) then return end
+
+ local int = ent.Amount
+ local room = self.MaxResources - self:GetAllResources()
+
+ if ( room <= 0 ) then self:SendMessage( "You can't carry anymore!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( room < int ) then int = room end
+ ent.Amount = ent.Amount - int
+ if ( ent.Amount <= 0 ) then ent:Fadeout() else ent:SetResourceDropInfo( ent.Type, ent.Amount ) end
+
+ self:IncResource( ent.Type, int )
+ self:SendMessage( "Picked up " .. string.Replace( ent.Type, "_", " " ) .. " ( " .. int .. "x )", 4, Color( 10, 200, 10, 255 ) )
+end
+
+function PlayerMeta:PickupResourceEntityPack( ent )
+ if ( !SPropProtection.PlayerCanTouch( self, ent ) ) then return end
+
+ if ( table.Count( ent.Resources ) > 0 ) then
+ for res, int in pairs( ent.Resources ) do
+ local room = self.MaxResources - self:GetAllResources()
+
+ if ( room <= 0 ) then self:SendMessage( "You can't carry anymore!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( room < int ) then int = room end
+ ent.Resources[res] = ent.Resources[res] - int
+
+ ent:SetResPackInfo( res, ent.Resources[res] )
+ if ( ent.Resources[res] <= 0 ) then ent.Resources[res] = nil end
+
+ self:IncResource( res, int )
+ self:SendMessage( "Picked up " .. string.Replace( res, "_", " " ) .. " ( " .. int .. "x )", 4, Color( 10, 200, 10, 255 ) )
+ end
+ end
+end
+
+function PlayerMeta:MakeLoadingBar( msg )
+ umsg.Start( "gms_MakeLoadingBar", self )
+ umsg.String( msg )
+ umsg.End()
+end
+
+function PlayerMeta:StopLoadingBar()
+ umsg.Start( "gms_StopLoadingBar",self )
+ umsg.End()
+end
+
+function PlayerMeta:MakeSavingBar( msg )
+ umsg.Start( "gms_MakeSavingBar", self )
+ umsg.String( msg )
+ umsg.End()
+end
+
+function PlayerMeta:StopSavingBar()
+ umsg.Start( "gms_StopSavingBar", self )
+ umsg.End()
+end
+
+function PlayerMeta:AllSmelt( ResourceTable )
+ local resourcedata = {}
+ resourcedata.Req = {}
+ resourcedata.Results = {}
+ local AmountReq = 0
+ for k, v in pairs( ResourceTable.Req ) do
+ if ( self:GetResource( k ) > 0 ) then
+ if ( self:GetResource( k ) <= ResourceTable.Max ) then
+ resourcedata.Req[k] = self:GetResource( k )
+ AmountReq = AmountReq + self:GetResource( k )
+ else
+ resourcedata.Req[k] = ResourceTable.Max
+ AmountReq = AmountReq + ResourceTable.Max
+ self:SendMessage( "You can only do " .. tostring( ResourceTable.Max ) .. " " .. string.Replace( k, "_", " " ) .. " at a time.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ resourcedata.Req[k] = 1
+ end
+ end
+ for k, v in pairs( ResourceTable.Results ) do
+ resourcedata.Results[k] = AmountReq
+ end
+ return resourcedata
+end
+
+function PlayerMeta:Sleep()
+ if ( !self:Alive() or self:GetNWBool( "Sleeping" ) or self:GetNWBool( "AFK" ) ) then return end
+ if ( self.Sleepiness > 700 ) then self:SendMessage( "You're not tired enough.", 3, Color( 255, 255, 255, 255 ) ) return end
+
+ self:SetNWBool( "Sleeping", true )
+ self:Freeze( true )
+
+ -- Check for shelter
+ local tr = util.TraceLine( {
+ start = self:GetShootPos(),
+ endpos = self:GetShootPos() + ( self:GetUp() * 300 ),
+ filter = self
+ } )
+
+ self.NeedShelter = false
+ if ( !tr.HitWorld and !tr.HitNonWorld ) then
+ self.NeedShelter = true
+ end
+
+ self:EmitSound( "stranded/start_sleeping.wav" )
+end
+
+function PlayerMeta:Wakeup()
+ if ( !self:GetNWBool( "Sleeping" ) ) then return end
+ self:SetNWBool( "Sleeping", false )
+ self:Freeze( false )
+
+ --Check for shelter
+ local trace = {}
+ trace.start = self:GetShootPos()
+ trace.endpos = trace.start + ( self:GetUp() * 300 )
+ trace.filter = self
+
+ local tr = util.TraceLine( trace )
+
+ if ( self.NeedShelter ) then
+ self:SendMessage( "I should get something to sleep under next time...", 6, Color( 200, 0, 0, 255 ) )
+ else
+ self:SendMessage( "Ah, nothing like a good nights sleep!", 5, Color( 255, 255, 255, 255 ) )
+ end
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Entity Functions
+---------------------------------------------------------------------------------------------------- */
+
+function EntityMeta:SetResourceDropInfo( strType, int )
+ timer.Simple( 0.5, function() self:SetResourceDropInfoInstant( strType, int ) end )
+end
+
+function EntityMeta:SetResourceDropInfoInstant( strType, int )
+ for k, v in pairs( player.GetAll() ) do
+ local strType = strType or "Error"
+ umsg.Start( "gms_SetResourceDropInfo", v )
+ umsg.String( self:EntIndex() )
+ umsg.String( string.gsub( strType, "_", " " ) )
+ umsg.Short( self.Amount )
+ umsg.End()
+ end
+end
+
+function EntityMeta:SetResPackInfo( strType, int )
+ for k, v in pairs( player.GetAll() ) do
+ local strType = strType or "Error"
+ umsg.Start( "gms_SetResPackInfo", v )
+ umsg.String( self:EntIndex() )
+ umsg.String( string.gsub( strType, "_", " " ) )
+ umsg.Short( int )
+ umsg.End()
+ end
+end
+
+
+function EntityMeta:SetFoodInfo( strType )
+ timer.Simple( 0.5, function() self:SetFoodInfoInstant( strType ) end )
+end
+
+function EntityMeta:SetFoodInfoInstant( strType )
+ for k, v in pairs( player.GetAll() ) do
+ local strType = strType or "Error"
+ umsg.Start( "gms_SetFoodDropInfo", v )
+ umsg.String( self:EntIndex() )
+ umsg.String( string.gsub( strType, "_", " " ) )
+ umsg.End()
+ end
+end
+
+function EntityMeta:DropToGround()
+ local trace = {}
+ trace.start = self:GetPos()
+ trace.endpos = trace.start + Vector( 0, 0, -100000 )
+ trace.mask = MASK_SOLID_BRUSHONLY
+ trace.filter = self
+
+ local tr = util.TraceLine( trace )
+
+ self:SetPos( tr.HitPos )
+end
+
+function GM.ReproduceTrees()
+ local GM = GAMEMODE
+ if ( GetConVarNumber( "gms_ReproduceTrees" ) == 1 ) then
+ local trees = {}
+ for k, v in pairs( ents.GetAll() ) do
+ if ( v:IsTreeModel() ) then
+ table.insert( trees, v )
+ end
+ end
+
+ if ( #trees < GetConVarNumber( "gms_MaxReproducedTrees" ) ) then
+ for k, ent in pairs( trees ) do
+ local num = math.random( 1, 3 )
+
+ if ( num == 1 ) then
+ local nearby = {}
+ for k, v in pairs( ents.FindInSphere( ent:GetPos(), 50 ) ) do
+ if ( v:GetClass() == "gms_seed" or v:IsProp() ) then
+ table.insert( nearby, v )
+ end
+ end
+
+ if ( #nearby < 3 ) then
+ local pos = ent:GetPos() + Vector( math.random( -500, 500 ), math.random( -500, 500 ), 0 )
+ local retries = 50
+
+ while ( ( pos:Distance( ent:GetPos() ) < 200 or GMS.ClassIsNearby( pos, "prop_physics", 100 ) ) and retries > 0 ) do
+ pos = ent:GetPos() + Vector( math.random( -300, 300 ),math.random( -300, 300 ), 0 )
+ retries = retries - 1
+ end
+
+ local pos = pos + Vector( 0, 0, 500 )
+
+ local seed = ents.Create( "gms_seed" )
+ seed:SetPos( pos )
+ seed:DropToGround()
+ seed:Setup( "tree", 180 )
+ seed:SetNetworkedString( "Owner", "World" )
+ seed:Spawn()
+ end
+ end
+ end
+ end
+ if ( #trees == 0 ) then
+ local info = {}
+ for i = 1, 20 do
+ info.pos = Vector( math.random( -10000, 10000 ), math.random( -10000, 10000 ), 1000 )
+ info.Retries = 50
+
+ --Find pos in world
+ while ( util.IsInWorld( info.pos ) == false and info.Retries > 0 ) do
+ info.pos = Vector( math.random( -10000, 10000 ),math.random( -10000, 10000 ), 1000 )
+ info.Retries = info.Retries - 1
+ end
+
+ --Find ground
+ local trace = {}
+ trace.start = info.pos
+ trace.endpos = trace.start + Vector( 0, 0, -100000 )
+ trace.mask = MASK_SOLID_BRUSHONLY
+
+ local groundtrace = util.TraceLine( trace )
+
+ --Assure space
+ local nearby = ents.FindInSphere( groundtrace.HitPos, 200 )
+ info.HasSpace = true
+
+ for k, v in pairs( nearby ) do
+ if ( v:IsProp() ) then
+ info.HasSpace = false
+ end
+ end
+
+ --Find sky
+ local trace = {}
+ trace.start = groundtrace.HitPos
+ trace.endpos = trace.start + Vector( 0, 0, 100000 )
+
+ local skytrace = util.TraceLine( trace )
+
+ --Find water?
+ local trace = {}
+ trace.start = groundtrace.HitPos
+ trace.endpos = trace.start + Vector( 0, 0, 1 )
+ trace.mask = MASK_WATER
+
+ local watertrace = util.TraceLine( trace )
+
+ --All a go, make entity
+ if ( info.HasSpace and skytrace.HitSky and !watertrace.Hit and ( groundtrace.MatType == MAT_DIRT or groundtrace.MatType == MAT_GRASS or groundtrace.MatType == MAT_SAND ) ) then
+ local seed = ents.Create( "gms_seed" )
+ seed:SetPos( groundtrace.HitPos )
+ seed:DropToGround()
+ seed:Setup( "tree", 180 + math.random( -20, 20 ) )
+ seed:SetNetworkedString( "Owner", "World" )
+ seed:Spawn()
+ end
+ end
+ end
+ end
+
+ timer.Simple( math.random( 1, 3 ) * 60, function() GM.ReproduceTrees() end )
+end
+timer.Simple( 60, function() GAMEMODE.ReproduceTrees() end )
+
+GMS.LootableNPCs = { "npc_antlion", "npc_antlionguard", "npc_crow", "npc_seagull", "npc_pigeon", "npc_zombie" }
+
+function EntityMeta:IsLootableNPC()
+ return table.HasValue( GMS.LootableNPCs, self:GetClass() )
+end
+
+function EntityMeta:MakeCampfire()
+ if ( GetConVarNumber( "gms_campfire" ) <= 0 ) then return end
+
+ local min, max = self:OBBMins(), self:OBBMaxs()
+ local vol = math.abs( max.x - min.x ) * math.abs( max.y - min.y ) * math.abs( max.z - min.z )
+ local mul = math.min( math.sqrt( vol ) / 200, 1 )
+
+ if ( !self.CampFire ) then self:SetHealth( 1337 ) end
+ self.CampFire = true
+
+ timer.Create( "gms_removecampfire_" .. self:EntIndex(), 480 * mul, 1, function() if ( IsValid( self ) ) then self:Fadeout() end end )
+
+ if ( GetConVarNumber( "gms_SpreadFire" ) >= 1 ) then
+ self:Ignite( 360, ( self:OBBMins() - self:OBBMaxs() ):Length() + 10 )
+ else
+ self:Ignite( 360, 0.001 )
+ end
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Entity Fading
+---------------------------------------------------------------------------------------------------- */
+
+GMS.FadingOutProps = {}
+GMS.FadingInProps = {}
+
+function EntityMeta:Fadeout( speed )
+ if ( !IsValid( self ) ) then return end
+ local speed = speed or 1
+
+ for k, v in pairs( player.GetAll() ) do
+ umsg.Start( "gms_CreateFadingProp", v )
+ umsg.String( self:GetModel() )
+ umsg.Vector( self:GetPos() )
+ local ang = self:GetAngles()
+ umsg.Vector( Vector( ang.p, ang.y, ang.r ) )
+ local col = self:GetColor()
+ umsg.Vector( Vector( col.r, col.g, col.b ) )
+ umsg.Short( math.Round( speed ) )
+ umsg.End()
+ end
+
+ self:Remove()
+end
+
+--Fadein is serverside
+function EntityMeta:Fadein( speed )
+ self.AlphaFade = 0
+ self:SetRenderMode( RENDERMODE_TRANSALPHA )
+ self:SetColor( Color( 255, 255, 255, 0 ) )
+ self.FadeInSpeed = speed or 4
+ table.insert( GMS.FadingInProps, self )
+end
+
+hook.Add( "Think", "gms_FadePropsThink", function()
+ for k, ent in pairs( GMS.FadingInProps ) do
+ if ( !ent or ent == NULL ) then
+ table.remove( GMS.FadingInProps, k )
+ elseif ( !IsValid( ent ) ) then
+ table.remove( GMS.FadingInProps, k )
+ elseif ( ent.AlphaFade >= 255 ) then
+ table.remove( GMS.FadingInProps, k )
+ else
+ ent.AlphaFade = ent.AlphaFade + ent.FadeInSpeed
+ ent:SetColor( Color( 255, 255, 255, ent.AlphaFade ) )
+ end
+ end
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Entity rising / lowering ( Used by gms_seed )
+---------------------------------------------------------------------------------------------------- */
+
+GM.RisingProps = {}
+GM.SinkingProps = {}
+
+function EntityMeta:RiseFromGround( speed, altmax )
+ local speed = speed or 1
+ local max;
+
+ if ( !altmax ) then
+ min, max = self:WorldSpaceAABB()
+ max = max.z
+ else
+ max = altmax
+ end
+
+ local tbl = {}
+ tbl.Origin = self:GetPos().z
+ tbl.Speed = speed
+ tbl.Entity = self
+
+ self:SetPos( self:GetPos() + Vector( 0, 0, -max + 10 ) )
+ table.insert( GAMEMODE.RisingProps, tbl )
+end
+
+function EntityMeta:SinkIntoGround( speed )
+ local speed = speed or 1
+
+ local tbl = {}
+ tbl.Origin = self:GetPos().z
+ tbl.Speed = speed
+ tbl.Entity = self
+ tbl.Height = max
+
+ table.insert( GAMEMODE.SinkingProps, tbl )
+end
+
+hook.Add( "Think", "gms_RiseAndSinkPropsHook", function()
+ for k, tbl in pairs( GAMEMODE.RisingProps ) do
+ if ( !IsValid( tbl.Entity ) || tbl.Entity:GetPos().z >= tbl.Origin ) then
+ table.remove( GAMEMODE.RisingProps, k )
+ else
+ tbl.Entity:SetPos( tbl.Entity:GetPos() + Vector( 0, 0, 1 * tbl.Speed ) )
+ end
+ end
+
+ for k, tbl in pairs( GAMEMODE.SinkingProps ) do
+ if ( !IsValid( tbl.Entity ) || tbl.Entity:GetPos().z <= tbl.Origin - tbl.Height ) then
+ table.remove( GAMEMODE.SinkingProps, k )
+ tbl.Entity:Remove()
+ else
+ tbl.Entity:SetPos( tbl.Entity:GetPos() + Vector( 0, 0, -1 * tbl.Speed ) )
+ end
+ end
+end )
+
+/* ----------------------------------------------------------------------------------------------------
+ Admin commands
+---------------------------------------------------------------------------------------------------- */
+
+concommand.Add( "gms_admin_maketree", function( ply )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 10000 )
+ GAMEMODE.MakeTree( tr.HitPos )
+end )
+
+concommand.Add( "gms_admin_makerock", function( ply )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 10000 )
+ GAMEMODE.MakeGenericPlant( ply, tr.HitPos, GMS.RockModels[ math.random( 1, #GMS.RockModels ) ], true )
+end )
+
+concommand.Add( "gms_admin_makefood", function( ply )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 10000 )
+ local ent = ents.Create( "prop_physics" )
+ ent:SetAngles( Angle( 0, math.random( 1, 360 ), 0 ) )
+ ent:SetModel( GMS.EdibleModels[math.random( 1, #GMS.EdibleModels )] )
+ ent:SetPos( tr.HitPos + Vector( 0, 0, 10 ) )
+ ent:Spawn()
+ SPropProtection.PlayerMakePropOwner( ply, ent )
+end )
+
+concommand.Add( "gms_admin_makeantlionbarrow", function( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( !args[1] ) then ply:SendMessage( "Specify max antlions!", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 10000 )
+ local ent = ents.Create( "gms_antlionbarrow" )
+ ent:SetPos( tr.HitPos )
+ ent:Spawn()
+ ent:SetNetworkedString( "Owner", "World" )
+ ent:SetKeyValue( "MaxAntlions", args[1] )
+end )
+
+concommand.Add( "gms_admin_makeplant", function( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ local tr = ply:TraceFromEyes( 10000 )
+ local typ = tonumber( args[ 1 ] ) or math.random( 1, 5 )
+ local pos = tr.HitPos
+
+ if ( typ == 1 ) then
+ GAMEMODE.MakeMelon( pos, math.random( 1, 3 ), ply )
+ elseif ( typ == 2 ) then
+ GAMEMODE.MakeBanana( pos, math.random( 1, 3 ), ply )
+ elseif ( typ == 3 ) then
+ GAMEMODE.MakeOrange( pos, math.random( 1, 3 ), ply )
+ elseif ( typ == 4 ) then
+ GAMEMODE.MakeBush( pos, ply )
+ elseif ( typ == 5 ) then
+ GAMEMODE.MakeGrain( pos, ply )
+ end
+end )
+
+concommand.Add( "gms_admin_populatearea", function( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( !args[1] or !args[2] or !args[3] ) then ply:SendMessage( "You need to specify <type> <amount> <radius>", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ for k, v in pairs( player.GetAll() ) do
+ v:SendMessage( "Populating area...", 3, Color( 255, 255, 255, 255 ) )
+ end
+
+ --Population time
+ local Amount = tonumber( args[2] ) or 10
+ local info = {}
+ info.Amount = Amount
+
+ if ( Amount > 200 ) then
+ ply:SendMessage( "Auto-capped at 200 props.", 3, Color( 200, 0, 0, 255 ) )
+ info.Amount = 200
+ end
+
+ local Type = args[1]
+ local Amount = info.Amount
+ local Radius = tonumber( args[3] ) or 1000
+
+ --Find playertrace
+ local plytrace = ply:TraceFromEyes( 10000 )
+
+ for i = 1, Amount do
+ info.pos = plytrace.HitPos + Vector( math.random( -Radius, Radius ), math.random( -Radius, Radius ), 1000 )
+ info.Retries = 50
+
+ --Find pos in world
+ while ( util.IsInWorld( info.pos ) == false and info.Retries > 0 ) do
+ info.pos = plytrace.HitPos + Vector( math.random( -Radius, Radius ), math.random( -Radius, Radius ), 1000 )
+ info.Retries = info.Retries - 1
+ end
+
+ --Find ground
+ local trace = {}
+ trace.start = info.pos
+ trace.endpos = trace.start + Vector( 0, 0, -100000 )
+ trace.mask = MASK_SOLID_BRUSHONLY
+
+ local groundtrace = util.TraceLine( trace )
+
+ --Assure space
+ local nearby = ents.FindInSphere( groundtrace.HitPos, 200 )
+ info.HasSpace = true
+
+ for k, v in pairs( nearby ) do
+ if ( v:IsProp() ) then
+ info.HasSpace = false
+ end
+ end
+
+ --Find sky
+ local trace = {}
+ trace.start = groundtrace.HitPos
+ trace.endpos = trace.start + Vector( 0, 0, 100000 )
+
+ local skytrace = util.TraceLine( trace )
+
+ --Find water?
+ local trace = {}
+ trace.start = groundtrace.HitPos
+ trace.endpos = trace.start + Vector( 0, 0, 1 )
+ trace.mask = MASK_WATER
+
+ local watertrace = util.TraceLine( trace )
+
+ --All a go, make entity
+ if ( Type == "Trees" ) then
+ if ( info.HasSpace and skytrace.HitSky and !watertrace.Hit and ( groundtrace.MatType == MAT_DIRT or groundtrace.MatType == MAT_GRASS or groundtrace.MatType == MAT_SAND ) ) then
+ GAMEMODE.MakeTree( groundtrace.HitPos )
+ end
+ elseif ( Type == "Rocks" ) then
+ if ( !watertrace.Hit and ( groundtrace.MatType == MAT_DIRT or groundtrace.MatType == MAT_GRASS or groundtrace.MatType == MAT_SAND ) ) then
+ local ent = ents.Create( "prop_physics" )
+ ent:SetAngles( Angle( 0, math.random( 1, 360 ), 0 ) )
+ ent:SetModel( GMS.RockModels[math.random( 1, #GMS.RockModels )] )
+ ent:SetPos( groundtrace.HitPos )
+ ent:Spawn()
+ ent:SetNetworkedString( "Owner", "World" )
+ ent:Fadein()
+ ent.PhysgunDisabled = true
+ ent:GetPhysicsObject():EnableMotion( false )
+ end
+ elseif ( Type == "Random_Plant" and info.HasSpace ) then
+ if ( !watertrace.Hit and ( groundtrace.MatType == MAT_DIRT or groundtrace.MatType == MAT_GRASS or groundtrace.MatType == MAT_SAND ) ) then
+ local typ = math.random( 1, 5 )
+ local pos = groundtrace.HitPos
+
+ if ( typ == 1 ) then
+ GAMEMODE.MakeMelon( pos,math.random( 1, 2 ), ply )
+ elseif ( typ == 2 ) then
+ GAMEMODE.MakeBanana( pos,math.random( 1, 2 ), ply )
+ elseif ( typ == 3 ) then
+ GAMEMODE.MakeOrange( pos,math.random( 1, 2 ), ply )
+ elseif ( typ == 4 ) then
+ GAMEMODE.MakeBush( pos, ply )
+ elseif ( typ == 5 ) then
+ GAMEMODE.MakeGrain( pos, ply )
+ end
+ end
+ end
+ end
+
+ --Finished
+ for k, v in pairs( player.GetAll() ) do
+ v:SendMessage( "Done!", 3, Color( 255, 255, 255, 255 ) )
+ end
+end )
+
+concommand.Add( "gms_admin_clearmap", function( ply )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ for k, v in pairs( ents.GetAll() ) do
+ if ( v:IsRockModel() or v:IsTreeModel() ) then
+ for k, tbl in pairs( GAMEMODE.RisingProps ) do
+ if ( tbl.Entity == v ) then
+ table.remove( GAMEMODE.RisingProps, k )
+ end
+ end
+ for k, tbl in pairs( GAMEMODE.SinkingProps ) do
+ if ( tbl.Entity == v ) then
+ table.remove( GAMEMODE.SinkingProps, k )
+ end
+ end
+ for k, ent in pairs( GAMEMODE.FadingInProps ) do
+ if ( ent == v ) then
+ table.remove( GAMEMODE.FadingInProps, k )
+ end
+ end
+ v:Fadeout()
+ end
+ end
+
+ for k, v in pairs( player.GetAll() ) do v:SendMessage( "Cleared map.", 3, Color( 255, 255, 255, 255 ) ) end
+end )
+
+concommand.Add( "gms_admin_saveallcharacters", function( ply )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ for k, v in pairs( player.GetAll() ) do
+ v:SaveCharacter()
+ end
+
+ ply:SendMessage( "Saved characters on all current players.", 3, Color( 255, 255, 255, 255 ) )
+end )
+
+function GM.ADropResource( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( args == nil or args[1] == nil ) then ply:SendMessage( "You need to at least give a resource type!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ args[1] = string.Capitalize( args[1] )
+ if ( args[2] == nil or string.lower( args[2] ) == "all" ) then args[2] = tostring( ply:GetResource( args[1] ) ) end
+ if ( tonumber( args[2] ) <= 0 ) then ply:SendMessage( "No zeros/negatives!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ local int = tonumber( args[2] )
+ local Type = args[1]
+
+ ply:DropResource( Type, int )
+ ply:SendMessage( "Dropped " .. string.Replace( Type, "_", " " ) .. " ( " .. int .. "x )", 3, Color( 10, 200, 10, 255 ) )
+end
+concommand.Add( "gms_ADropResources", GM.ADropResource )
+
+/* ----------------------------------------------------------------------------------------------------
+ Console Commands
+---------------------------------------------------------------------------------------------------- */
+
+concommand.Add( "gms_dropall", function( ply )
+ local DeltaTime = 0
+ for k, v in pairs( ply.Resources ) do
+ if ( v > 0 ) then
+ timer.Simple( DeltaTime, function() ply:DecResource( k, v ) ply:DropResource( k, v ) end, ply, k, v )
+ DeltaTime = DeltaTime + 0.2
+ end
+ end
+ ply.NextSpawnTime = CurTime() + DeltaTime + 0.5
+end )
+
+concommand.Add( "gms_salvage", function( ply )
+ if ( ply.InProcess ) then return end
+
+ local tr = ply:TraceFromEyes( 100 )
+ if ( !tr.HitNonWorld ) then return end
+
+ local ent = tr.Entity
+
+ if ( ent:GetClass() != "gms_buildsite" && ( table.HasValue( GMS.StructureEntities, ent:GetClass() ) || ent.NormalProp == true ) && SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ ply:DoProcess( "Salvage", 6, { Entity = ent, MatType = tr.MatType } )
+ else
+ ply:SendMessage( "Cannot salvage this kind of prop.", 5, Color( 255, 255, 255, 255 ) )
+ end
+end )
+
+concommand.Add( "gms_steal", function( ply, cmd, args )
+ local tr = ply:TraceFromEyes( 100 )
+ local ent = tr.Entity
+
+ if ( ply:GetSkill( "Survival" ) < 30 ) then ply:SendMessage( "You can only steal at survival level 30+.", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( !IsValid( ent ) || !tr.HitNonWorld || ent:IsNPC() || ent:IsPlayer() || ent:GetClass() == "gms_buildsite" || ent:GetClass() == "gms_seed" || ent:GetNWString( "Owner", "None" ) == "World" || SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ ply:SendMessage( "You can't steal this.", 3, Color( 200, 0, 0, 255 ) )
+ return
+ end
+
+ local cls = ent:GetClass()
+ local time = math.max( ent:GetVolume(), 1 )
+ if ( cls == "gms_resourcedrop" ) then
+ time = ent.Amount * 0.5
+ elseif ( cls == "gms_resourcepack" or cls == "gms_fridge" ) then
+ for r, n in pairs( ent.Resources ) do
+ time = time + ( n * 0.25 )
+ end
+ end
+
+ time = math.max( time - math.floor( ply:GetSkill( "Stealing" ) / 3 ), math.max( time * 0.25, 2 ) )
+ ply:DoProcess( "Steal", time, { Ent = ent } )
+end )
+
+function GM.PlantMelon( ply, cmd, args )
+ if ( ply:GetNWInt( "plants" ) >= GetConVarNumber( "gms_PlantLimit" ) ) then
+ ply:SendMessage( "You have hit the plant limit.", 3, Color( 200, 0, 0, 255 ) )
+ return
+ end
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( tr.HitWorld ) then
+ if ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND ) and !GMS.IsInWater( tr.HitPos ) then
+ if ( ply:GetResource( "Melon_Seeds" ) >= 1 ) then
+ if ( !GMS.ClassIsNearby( tr.HitPos, "gms_seed", 30 ) and !GMS.ClassIsNearby( tr.HitPos, "prop_physics", 50 ) ) then
+ local data = {}
+ data.Pos = tr.HitPos
+ ply:DoProcess( "PlantMelon", 3, data )
+ else
+ ply:SendMessage( "You need more distance between seeds/props.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You need a watermelon seed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You cannot plant on this terrain.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "Aim at the ground to plant.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+concommand.Add( "gms_plantmelon", GM.PlantMelon )
+
+function GM.PlantBanana( ply, cmd, args )
+ if ( ply:GetNWInt( "plants" ) >= GetConVarNumber( "gms_PlantLimit" ) ) then ply:SendMessage( "You have hit the plant limit.", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( tr.HitWorld ) then
+ if ( ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND ) and !GMS.IsInWater( tr.HitPos ) ) then
+ if ( ply:GetResource( "Banana_Seeds" ) >= 1 ) then
+ if ( !GMS.ClassIsNearby( tr.HitPos, "gms_seed", 30 ) and !GMS.ClassIsNearby( tr.HitPos, "prop_physics", 50 ) ) then
+ ply:DoProcess( "PlantBanana", 3, { Pos = tr.HitPos } )
+ else
+ ply:SendMessage( "You need more distance between seeds/props.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You need a banana seed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You cannot plant on this terrain.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "Aim at the ground to plant.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+concommand.Add( "gms_plantbanana", GM.PlantBanana )
+
+function GM.PlantOrange( ply, cmd, args )
+ if ( ply:GetNWInt( "plants" ) >= GetConVarNumber( "gms_PlantLimit" ) ) then ply:SendMessage( "You have hit the plant limit.",3,Color( 200,0,0,255 ) ) return end
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( tr.HitWorld ) then
+ if ( ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND ) and !GMS.IsInWater( tr.HitPos ) ) then
+ if ( ply:GetResource( "Orange_Seeds" ) >= 1 ) then
+ if ( !GMS.ClassIsNearby( tr.HitPos, "gms_seed", 30 ) and !GMS.ClassIsNearby( tr.HitPos, "prop_physics", 50 ) ) then
+ ply:DoProcess( "PlantOrange", 3, { Pos = tr.HitPos } )
+ else
+ ply:SendMessage( "You need more distance between seeds/props.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You need an orange seed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You cannot plant on this terrain.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "Aim at the ground to plant.", 3, Color( 200 ,0, 0, 255 ) )
+ end
+end
+concommand.Add( "gms_plantorange", GM.PlantOrange )
+
+function GM.PlantGrain( ply, cmd, args )
+ if ( !ply:HasUnlock( "Grain_Planting" ) ) then ply:SendMessage( "You need more planting skill.", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( ply:GetNWInt( "plants" ) >= GetConVarNumber( "gms_PlantLimit" ) ) then ply:SendMessage( "You have hit the plant limit.", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( tr.HitWorld ) then
+ local nearby = false
+
+ for k, v in pairs( ents.FindInSphere( tr.HitPos, 50 ) ) do
+ if ( ( v:IsGrainModel() or v:IsProp() or v:GetClass() == "gms_seed" ) and ( tr.HitPos-Vector( v:LocalToWorld( v:OBBCenter() ).x, v:LocalToWorld( v:OBBCenter() ).y, tr.HitPos.z ) ):Length() <= 50 ) then
+ nearby = true
+ end
+ end
+
+ if ( ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND ) and !GMS.IsInWater( tr.HitPos ) ) then
+ if ( ply:GetResource( "Grain_Seeds" ) >= 1 ) then
+ if ( !nearby ) then
+ ply:DoProcess( "PlantGrain", 3, { Pos = tr.HitPos } )
+ else
+ ply:SendMessage( "You need more distance between seeds/props.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You need a grain seed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You cannot plant on this terrain.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "Aim at the ground to plant.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+concommand.Add( "gms_plantgrain", GM.PlantGrain )
+
+function GM.PlantBush( ply, cmd, args )
+ if ( ply:GetNWInt( "plants" ) >= GetConVarNumber( "gms_PlantLimit" ) ) then ply:SendMessage( "You have hit the plant limit.", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( tr.HitWorld ) then
+ local nearby = false
+
+ for k, v in pairs( ents.FindInSphere( tr.HitPos, 50 ) ) do
+ if ( ( v:IsBerryBushModel() or v:IsProp() or v:GetClass() == "gms_seed" ) and ( tr.HitPos-Vector( v:LocalToWorld( v:OBBCenter() ).x, v:LocalToWorld( v:OBBCenter() ).y, tr.HitPos.z ) ):Length() <= 50 ) then
+ nearby = true
+ end
+ end
+
+ if ( ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND ) and !GMS.IsInWater( tr.HitPos ) ) then
+ if ( ply:GetResource( "Berries" ) >= 1 ) then
+ if ( !nearby ) then
+ ply:DoProcess( "PlantBush", 3, { Pos = tr.HitPos } )
+ else
+ ply:SendMessage( "You need more distance between seeds/props.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You need a berry.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You cannot plant on this terrain.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "Aim at the ground to plant.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+concommand.Add( "gms_plantbush", GM.PlantBush )
+
+function GM.PlantTree( ply, cmd, args )
+ if ( !ply:HasUnlock( "Sprout_Planting" ) ) then ply:SendMessage( "You need more planting skill.", 3, Color( 200, 0, 0, 255 ) ) return end
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( tr.HitWorld ) then
+ if ( ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND ) and !GMS.IsInWater( tr.HitPos ) ) then
+ if ( ply:GetResource( "Sprouts" ) >= 1 ) then
+ ply:DoProcess( "PlantTree", 5, { Pos = tr.HitPos } )
+ else
+ ply:SendMessage( "You need a sprout.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "You cannot plant on this terrain.", 3, Color( 200, 0, 0, 255 ) )
+ end
+ else
+ ply:SendMessage( "Aim at the ground to plant.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+concommand.Add( "gms_planttree", GM.PlantTree )
+
+function GM.DrinkFromBottle( ply, cmd, args )
+ if ( ply:GetResource( "Water_Bottles" ) < 1 ) then ply:SendMessage( "You need a water bottle.", 3, Color( 200, 0, 0, 255 ) ) return end
+ ply:DoProcess( "DrinkBottle", 1.5 )
+end
+concommand.Add( "gms_drinkbottle", GM.DrinkFromBottle )
+
+function GM.EatBerry( ply, cmd, args )
+ if ( ply:GetResource( "Berries" ) < 1 ) then ply:SendMessage( "You need some berries.", 3, Color( 200, 0, 0, 255 ) ) return end
+ ply:DoProcess( "EatBerry", 1.5 )
+end
+concommand.Add( "gms_eatberry", GM.EatBerry )
+
+function GM.TakeAMedicine( ply, cmd, args )
+ if ( ply:GetResource( "Medicine" ) < 1 ) then ply:SendMessage( "You need Medicine.", 3, Color( 200, 0, 0, 255 ) ) return end
+ ply:DoProcess( "TakeMedicine", 1.5 )
+end
+concommand.Add( "gms_takemedicine", GM.TakeAMedicine )
+
+function GM.DropWeapon( ply, cmd, args )
+ if ( !ply:Alive() ) then return end
+ if ( table.HasValue( GMS.NonDropWeapons, ply:GetActiveWeapon():GetClass() ) ) then
+ ply:SendMessage( "You cannot drop this!", 3, Color( 200, 0, 0, 255 ) )
+ else
+ ply:DropWeapon( ply:GetActiveWeapon() )
+ end
+end
+concommand.Add( "gms_dropweapon", GM.DropWeapon )
+
+function GM.DropResource( ply, cmd, args )
+ if ( args == nil or args[1] == nil ) then ply:SendMessage( "You need to at least give a resource type!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ args[1] = string.Capitalize( args[1] )
+ if ( !ply.Resources[args[1]] or ply.Resources[args[1]] == 0 ) then ply:SendMessage( "You don't have this kind of resource.", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( args[2] == nil or string.lower( args[2] ) == "all" ) then args[2] = tonumber( ply:GetResource( args[1] ) ) end
+
+ if ( !tonumber( args[2] ) || tonumber( args[2] ) <= 0 ) then ply:SendMessage( "No zeros/negatives!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ local int = tonumber( args[2] )
+ local Type = args[1]
+ local res = ply:GetResource( Type )
+
+ if ( int > res ) then
+ int = res
+ end
+ ply:DropResource( Type, int )
+ ply:DecResource( Type, int )
+
+ ply:SendMessage( "Dropped " .. string.Replace( Type, "_", " " ) .. " ( " .. int .. "x )", 3, Color( 10, 200, 10, 255 ) )
+end
+concommand.Add( "gms_DropResources", GM.DropResource )
+
+function GM.TakeResource( ply, cmd, args )
+ if ( ply.InProcess ) then return end
+
+ local takeAll = false
+ if ( args == nil or args[ 1 ] == nil ) then takeAll = true end
+
+ local int = tonumber( args[ 2 ] ) or 99999
+ local typ = string.Capitalize( args[ 1 ] or "" )
+
+ if ( int <= 0 ) then ply:SendMessage( "No zeros/negatives!", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ local tr = ply:TraceFromEyes( 150 )
+ local ent = tr.Entity
+
+ if ( !IsValid( ent ) ) then return end
+
+ local cls = ent:GetClass()
+
+ if ( cls != "gms_resourcedrop" && cls != "gms_resourcepack" && cls != "gms_fridge" ) then return end
+ if ( !SPropProtection.PlayerCanTouch( ply, ent ) ) then return end
+ if ( ( ply:GetPos() - ent:LocalToWorld( ent:OBBCenter() ) ):Length() >= 100 ) then return end
+
+ if ( cls == "gms_resourcedrop" ) then
+ if ( ent.Type != typ && !takeAll ) then return end
+ local room = ply.MaxResources - ply:GetAllResources()
+ if ( room <= 0 ) then return end
+ if ( int >= ent.Amount ) then int = ent.Amount end
+ if ( room < int ) then int = room end
+ ent.Amount = ent.Amount - int
+ if ( ent.Amount <= 0 ) then ent:Fadeout() else ent:SetResourceDropInfo( ent.Type, ent.Amount ) end
+
+ ply:IncResource( ent.Type, int )
+ ply:SendMessage( "Picked up " .. string.Replace( ent.Type, "_", " " ) .. " ( " .. int .. "x )", 4, Color( 10, 200, 10, 255 ) )
+ end
+
+ if ( cls == "gms_resourcepack" ) then
+ for res, num in pairs( ent.Resources ) do
+ if ( res == typ or takeAll ) then
+ local totake = int
+ local room = ply.MaxResources - ply:GetAllResources()
+ if ( room <= 0 ) then return end
+ if ( totake >= num ) then totake = num end
+ if ( room < totake ) then totake = room end
+ ent.Resources[ res ] = num - totake
+ ent:SetResPackInfo( res, ent.Resources[ res ] )
+ if ( ent.Resources[ res ] <= 0 ) then ent.Resources[ res ] = nil end
+
+ ply:IncResource( res, totake )
+ ply:SendMessage( "Picked up " .. string.Replace( res, "_", " " ) .. " ( " .. totake .. "x )", 4, Color( 10, 200, 10, 255 ) )
+ end
+ end
+ end
+
+ if ( takeAll ) then return end
+
+ if ( cls == "gms_fridge" ) then
+ for res, num in pairs( ent.Resources ) do
+ if ( res == args[ 1 ] ) then
+ ent.Resources[ res ] = num - 1
+ ent:SetResPackInfo( res, ent.Resources[ res ] )
+ if ( ent.Resources[ res ] <= 0 ) then ent.Resources[ res ] = nil end
+
+ local food = ents.Create( "gms_food" )
+ food:SetPos( ent:GetPos() + Vector( 0, 0, ent:OBBMaxs().z + 16 ) )
+ SPropProtection.PlayerMakePropOwner( ply, food )
+ food.Value = GMS.Combinations[ "Cooking" ][ string.Replace( res, " ", "_" ) ].FoodValue
+ food.Name = res
+ food:Spawn()
+ food:SetFoodInfo( res )
+
+ timer.Simple( 300, function( food ) if ( IsValid( food ) ) then food:Fadeout( 2 ) end end, food )
+ end
+ end
+ end
+end
+concommand.Add( "gms_TakeResources", GM.TakeResource ) // ply:PickupResourceEntityPack( ent )
+
+concommand.Add( "gms_structures", function( ply )
+ ply:OpenCombiMenu( "Structures" )
+end )
+
+concommand.Add( "gms_combinations", function( ply )
+ ply:OpenCombiMenu( "Combinations" )
+end )
+
+concommand.Add( "gms_MakeCombination", function( ply, cmd, args )
+ if ( !args[1] or !args[2] ) then ply:SendMessage( "Please specify a valid combination.", 3, Color( 255, 255, 255, 255 ) ) return end
+
+ local group = args[1]
+ local combi = args[2]
+
+ if ( !GMS.Combinations[ group ] ) then return end
+ if ( !GMS.Combinations[ group ][ combi ] ) then return end
+
+ local tbl = GMS.Combinations[ group ][ combi ]
+
+ if ( group == "Cooking" and tbl.Entity ) then
+ local nearby = false
+
+ for k, v in pairs( ents.FindInSphere( ply:GetPos(), 100 ) ) do
+ if ( ( v:IsProp() and v:IsOnFire() ) or v:GetClass() == tbl.Entity ) then nearby = true end
+ end
+
+ if ( !nearby ) then ply:SendMessage( "You need to be close to a fire!", 3, Color( 200, 0 ,0, 255 ) ) return end
+ elseif ( tbl.Entity ) then
+ local nearby = false
+
+ for k, v in pairs( ents.FindInSphere( ply:GetPos(), 100 ) ) do
+ if ( v:GetClass() == tbl.Entity ) then nearby = true end
+ end
+
+ if ( !nearby ) then ply:SendMessage( "You need to be close to a " .. tbl.Entity .. "!", 3, Color( 200, 0, 0, 255 ) ) return end
+ end
+
+ --Check for skills
+ local numreq = 0
+
+ if ( tbl.SkillReq ) then
+ for k, v in pairs( tbl.SkillReq ) do
+ if ( ply:GetSkill( k ) >= v ) then
+ numreq = numreq + 1
+ end
+ end
+
+ if ( numreq < table.Count( tbl.SkillReq ) ) then ply:SendMessage( "Not enough skill.", 3, Color( 200, 0, 0, 255 ) ) return end
+ end
+
+ --Check for resources
+ local numreq = 0
+
+ for k, v in pairs( tbl.Req ) do
+ if ( ply:GetResource( k ) ) >= v then
+ numreq = numreq + 1
+ end
+ end
+
+ if ( numreq < table.Count( tbl.Req ) and group != "Structures" ) then ply:SendMessage( "Not enough resources.", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ --All well, make stuff:
+ if ( group == "Cooking" ) then
+ local data = {}
+ data.Name = tbl.Name
+ data.FoodValue = tbl.FoodValue
+ data.Cost = table.Copy( tbl.Req )
+ local time = 5
+
+ if ply:GetActiveWeapon():GetClass() == "gms_fryingpan" then
+ time = 2
+ end
+
+ ply:DoProcess( "Cook", time, data )
+ elseif ( group == "Combinations" ) then
+ local data = {}
+ data.Name = tbl.Name
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ local time = 5
+
+ ply:DoProcess( "MakeGeneric", time, data )
+ elseif ( group == "gms_pistolgunlab" or group == "gms_gunchunks" or group == "gms_smggunlab" or group == "gms_hightechgunlab" or group == "gms_transmutator" or group == "gms_advancedtransmutator" or group == "gms_renbuyshop" or group == "gms_rensellshop" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.3
+
+ if ( tbl.SwepClass != nil ) then
+ data.Class = tbl.SwepClass
+ ply:DoProcess( "MakeWeapon", time, data )
+ else
+ ply:DoProcess( "Processing", time, data )
+ end
+ elseif ( group == "gms_factory" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.3
+
+ local smelt = false
+ for r,n in pairs( data.Res ) do
+ if ( r == "Iron" or r == "Copper" ) then smelt = true end
+ end
+
+ if ( tbl.SwepClass != nil ) then
+ data.Class = tbl.SwepClass
+ ply:DoProcess( "MakeWeapon", time, data )
+ elseif ( smelt ) then
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.15, 2 ) )
+ ply:DoProcess( "Smelt", time, data )
+ else
+ ply:DoProcess( "Processing", time, data )
+ end
+ elseif ( group == "gms_stoneworkbench" or group == "gms_copperworkbench" or group == "gms_ironworkbench" or group == "gms_silverworkbench" or group == "gms_goldworkbench" or group == "gms_steelworkbench" or group == "gms_platinumworkbench" ) then
+ local data = {}
+ data.Name = tbl.Name
+ data.Class = tbl.SwepClass
+ data.Cost = table.Copy( tbl.Req )
+
+ local time = 10
+ if ( ply:GetActiveWeapon():GetClass() == "gms_wrench" ) then time = 7 end
+ time = math.max( time - math.floor( math.max( ply:GetSkill( "Weapon_Crafting" ) - 8, 0 ) / 4 ), 4 )
+
+ ply:DoProcess( "MakeWeapon", time, data )
+ elseif ( group == "gms_techworkbench" or group == "gms_obelisk" or group == "gms_runealtar" or group == "gms_mithrilworkbench" or group == "gms_runicinfuser") then
+ local data = {}
+ data.Name = tbl.Name
+ data.Cost = table.Copy( tbl.Req )
+
+ if ( tbl.SwepClass != nil ) then
+ local time = 10
+ if ( ply:GetActiveWeapon():GetClass() == "gms_wrench" ) then time = 7 end
+ time = math.max( time - math.floor( math.max( ply:GetSkill( "Weapon_Crafting" ) - 8, 0 ) / 4 ), 4 )
+ data.Class = tbl.SwepClass
+ ply:DoProcess( "MakeWeapon", time, data )
+ else
+ data.Res = tbl.Results
+ local time = 5
+ ply:DoProcess( "MakeGeneric", time, data )
+ end
+ elseif ( group == "Structures" ) then
+ local trs = ply:TraceFromEyes( 250 )
+ if ( !trs.HitWorld ) then ply:SendMessage( "Aim at the ground to construct a structure.", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ ply:DoProcess( "MakeBuilding", 20, {
+ Name = tbl.Name,
+ Class = tbl.Results,
+ Cost = table.Copy( tbl.Req ),
+ BuildSiteModel = tbl.BuildSiteModel,
+ Pos = trs.HitPos
+ } )
+
+ elseif ( group == "gms_stonefurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+
+ local time = timecount * 0.5
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.25, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_copperfurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.6
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.3, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_ironfurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.7
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.35, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_techfurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.7
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.35, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_silverfurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.7
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.35, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_goldfurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.7
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.35, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_steelfurnace" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.1
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.35, 2 ) )
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_platinumfurnace") then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.5
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.35, 2 ) )
+
+
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_mithrilfactory") then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.2
+ time = math.max( time - math.floor( ply:GetSkill( "Smelting" ) / 5 ), math.max( timecount * 0.20, 2 ) )
+
+
+
+
+
+
+ ply:DoProcess( "Smelt", time, data )
+ elseif ( group == "gms_grindingstone" ) then
+ local data = {}
+ data.Name = tbl.Name
+ if ( tbl.AllSmelt == true ) then
+ local sourcetable = ply:AllSmelt( tbl )
+
+ for r, n in pairs( sourcetable.Results ) do
+ if ( r == "Flour" ) then sourcetable.Results[r] = math.floor( n * 0.6 ) end
+ end
+
+ data.Res = sourcetable.Results
+ data.Cost = table.Copy( sourcetable.Req )
+ else
+ data.Res = tbl.Results
+ data.Cost = table.Copy( tbl.Req )
+ end
+ local timecount = 1
+ for k, v in pairs( data.Cost ) do
+ timecount = timecount + v
+ end
+ local time = timecount * 0.75
+
+ ply:DoProcess( "Crush", time, data )
+ end
+end )
+
+concommand.Add( "gms_sleep", function( ply, cmd, args ) ply:Sleep() end )
+concommand.Add( "gms_wakeup", function( ply, cmd, args ) ply:Wakeup() end )
+
+function GM.AFK( ply, cmd, args )
+ if ( ply:GetNWBool( "Sleeping" ) or !ply:Alive() ) then return end
+ if ( ply.InProcess ) then return end
+ if ( !ply:GetNWBool( "AFK", false ) ) then
+ ply:SetNWBool( "AFK", true )
+ else
+ ply:SetNWBool( "AFK", false )
+ end
+
+ ply:Freeze( ply:GetNWBool( "AFK" ) )
+end
+concommand.Add( "gms_afk", GM.AFK )
+
+function GM.PlayerStuck( ply, cmd, args )
+ if ( ply.InProcess ) then return end
+ if ( ply.Spam == true ) then ply:SendMessage( "No spamming!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( ply.Spam == false or ply.Spam == nil ) then ply:SetPos( ply:GetPos() + Vector( 0, 0, 64 ) ) end
+
+ ply.Spam = true
+ timer.Simple( 0.2, function() ply.Spam = false end )
+end
+concommand.Add( "gms_stuck", GM.PlayerStuck )
+
+function GM.MakeCampfire( ply, cmd, args )
+ if ( GetConVarNumber( "gms_campfire" ) == 1 ) then
+ local tr = ply:TraceFromEyes( 150 )
+
+ if ( !tr.HitNonWorld or !tr.Entity ) then ply:SendMessage( "Aim at the prop( s ) to use for campfire.", 3, Color( 255, 255, 255, 255 ) ) return end
+
+ local ent = tr.Entity
+ local cls = tr.Entity:GetClass()
+
+ if ( ent:IsOnFire() or cls != "prop_physics" and cls != "prop_physics_multiplayer" and cls != "prop_dynamic" ) then
+ ply:SendMessage( "Aim at the prop( s ) to use for campfire.", 3, Color( 255, 255, 255, 255 ) )
+ return
+ end
+
+ local mat = tr.MatType
+
+ if ( ply:GetResource( "Wood" ) < 5 ) then ply:SendMessage( "You need at least 5 wood to make a fire.", 5, Color( 255, 255, 255, 255 ) ) return end
+
+ if ( mat != MAT_WOOD ) then ply:SendMessage( "Prop has to be wood, or if partially wood, aim at the wooden part.", 5, Color( 255, 255, 255, 255 ) ) return end
+
+ local data = {}
+ data.Entity = ent
+
+ if ( SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ ply:DoProcess( "Campfire", 5, data )
+ return
+ end
+ end
+end
+concommand.Add( "gms_makefire", GM.MakeCampfire )
+
+/* ----------------------------------------------------------------------------------------------------
+ Player spawn
+---------------------------------------------------------------------------------------------------- */
+
+function GM:PlayerInitialSpawn( ply )
+ ply:SetTeam( 1 )
+
+ ply.Skills = {}
+ ply.Resources = {}
+ ply.Experience = {}
+ ply.FeatureUnlocks = {}
+
+ ply:SetSkill( "Survival", 0 )
+ ply:SetXP( "Survival", 0 )
+ ply.MaxResources = 25
+ ply.Loaded = true
+
+ -- Admin info, needed clientside
+ if ( ply:IsAdmin() ) then
+ for k, v in pairs( file.Find( "gmstranded/gamesaves/*.txt", "DATA" ) ) do
+ local name = string.sub( v, 1, string.len( v ) - 4 )
+
+ if ( string.Right( name, 5 ) != "_info" ) then
+ umsg.Start( "gms_AddLoadGameToList", ply )
+ umsg.String( name )
+ umsg.End()
+ end
+ end
+ end
+
+ -- Character loading
+ if ( file.Exists( "gmstranded/saves/" .. ply:UniqueID() .. ".txt", "DATA" ) ) then
+ local tbl = util.JSONToTable( file.Read( "gmstranded/saves/" .. ply:UniqueID() .. ".txt", "DATA" ) )
+
+ if ( tbl[ "skills" ] ) then
+ for k, v in pairs( tbl[ "skills" ] ) do ply:SetSkill( k, v ) end
+ end
+
+ if ( tbl[ "experience" ] ) then
+ for k, v in pairs( tbl["experience"] ) do ply:SetXP( k, v ) end
+ end
+
+ /*if ( tbl["unlocks"] ) then
+ for k, v in pairs( tbl["unlocks"] ) do ply.FeatureUnlocks[ k ] = v end
+ end*/
+
+ if ( tbl["resources"] ) then
+ for k, v in pairs( tbl["resources"] ) do ply:SetResource( k, v ) end
+ end
+
+ if ( tbl["weapons"] ) then
+ for k, v in pairs( tbl["weapons"] ) do ply:Give( v ) end
+ end
+
+ ply:StripAmmo()
+
+ if ( tbl[ "ammo" ] ) then
+ for k, v in pairs( tbl[ "ammo" ] ) do ply:GiveAmmo( v, k ) end
+ end
+
+ if ( !ply.Skills[ "Survival" ] ) then ply.Skills[ "Survival" ] = 0 end
+
+ ply.FeatureUnlocks = tbl["unlocks"]
+ ply.MaxResources = ( ply.Skills["Survival"] * 5 ) + 25
+
+ ply:SendMessage( "Loaded character successfully.", 3, Color( 255, 255, 255, 255 ) )
+ ply:SendMessage( "Last visited on " .. tbl.date .. ", enjoy your stay.", 10, Color( 255, 255, 255, 255 ) )
+ end
+
+ ply:SetNWInt( "plants", 0 )
+ for k, v in pairs( ents.GetAll() ) do
+ if ( v and IsValid( v ) and v:GetNWEntity( "plantowner" ) and IsValid( v:GetNWEntity( "plantowner" ) ) and v:GetNWEntity( "plantowner" ) == ply ) then
+ ply:SetNWInt( "plants", ply:GetNWInt( "plants" ) + 1 )
+ end
+ end
+
+ local time = 2
+
+ local rp = RecipientFilter()
+ rp:AddPlayer( ply )
+
+ for id, t in pairs( GAMEMODE.Tribes ) do
+ timer.Simple( time, function()
+ umsg.Start( "sendTribe", rp )
+ umsg.Short( id )
+ umsg.String( t.name )
+ umsg.Vector( Vector( t.color.r, t.color.g, t.color.b ) )
+ if ( t.password == false ) then
+ umsg.Bool( false )
+ else
+ umsg.Bool( true )
+ end
+ umsg.End()
+
+ end )
+ time = time + 0.1
+ end
+
+ for _, v in ipairs( ents.FindByClass( "gms_resourcedrop" ) ) do
+ timer.Simple( time, function()
+ umsg.Start( "gms_SetResourceDropInfo", rp )
+ umsg.String( v:EntIndex() )
+ umsg.String( string.gsub( v.Type or "Error!", "_", " " ) )
+ umsg.Short( v.Amount )
+ umsg.End()
+ end )
+ time = time + 0.1
+ end
+
+ for _, v in ipairs( table.Add( ents.FindByClass( "gms_resourcepack" ), ents.FindByClass( "gms_fridge" ) ) ) do
+ for res, num in pairs( v.Resources ) do
+ timer.Simple( time, function()
+ umsg.Start( "gms_SetResPackInfo", rp )
+ umsg.String( v:EntIndex() )
+ umsg.String( string.gsub( res, "_", " " ) )
+ umsg.Short( num )
+ umsg.End()
+ end )
+ time = time + 0.1
+ end
+ time = time + 0.1
+ end
+
+ for _, v in ipairs( ents.FindByClass( "gms_food" ) ) do
+ timer.Simple( time, function()
+ umsg.Start( "gms_SetFoodDropInfo", ply )
+ umsg.String( v:EntIndex() )
+ umsg.String( string.gsub( v.Name or "ERROR", "_", " " ) )
+ umsg.End()
+ end )
+ time = time + 0.1
+ end
+end
+
+local SpawnClasses = {
+ "info_player_deathmatch", "info_player_combine", "info_player_combine",
+ "info_player_rebel", "info_player_counterterrorist", "info_player_terrorist",
+ "info_player_axis", "info_player_allies", "gmod_player_start",
+ "info_player_teamspawn", "ins_spawnpoint", "aoc_spawnpoint",
+ "dys_spawn_point", "info_player_pirate", "info_player_viking",
+ "info_player_knight", "diprip_start_team_blue", "diprip_start_team_red",
+ "info_player_red", "info_player_blue", "info_player_coop",
+ "info_player_human", "info_player_zombie", "info_player_deathmatch",
+ "info_player_zombiemaster"
+}
+
+function GM:PlayerSelectSpawn( pl )
+ if ( GAMEMODE.TeamBased ) then
+ local ent = GAMEMODE:PlayerSelectTeamSpawn( pl:Team(), pl )
+ if ( IsValid( ent ) ) then return ent end
+ end
+
+ if ( !IsTableOfEntitiesValid( self.SpawnPoints ) ) then
+ self.LastSpawnPoint = 0
+ self.SpawnPoints = ents.FindByClass( "info_player_start" )
+ for id, cl in pairs( SpawnClasses ) do
+ self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( cl ) )
+ end
+ end
+
+ local count = table.Count( self.SpawnPoints )
+ if ( count == 0 ) then
+ MsgN( "[PlayerSelectSpawn] Error! No spawn points!" )
+ return nil
+ end
+
+ local ChosenSpawnPoint = nil
+
+ for id, ChosenSpawnPoint in pairs( self.SpawnPoints ) do
+
+ if ( IsValid( ChosenSpawnPoint ) && ChosenSpawnPoint:IsInWorld() ) then
+ if ( GAMEMODE:IsSpawnpointSuitable( pl, ChosenSpawnPoint, id == count ) ) then
+ return ChosenSpawnPoint
+ end
+ end
+
+ end
+
+ return ChosenSpawnPoint
+end
+
+function GM:PlayerSpawn( ply )
+
+ self:SetPlayerSpeed( ply, 250, 250 )
+ ply:SetMaxHealth( 100 )
+ ply:UnSpectate()
+
+ for k, v in pairs( GMS.FeatureUnlocks ) do
+ if ( ply:HasUnlock( k ) && v.OnUnlock ) then v.OnUnlock( ply ) end
+ end
+
+ hook.Call("PlayerLoadout", self, ply)
+ hook.Call("PlayerSetModel", self, ply)
+
+ ply.Sleepiness = 1000
+ ply.Hunger = 1000
+ ply.Thirst = 1000
+ ply.Oxygen = 1000
+ ply.Power = 50
+
+ ply.Resources = ply.Resources or {}
+
+ if ( ply.Resources[ "Batteries" ] ) then ply.Power = math.min( ply.Power + ply.Resources[ "Batteries" ] * 50, 500 ) end
+
+ /* GMOD CUSTOMIZATION */
+ ply:UpdatePlayerColor()
+
+ local col = ply:GetInfo( "cl_weaponcolor" )
+ ply:SetWeaponColor( Vector( col ) )
+
+ ply:SetupHands()
+
+ ply:UpdateNeeds()
+end
+
+function GM:PlayerSetModel( ply )
+ local cl_playermodel = ply:GetInfo( "cl_playermodel" )
+ local modelname = player_manager.TranslatePlayerModel( cl_playermodel )
+ util.PrecacheModel( modelname )
+ ply:SetModel( modelname )
+end
+
+function GM:PlayerSetHandsModel( ply, ent )
+
+ local simplemodel = player_manager.TranslateToPlayerModelName( ply:GetModel() )
+ local info = player_manager.TranslatePlayerHands( simplemodel )
+ if ( info ) then
+ ent:SetModel( info.model )
+ ent:SetSkin( info.skin )
+ ent:SetBodyGroups( info.body )
+ end
+
+end
+
+function GM:PlayerLoadout( ply )
+ ply:Give( "gms_fists" )
+ ply:Give( "weapon_physcannon" )
+ ply:Give( "weapon_physgun" )
+
+ ply:SelectWeapon( "weapon_physgun" )
+ ply:SelectWeapon( "gms_fists" )
+
+ if ( GetConVarNumber( "gms_AllTools" ) == 1 ) then
+ for id, wep in pairs( GMS.AllWeapons ) do ply:Give( wep ) end
+ end
+
+ if ( ply:IsDeveloper() ) then ply:Give( "gmod_tool" ) ply:Give( "pill_pigeon" ) end
+end
+
+function GM:PlayerCanPickupWeapon( ply, wep )
+ if ( ply:HasWeapon( wep:GetClass() ) ) then return false end
+ return true
+end
+
+function GM:CanProperty( pl, property, ent )
+ if ( !IsValid( ent ) ) then return false end
+ if ( !pl:IsAdmin() ) then return false end
+
+ if ( ent.m_tblToolsAllowed ) then
+ local vFound = false
+ for k, v in pairs( ent.m_tblToolsAllowed ) do
+ if ( property == v ) then vFound = true end
+ end
+
+ if ( !vFound ) then return false end
+ end
+
+ if ( property == "bonemanipulate" ) then
+ if ( game.SinglePlayer() ) then return true end
+
+ if ( ent:IsNPC() ) then return GetConVarNumber( "sbox_bonemanip_npc" ) != 0 end
+ if ( ent:IsPlayer() ) then return GetConVarNumber( "sbox_bonemanip_player" ) != 0 end
+
+ return GetConVarNumber( "sbox_bonemanip_misc" ) != 0
+ end
+
+ return true
+end
+
+hook.Add( "PlayerDeath", "Death", function( ply )
+
+ // Creates the gravestone
+ local grave = ents.Create("gms_gravestone")
+
+ grave:SetPos( Vector( ply:GetPos().x, ply:GetPos().y, ply:GetPos().z+18 ) )
+
+ grave:Spawn()
+ grave:SetplName(ply:Nick())
+
+ grave:SetNetworkedString( "Owner", "Everyone" )
+
+ wepstbl = {}
+ restbl = {}
+
+ for _, v in pairs( ply:GetWeapons() ) do
+ if ( !table.HasValue( GMS.NonDropWeapons, v:GetClass() ) && GetConVarNumber( "gms_AllTools" ) != 1 ) then
+ //ply:DropWeapon( v )
+ table.insert(wepstbl, v:GetClass())
+ SPropProtection.PlayerMakePropOwner( ply, v )
+ end
+ end
+
+ for _, v in pairs(ply.Resources) do
+
+ num1 = v * 0.1
+ num2 = v - math.Round(num1)
+
+ if (num2 > 0) then
+
+ table.insert(restbl, _.." x"..num2)
+ ply:DecResource(_,v)
+
+ end
+
+
+
+ end
+
+ ply.Resources = {}
+
+ grave.deathWeapons = wepstbl
+ grave.deathResources = restbl
+
+ ply:CancelProcess()
+
+ if ( ply:GetNWBool("AFK") ) then
+ ply:Freeze( false )
+ ply:SetNWBool( "AFK", false )
+ end
+end )
+
+timer.Create( "GMS.AutoSaveAllCharacters", math.Clamp( GetConVarNumber( "gms_AutoSaveTime" ), 1, 60 ) * 60, 0, function()
+ if ( GetConVarNumber( "gms_AutoSave" ) == 1 ) then
+ for k, v in pairs( player.GetAll() ) do
+ v:SendMessage( "Autosaving..", 3, Color( 255, 255, 255, 255 ) )
+ v:SaveCharacter()
+ end
+ end
+end )
+
+function GM:PlayerDisconnected( ply )
+ Msg( "Saving character of disconnecting player " .. ply:Nick() .. "...\n" )
+ ply:SaveCharacter()
+end
+
+function GM:ShutDown()
+ for k, v in pairs( player.GetAll() ) do v:SaveCharacter() end
+end
+
+function PlayerMeta:UpdatePlayerColor()
+ local col = self:GetInfo( "cl_playercolor" )
+ if ( GetConVarNumber( "gms_TeamColors" ) > 0 ) then
+ local tcol = team.GetColor( self:Team() )
+ col = tcol.r / 255 .. " " .. tcol.g / 255 .. " " .. tcol.b / 255
+ end
+ self:SetPlayerColor( Vector( col ) )
+end
+
+function PlayerMeta:ResetCharacter()
+
+ self.Skills = {}
+ self.Resources = {}
+ self.Experience = {}
+ self.FeatureUnlocks = {}
+
+ self:SetSkill( "Survival", 0 )
+ self:SetXP( "Survival", 0 )
+ self.MaxResources = 25
+
+ self:SaveCharacter()
+
+ umsg.Start( "gms_ResetPlayer", ply )
+ umsg.End()
+
+end
+
+function PlayerMeta:SaveCharacter()
+ if ( !file.IsDir( "gmstranded", "DATA" ) ) then file.CreateDir( "gmstranded" ) end
+ if ( !file.IsDir( "gmstranded/saves", "DATA" ) ) then file.CreateDir( "gmstranded/saves" ) end
+ if ( !self.Loaded ) then
+ print( "Player " .. self:Name() .. " tried to save before he has loaded!" )
+ self:SendMessage( "Character save failed: Not yet loaded!", 3, Color( 255, 50, 50, 255 ) )
+ return
+ end
+
+ local tbl = {}
+ tbl["date"] = os.date( "%A %m/%d/%y" )
+ tbl["name"] = self:Nick()
+
+ tbl["skills"] = self.Skills
+ tbl["experience"] = self.Experience
+ tbl["unlocks"] = self.FeatureUnlocks
+
+ tbl["resources"] = {}
+ tbl["weapons"] = {}
+ tbl["ammo"] = {}
+
+ for k, v in pairs( self.Resources ) do
+ if ( v > 0 ) then tbl["resources"][ k ] = v end
+ end
+
+ for id, wep in pairs( self:GetWeapons() ) do
+ if ( wep:GetClass() != "gms_fists" || wep:GetClass() != "weapon_physgun" || wep:GetClass() != "weapon_physcannon" ) then
+ table.insert( tbl[ "weapons" ], wep:GetClass() )
+ end
+ end
+
+ local ammo_types = { "ar2", "smg1", "pistol", "buckshot", "357", "grenade", "alyxgun", "xbowbolt", "AlyxGun", "RPG_Round","SMG1_Grenade", "SniperRound",
+ "SniperPenetratedRound", "Grenade", "Thumper", "Gravity", "Battery", "GaussEnergy", "CombineCannon", "AirboatGun", "StriderMinigun", "StriderMinigunDirect",
+ "HelicopterGun", "AR2AltFire", "Grenade", "Hopwire", "CombineHeavyCannon", "ammo_proto1"
+ }
+
+ for id, str in pairs( ammo_types ) do
+ local ammo = self:GetAmmoCount( str )
+ if ( ammo > 0 ) then tbl[ "ammo" ][ str ] = ammo end
+ end
+
+ file.Write( "gmstranded/saves/" .. self:UniqueID() .. ".txt", util.TableToJSON( tbl ) )
+ self:SendMessage( "Saved character!", 3, Color( 255, 255, 255 ) )
+end
+
+concommand.Add( "gms_savecharacter", function( ply, cmd, args )
+ if ( ply.GMSLastSave && ply.GMSLastSave > CurTime() ) then ply:SendMessage( "You must wait " .. math.floor( ply.GMSLastSave - CurTime() ) .. " seconds before saving again.", 3, Color( 255, 50, 50, 255 ) ) return end
+ ply.GMSLastSave = CurTime() + 30
+ ply:SaveCharacter()
+end )
+
+concommand.Add( "gms_resetcharacter", function( ply, cmd, args )
+ if ( !args[ 1 ] ) then ply:ConCommand( "gms_resetcharacter_verify" ) return end
+ if ( args[ 1 ] != "I agree" ) then ply:ChatPrint( "You didn't type what was asked." ) return end
+ ply:ResetCharacter()
+end )
+
+/*------------------------ Prop spawning ------------------------*/
+
+function GM:PlayerSpawnProp( ply, model )
+ if ( ply.InProcess ) then return false end
+ if ( ply.NextSpawn && ply.NextSpawn > CurTime() ) then ply:SendMessage( "No spamming!", 3, Color( 200, 0, 0, 255 ) ) return false end -- No spamming
+ if ( !ply:IsAdmin() && GMS_IsAdminOnlyModel( model ) ) then ply:SendMessage( "You cannot spawn this prop unless you're admin.", 5, Color( 200, 0, 0, 255 ) ) return false end
+ return true //LimitReachedProcess( ply, "props" )
+end
+
+function GM:PlayerSpawnedProp( ply, mdl, ent )
+ ply.NextSpawn = CurTime() + 1
+ SPropProtection.PlayerMakePropOwner( ply, ent )
+
+ if ( GetConVarNumber( "gms_FreeBuild" ) == 1 ) then return end
+ if ( GetConVarNumber( "gms_FreeBuildSA" ) == 1 and ply:IsAdmin() ) then return end
+
+ ent.NormalProp = true
+
+ timer.Simple( 0.2, function() self:PlayerSpawnedPropDelay( ply, mdl, ent ) end )
+end
+
+function GM:PlayerSpawnedPropDelay( ply, mdl, ent )
+ if ( !IsValid( ent ) ) then return end
+
+ --Trace
+ ent.EntOwner = ply
+
+ -- Do volume in cubic "feet"
+ local vol = ent:GetVolume()
+
+ local x = 0
+ local trace = nil
+ local tr = nil
+ trace = {}
+ trace.start = ent:GetPos() + Vector( ( math.random() * 200 ) - 100, ( math.random() * 200 ) - 100, ( math.random() * 200 ) - 100 )
+ trace.endpos = ent:GetPos()
+ tr = util.TraceLine( trace )
+
+ while ( tr.Entity != ent and x < 5 ) do
+ x = x + 1
+ trace = {}
+ trace.start = ent:GetPos() + Vector( ( math.random() * 200 ) - 100, ( math.random() * 200 ) - 100, ( math.random() * 200 ) - 100 )
+ trace.endpos = ent:GetPos()
+ tr = util.TraceLine( trace )
+ end
+
+ --Faulty trace
+ if ( tr.Entity != ent ) then ent:Remove() ply:SendMessage( "You need more space to spawn.", 3, Color( 255, 255, 255, 255 ) ) return end
+
+ if ( !GMS.MaterialResources[ tr.MatType ] ) then
+ MsgC( Color( 255, 0, 0 ), "WARNING! Can't detect material of " .. mdl .. "!\n" )
+ tr.MatType = MAT_CONCRETE
+ end
+
+ local res = GMS.MaterialResources[ tr.MatType ]
+ //local cost = math.ceil( vol * ( GetConVarNumber( "gms_CostsScale" ) / 2 ) )
+ local cost = math.ceil( vol * 0.5 )
+
+ if ( cost > ply:GetResource( res ) ) then
+ if ( IsValid( ply:GetBuildingSite() ) ) then ply:GetBuildingSite():Remove() end
+ local site = ply:CreateBuildingSite( ent:GetPos(), ent:GetAngles(), ent:GetModel(), ent:GetClass() )
+ local tbl = site:GetTable()
+ site.EntOwner = ply
+ site.NormalProp = true
+ local costtable = {}
+ costtable[ res ] = cost
+
+ tbl.Costs = table.Copy( costtable )
+ ply:DoProcess( "Assembling", math.max( 2, math.min( cost / 100, 120 ) ) )
+ ply:SendMessage( "Not enough resources, creating buildsite.", 3, Color( 255, 255, 255, 255 ) )
+ local str = ":"
+ for k, v in pairs( site.Costs ) do
+ str = str .. " " .. string.Replace( k, "_", " " ) .. " ( " .. v .. "x )"
+ end
+ site:SetNWString( "Resources", str )
+ local Name = "Prop"
+ site:SetNWString( "Name", Name )
+ ent:Remove()
+ return
+ end
+
+ -- Resource cost
+ if ply:GetResource( res ) < cost then
+ ent:Remove()
+ ply:SendMessage( "You need " .. string.Replace( res, "_", " " ) .. " ( " .. cost .. "x ) to spawn this prop.", 3, Color( 200, 0, 0, 255 ) )
+ else
+ ply:DecResource( res, cost )
+ ply:SendMessage( "Used " .. string.Replace( res, "_", " " ) .. " ( " .. cost .. "x ) to spawn this prop.", 3, Color( 255, 255, 255, 255 ) )
+ ply:DoProcess( "Assembling", math.max( 2, math.min( cost / 100, 120 ) ) )
+ end
+end
+
+-- No Ragdolls, Effects, SENTs, NPCs, SWEPs or Vehicles in Stranded.
+
+function GM:PlayerSpawnRagdoll( ply, model )
+ return false
+end
+
+function GM:PlayerSpawnEffect( ply, model )
+ return false
+end
+
+function GM:PlayerSpawnSENT( ply, name )
+ return false
+end
+
+function GM:PlayerSpawnNPC( ply, npc_type, equipment )
+ return false
+end
+
+function GM:PlayerSpawnSWEP( ply, wname, wtable )
+ return false
+end
+
+function GM:PlayerGiveSWEP( ply, wname, wtable )
+ return false
+end
+
+function GM:PlayerSpawnVehicle( ply, model, vname, vtable )
+ return false
+end
+
+/*------------------------ Needs ------------------------*/
+
+timer.Create( "GMS.SubtractNeeds", 3, 0, function()
+ for k, ply in pairs( player.GetAll() ) do
+ if ( ply:Alive() ) then
+ local AddHunger = -3
+ local AddThirst = -6
+
+ -- Sleeping
+ if ( ply:GetNWBool( "Sleeping" ) ) then
+ if ( ply.Sleepiness <= 950 ) then
+ local trace = {}
+ trace.start = ply:GetShootPos()
+ trace.endpos = trace.start - ( ply:GetUp() * 300 )
+ trace.filter = ply
+
+ local tr = util.TraceLine( trace )
+ if ( IsValid( tr.Entity ) and tr.Entity:IsSleepingFurniture() ) then
+ ply.Sleepiness = math.Clamp( ply.Sleepiness + 100, 0, 1000 )
+ else
+ ply.Sleepiness = math.Clamp( ply.Sleepiness + 50, 0, 1000 )
+ end
+ elseif ( ply.Sleepiness > 950 ) then
+ ply.Sleepiness = 1000
+ ply:Wakeup()
+ end
+
+ AddThirst = -20
+ AddHunger = -20
+
+ if ( ply.NeedShelter ) then
+ if ( ply:Health() >= 11 ) then
+ ply:SetHealth( ply:Health() - 10 )
+ else
+ ply:Kill()
+ for k, v in pairs( player.GetAll() ) do v:SendMessage( ply:Nick() .. " died in sleep.", 3, Color( 170, 0, 0, 255 ) ) end
+ end
+ end
+ end
+
+ if ( !ply:GetNWBool( "AFK" ) ) then
+
+ // Oxygen
+ if ( ply:WaterLevel() > 2 ) then
+ if ( ply.Oxygen > 0 ) then
+ ply.Oxygen = math.max( ply.Oxygen - math.min( 1600 / ply:GetSkill( "Swimming" ), 500 ), 0 )
+ ply:IncXP( "Swimming", math.Clamp( math.Round( 100 / ply:GetSkill( "Swimming" ) ), 1, 1000 ) )
+ end
+ else
+ if ( ply.Oxygen < 1000 ) then ply.Oxygen = math.min( ply.Oxygen + 100, 1000 ) end
+ end
+
+ // Flashlight
+ if ( ply:FlashlightIsOn() ) then
+ if ( ply.Power > 0 ) then
+ ply.Power = math.max( ply.Power - 5, 0 )
+ if ( ply.Power < 5 ) then ply:Flashlight( false ) end
+ end
+ else
+ local maxPow = 50
+ if ( ply.Resources["Batteries"] ) then maxPow = math.min( maxPow + ply.Resources["Batteries"] * 50, 500 ) end
+ if ( ply.Power < maxPow ) then ply.Power = math.min( ply.Power + 10, maxPow ) end
+ end
+
+ if ( ply.Sleepiness > 0 ) then ply.Sleepiness = math.Clamp( ply.Sleepiness - 2, 0, 1000 ) end
+ if ( ply.Thirst > 0 ) then ply.Thirst = math.Clamp( ply.Thirst + AddThirst, 0, 1000 ) end
+ if ( ply.Hunger > 0 ) then ply.Hunger = math.Clamp( ply.Hunger + AddHunger, 0, 1000 ) end
+ end
+
+ ply:UpdateNeeds()
+
+ --Are you dying?
+ if ( ply.Sleepiness <= 0 or ply.Thirst <= 0 or ply.Hunger <= 0 ) then
+ if ( ply:Health() >= 3 ) then
+ ply:SetHealth( ply:Health() - 2 )
+ ply:ScreenFade( SCREENFADE.IN, Color( 255, 0, 0 ), 0.7, 0 )
+ ply:ViewPunch( Angle( math.random( 6, -6 ), math.random( 4, -4 ), 0 ) )
+ else
+ ply:Kill()
+ for k, v in pairs( player.GetAll() ) do v:SendMessage( ply:Nick() .. " didn't survive.", 3, Color( 170, 0, 0, 255 ) ) end
+ end
+ end
+
+ if ( ply.Oxygen <= 0 ) then
+ if ( ply:Health() >= 9 ) then
+ ply:SetHealth( ply:Health() - 8 )
+ ply:EmitSound( "player/pl_drown" .. math.random( 1, 3 ) .. ".wav", 100, math.random( 95, 105 ) )
+ ply:ScreenFade( SCREENFADE.IN, Color( 0, 0, 255 ), 0.7, 0)
+ ply:ViewPunch( Angle( math.random( 6, -6 ), 0, 0 ) )
+ else
+ ply:Kill()
+ for k, v in pairs( player.GetAll() ) do v:SendMessage( ply:Nick() .. " has drowned.", 3, Color( 170, 0, 0, 255 ) ) end
+ end
+ end
+ end
+ end
+end )
+
+/* NPC Looting and hunting */
+
+function GM:OnNPCKilled( npc, killer, weapon )
+
+ if ( npc != killer ) then self.BaseClass.OnNPCKilled( self, npc, killer, weapon ) end
+ npc:Fadeout( 5 )
+
+ if ( !killer:IsPlayer() ) then return end
+ killer:SetFrags( killer:Frags() + 1 )
+
+ if ( !npc:IsLootableNPC() ) then return end
+
+ local loot = ents.Create( "gms_loot" )
+ SPropProtection.PlayerMakePropOwner( killer, loot )
+
+ loot.Resources = { Meat = math.random( 1, 5 ) }
+ loot:SetPos( npc:GetPos() + Vector( 0, 0, 64 ) )
+ loot:Spawn()
+ timer.Simple( 180, function() if ( loot:IsValid() ) then loot:Fadeout( 2 ) end end )
+
+ killer:IncXP( "Hunting", math.Clamp( math.Round( 150 / killer:GetSkill( "Hunting" ) ), 1, 1000 ) )
+end
+
+/* Use Hook */
+hook.Add( "KeyPress", "GMS_UseKeyHook", function( ply, key )
+ if ( key != IN_USE ) then return end
+ if ( ply:KeyDown( 1 ) ) then return end
+
+ local tr = ply:TraceFromEyes( 128 )
+ if ( tr.HitNonWorld && IsValid( tr.Entity ) && !GMS.IsInWater( tr.HitPos ) ) then
+ local ent = tr.Entity
+ local mdl = tr.Entity:GetModel()
+ local cls = tr.Entity:GetClass()
+
+ if ( ( ent:IsFoodModel() or cls == "gms_food" ) and ( ( ply:GetPos() - ent:LocalToWorld( ent:OBBCenter() ) ):Length() <= 128 ) and SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ if ( cls == "gms_food" ) then
+ ply:DoProcess( "EatFood", 3, { Entity = ent } )
+ else
+ ply:DoProcess( "EatFruit", 2, { Entity = ent } )
+ end
+ elseif ( ent:IsTreeModel() or ent:GetClass() == "gms_tree" ) then
+ if ( !ply:HasUnlock( "Sprout_Collecting" ) ) then ply:SendMessage( "You don't have enough skill.", 3, Color( 200, 0, 0, 255 ) ) return end
+ ply:DoProcess( "SproutCollect", 5 )
+ elseif ( cls == "gms_resourcedrop" and ( ply:GetPos() - tr.HitPos ):Length() <= 128 and SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ ply:PickupResourceEntity( ent )
+ elseif ( ( cls == "gms_resourcepack" or cls == "gms_fridge" ) and ( ply:GetPos() - tr.HitPos ):Length() <= 128 and SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ ply:ConCommand( "gms_openrespackmenu" )
+ elseif ( ent:IsOnFire() && SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ if ( GetConVarNumber( "gms_campfire" ) == 1 ) then ply:OpenCombiMenu( "Cooking" ) end
+ end
+ elseif ( tr.HitWorld ) then
+ for k, v in pairs( ents.FindInSphere( tr.HitPos, 100 ) ) do
+ if ( v:IsGrainModel() && SPropProtection.PlayerCanTouch( ply, v ) ) then
+ ply:DoProcess( "HarvestGrain", 3, { Entity = v } )
+ return
+ elseif ( v:IsBerryBushModel() && SPropProtection.PlayerCanTouch( ply, v ) ) then
+ ply:DoProcess( "HarvestBush", 3, { Entity = v } )
+ return
+ end
+ end
+ if ( ( tr.MatType == MAT_DIRT or tr.MatType == MAT_GRASS or tr.MatType == MAT_SAND or tr.MatType == MAT_SNOW ) and !GMS.IsInWater( tr.HitPos ) ) then
+ local time = 5
+ if ( IsValid( ply:GetActiveWeapon() ) && ply:GetActiveWeapon():GetClass() == "gms_shovel" ) then time = 2 end
+ ply:DoProcess( "Foraging", time )
+ end
+ end
+
+ local trace = {}
+ trace.start = ply:GetShootPos()
+ trace.endpos = trace.start + ( ply:GetAimVector() * 150 )
+ trace.mask = bit.bor( MASK_WATER, MASK_SOLID )
+ trace.filter = ply
+
+ local tr2 = util.TraceLine( trace )
+ if ( ( tr2.Hit && tr2.MatType == MAT_SLOSH && ply:WaterLevel() > 0 ) or ply:WaterLevel() == 3 ) then
+ ply.Thirst = math.min( ply.Thirst + 50, 1000 )
+ if ( !ply.Hasdrunk ) then
+ ply:EmitSound( Sound( "npc/barnacle/barnacle_gulp" .. math.random( 1, 2 ) .. ".wav" ), 100, math.random( 95, 105 ) )
+ ply.Hasdrunk = true
+ timer.Simple( 0.9, function() ply.Hasdrunk = false end, ply )
+ end
+ ply:UpdateNeeds()
+ elseif ( GMS.IsInWater( tr.HitPos ) && !tr.HitNonWorld ) then
+ if (ply:GetActiveWeapon():GetClass() == "gms_bucket") then
+ ply:DoProcess( "BottleWater", 20 )
+ else
+ ply:DoProcess( "BottleWater", 3 )
+ end
+ end
+end )
+
+/* Saving / loading functions */
+
+-- Commands
+concommand.Add( "gms_admin_savemap", function( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( !args[ 1 ] or string.Trim( args[ 1 ] ) == "" ) then return end
+ GAMEMODE:PreSaveMap( string.Trim( args[1] ) )
+end )
+
+concommand.Add( "gms_admin_loadmap", function( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0 ,0, 255 ) ) return end
+ if ( !args[ 1 ] or string.Trim( args[ 1 ] ) == "" ) then return end
+ GAMEMODE:PreLoadMap( string.Trim( args[ 1 ] ) )
+end )
+
+concommand.Add( "gms_admin_deletemap", function( ply, cmd, args )
+ if ( IsValid( ply ) && !ply:IsAdmin() ) then ply:SendMessage( "You need admin rights for this!", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( !args[ 1 ] or string.Trim( args[ 1 ] ) == "" ) then return end
+ GAMEMODE:DeleteSavegame( string.Trim( args[ 1 ] ) )
+end )
+
+--Delete map
+function GM:DeleteSavegame( name )
+ if ( !file.Exists( "gmstranded/gamesaves/" .. name .. ".txt", "DATA" ) ) then return end
+ file.Delete( "gmstranded/gamesaves/" .. name .. ".txt" )
+ if ( file.Exists( "gmstranded/gamesaves/" .. name .. "_info.txt", "DATA" ) ) then file.Delete( "gmstranded/gamesaves/" .. name .. "_info.txt" ) end
+
+ for k, ply in pairs( player.GetAll() ) do
+ if( ply:IsAdmin() ) then
+ umsg.Start( "gms_RemoveLoadGameFromList", ply )
+ umsg.String( name )
+ umsg.End()
+ end
+ end
+end
+
+--Save map
+function GM:PreSaveMap( name )
+ if ( CurTime() < 3 ) then return end
+ if ( CurTime() < self.NextSaved ) then return end
+
+ for k, ply in pairs( player.GetAll() ) do
+ ply:MakeSavingBar( "Saving game as \"" .. name .. "\"" )
+ end
+
+ self.NextSaved = CurTime() + 0.6
+ timer.Simple( 0.5, function() self:SaveMap( name ) end )
+end
+
+function GM:SaveMap( name )
+ local savegame = {}
+ savegame["name"] = name
+ savegame["entries"] = {}
+
+ savegame_info = {}
+ savegame_info["map"] = game.GetMap()
+ savegame_info["date"] = os.date( "%A %m/%d/%y" )
+
+ for k, ent in pairs( ents.GetAll() ) do
+ if ( !IsValid( ent ) || ent:CreatedByMap() || !table.HasValue( GMS.SavedClasses, ent:GetClass() ) ) then continue end
+ if ( ent.GMSAutoSpawned ) then continue end
+ local entry = {}
+
+ entry["class"] = ent:GetClass()
+ entry["model"] = ent:GetModel()
+
+ entry["owner"] = ent:GetNWString( "Owner" )
+ entry["ownerid"] = ent:GetNWInt( "OwnerID" )
+ entry["tribeid"] = ent:GetNWInt( "TribeID" )
+
+ if ( ent.Children != nil ) then entry[ "Children" ] = ent.Children end
+ if ( ent.IsPlantChild ) then entry["PlantParentName"] = ent.PlantParentName end
+ if ( ent.IsPlant ) then entry["PlantName"] = ent:GetName() end
+
+ entry["color"] = ent:GetColor()
+ entry["pos"] = ent:GetPos()
+ entry["angles"] = ent:GetAngles()
+ entry["material"] = ent:GetMaterial() or "0"
+ entry["keyvalues"] = ent:GetKeyValues()
+ entry["table"] = ent:GetTable()
+ entry["solid"] = ent:GetSolid()
+
+ local phys = ent:GetPhysicsObject()
+
+ if ( IsValid( phys ) ) then
+ entry["freezed"] = phys:IsMoveable()
+ entry["sleeping"] = phys:IsAsleep()
+ end
+
+ if ( entry["class"] == "gms_resourcedrop" ) then entry["type"] = ent.Type entry["amount"] = ent.Amount end // ResDrop
+
+ table.insert( savegame["entries"], entry )
+
+ end
+
+ if ( !file.IsDir( "gmstranded", "DATA" ) ) then file.CreateDir( "gmstranded" ) end
+ if ( !file.IsDir( "gmstranded/gamesaves", "DATA" ) ) then file.CreateDir( "gmstranded/gamesaves" ) end
+
+ file.Write( "gmstranded/gamesaves/" .. name .. ".txt", util.TableToJSON( savegame ) )
+ file.Write( "gmstranded/gamesaves/" .. name .. "_info.txt", util.TableToJSON( savegame_info ) )
+
+ for k, ply in pairs( player.GetAll() ) do
+ ply:SendMessage( "Saved game \"" .. name .. "\".", 3, Color( 255, 255, 255, 255 ) )
+ ply:StopSavingBar()
+
+ if ( ply:IsAdmin() ) then
+ umsg.Start( "gms_AddLoadGameToList", ply )
+ umsg.String( name )
+ umsg.End()
+ end
+ end
+end
+
+--Load map
+function GM:PreLoadMap( name )
+ if ( CurTime() < 3 ) then return end
+ if ( CurTime() < self.NextLoaded ) then return end
+ if ( !file.Exists( "gmstranded/gamesaves/" .. name .. ".txt", "DATA" ) ) then return end
+
+ game.CleanUpMap()
+
+ for k, ply in pairs( player.GetAll() ) do ply:MakeLoadingBar( "Savegame \"" .. name .. "\"" ) end
+
+ self.NextLoaded = CurTime() + 0.6
+ timer.Simple( 0.5, function() self:LoadMap( name ) end )
+end
+
+function GM:LoadMap( name )
+ local savegame = util.JSONToTable( file.Read( "gmstranded/gamesaves/" .. name .. ".txt" ) )
+ local num = table.Count( savegame["entries"] )
+
+ if ( num == 0 ) then
+ for k, ply in pairs( player.GetAll() ) do
+ ply:SendMessage( "This savegame is empty!", 3, Color( 255, 255, 255, 255 ) )
+ ply:StopLoadingBar()
+ end
+ return end
+
+ Time = DayTime
+
+ self:LoadMapEntity( savegame, num, 1 )
+end
+
+--Don't load it all at once
+function GM:LoadMapEntity( savegame, max, k )
+ local entry = savegame["entries"][k]
+
+ local ent = ents.Create( entry["class"] )
+
+ if ( !entry["model"] ) then
+ print( "WARNING! " .. entry["class"] .. " doesn't have a model!" )
+ else
+ ent:SetModel( entry["model"] )
+ end
+
+
+ ent:SetColor( entry["color"] )
+ ent:SetPos( entry["pos"] )
+ ent:SetAngles( entry["angles"] )
+
+ if ( entry["Children"] ) then ent.Children = entry[ "Children" ] end
+ if ( entry["PlantParentName"] ) then ent.PlantParentName = entry["PlantParentName"] end
+ if ( entry["PlantName"] ) then ent:SetName( entry["PlantName"] ) end
+ if ( entry["material"] != "0" ) then ent:SetMaterial( entry["material"] ) end
+ if ( entry["solid"] ) then ent:SetSolid( entry["solid"] ) end
+
+ for k, v in pairs( entry["keyvalues"] ) do ent:SetKeyValue( k, v ) end
+ for k, v in pairs( entry["table"] ) do ent[ k ] = v end
+
+ ent:Spawn()
+
+ if ( entry["table"].Resources ) then
+ ent.Resources = {}
+ for k1, v1 in pairs( entry["table"].Resources ) do ent.Resources[ k1 ] = tonumber( v1 ) end
+ end
+
+ if ( player.FindByName( entry["owner"] ) ) then
+ if ( ent.IsPlant ) then ent:SetNWEntity( "plantowner", player.FindByName( entry["owner"] ) ) end
+ SPropProtection.PlayerMakePropOwner( player.FindByName( entry["owner"] ), ent )
+ elseif ( entry["owner"] == "World" ) then
+ ent:SetNetworkedString( "Owner", entry["owner"] )
+ end
+
+ if ( entry["class"] == "gms_resourcedrop" ) then // RP
+ ent.Type = entry["type"]
+ ent.Amount = entry["amount"]
+ ent:SetResourceDropInfo( ent.Type, ent.Amount )
+ end
+
+ local phys = ent:GetPhysicsObject()
+ if ( phys and phys != NULL and phys:IsValid() ) then
+ phys:EnableMotion( entry["freezed"] )
+ if ( entry["sleeping"] ) then phys:Sleep() else phys:Wake() end
+ end
+
+ if ( k >= max ) then
+ for k, ply in pairs( player.GetAll() ) do
+ ply:SendMessage( "Loaded game \"" .. savegame[ "name" ] .. "\" ( " .. max .. " entries )", 3, Color( 255, 255, 255, 255 ) )
+ ply:StopLoadingBar()
+ end
+
+ -- Fix all plants
+ for id, ent in pairs( ents.GetAll() ) do
+ if ( ent.IsPlantChild ) then
+ ent.PlantParent = ents.FindByName( ent.PlantParentName )[ 1 ]
+ if ( !IsValid( ent.PlantParent ) ) then continue end
+ ent.PlantParent:SetName( "gms_plant" .. ent.PlantParent:EntIndex() )
+ ent.PlantParentName = ent.PlantParent:GetName()
+ end
+ end
+
+ local time = 0
+ for _, v in ipairs( table.Add( ents.FindByClass( "gms_resourcepack" ), ents.FindByClass( "gms_fridge" ) ) ) do
+ for res, num in pairs( v.Resources ) do
+ timer.Simple( time, function()
+ umsg.Start( "gms_SetResPackInfo", rp )
+ umsg.String( v:EntIndex() )
+ umsg.String( string.gsub( res, "_", " " ) )
+ umsg.Short( num )
+ umsg.End()
+ end )
+ time = time + 0.1
+ end
+ time = time + 0.1
+ end
+ else
+ timer.Simple( 0.05, function() self:LoadMapEntity( savegame, max, k + 1 ) end )
+ end
+end
+
+/* Misc functions */
+hook.Add( "Think", "GM_WaterExtinguish", function()
+ for _, v in ipairs( ents.FindByClass( "prop_phy*" ) ) do
+ if ( v:WaterLevel() > 0 and v:IsOnFire() ) then
+ v:Extinguish()
+ timer.Remove( "gms_removecampfire_" .. v:EntIndex() )
+ end
+ end
+end )
+
+function GM:PlayerSwitchFlashlight( ply, SwitchOn )
+ return ( ply.Power > 25 && ply.Resources[ "Flashlight" ] != nil && ply.Resources[ "Flashlight" ] > 0 ) or !SwitchOn
+end
+
+local AlertSoundsHunger = { "stranded/need_hunger1.wav", "stranded/need_hunger2.wav" }
+local AlertSoundsThirst = { "stranded/need_thirst1.wav" }
+local AlertSoundsSleep = { "stranded/need_sleepiness1.wav", "stranded/need_sleepiness2.wav", "stranded/need_sleepiness3.wav", "stranded/need_sleepiness4.wav" }
+
+/* Alert Messages */
+timer.Create( "AlertTimer", 6, 0, function()
+ //if ( GetConVarNumber( "gms_alerts" ) != 1 ) then return end
+ for k, ply in pairs( player.GetAll() ) do
+ if ( !ply:Alive() ) then continue end
+ if ( ply.Hunger < 125 ) then ply:EmitSound( Sound( AlertSoundsHunger[ math.random( 1, #AlertSoundsHunger ) ] ), 100, math.random( 95, 105 ) ) end
+ if ( ply.Thirst < 125 ) then ply:EmitSound( Sound( AlertSoundsThirst[ math.random( 1, #AlertSoundsThirst ) ] ), 100, math.random( 95, 105 ) ) end
+ if ( ply.Sleepiness < 125 ) then ply:EmitSound( Sound( AlertSoundsSleep[ math.random( 1, #AlertSoundsSleep ) ] ), 100, math.random( 95, 105 ) ) end
+ end
+end )
+
+/* Tribe system */
+function CreateTribe( ply, name, red, green, blue, password )
+
+ name = string.Trim( name )
+ if ( name == "" ) then ply:SendMessage( "You should enter tribe name!", 5, Color( 255, 50, 50, 255 ) ) return end
+ for id, tribe in pairs( GAMEMODE.Tribes ) do
+ if ( tribe.name == name ) then ply:SendMessage( "Tribe with this name already exists!", 5, Color( 255, 50, 50, 255 ) ) return end
+ end
+
+ local id = table.insert( GAMEMODE.Tribes, {
+ name = name,
+ color = Color( red, green, blue ),
+ password = password or false
+ } )
+
+ local rp = RecipientFilter()
+ rp:AddAllPlayers()
+
+ umsg.Start( "sendTribe", rp )
+ umsg.Short( id )
+ umsg.String( name )
+ umsg.Vector( Vector( red, green, blue ) )
+ if ( Password == false ) then
+ umsg.Bool( false )
+ else
+ umsg.Bool( true )
+ end
+ umsg.End()
+
+ team.SetUp( id, name, Color( red, green, blue ) )
+ ply:SetTeam( id )
+ ply:UpdatePlayerColor()
+ SPropProtection.TribePP( ply )
+ ply:SendMessage( "Successfully created " .. name .. ".", 5, Color( 255, 255, 255, 255 ) )
+
+end
+
+function GM.CreateTribeCmd( ply, cmd, args, argv )
+ if ( !args[4] or args[4] == "" ) then ply:ChatPrint( "Syntax is: gms_createtribe \"tribename\" red green blue [password( optional )]" ) return end
+ if ( args[5] and args[5] != "" ) then
+ CreateTribe( ply, args[1], args[2], args[3], args[4], args[5] )
+ else
+ CreateTribe( ply, args[1], args[2], args[3], args[4], "" )
+ end
+end
+concommand.Add( "gms_createtribe", GM.CreateTribeCmd )
+
+function GM.JoinTribeCmd( ply, cmd, args )
+ if ( !args[ 1 ] || args[ 1 ] == "" ) then ply:ChatPrint( "Syntax is: gms_join \"tribename\" [password( if needed )]" ) return end
+ for id, v in pairs( GAMEMODE.Tribes ) do
+ if ( string.lower( v.name ) != string.lower( args[1] ) ) then continue end
+
+ if ( v.password && v.password != args[ 2 ] ) then ply:SendMessage( "Incorrcet tribal password", 3, Color( 255, 50, 50, 255 ) ) return end
+
+ ply:SetTeam( id )
+ ply:UpdatePlayerColor()
+ SPropProtection.TribePP( ply )
+ ply:SendMessage( "Joined " .. v.name .. ".", 5, Color( 255, 255, 255, 255 ) )
+ for id, pl in pairs( player.GetAll() ) do
+ if ( pl:Team() == ply:Team() && pl != ply ) then pl:SendMessage( ply:Name() .. " joined the tribe.", 5, Color( 255, 255, 255, 255 ) ) end
+ end
+ end
+ SPropProtection.CheckForEmptyTribes()
+end
+concommand.Add( "gms_join", GM.JoinTribeCmd )
+
+function GM.LeaveTribeCmd( ply, cmd, args )
+ ply:SetTeam( 1 )
+ SPropProtection.TribePP( ply )
+ ply:SendMessage( "Left the tribe.", 5, Color( 255, 255, 255, 255 ) )
+ SPropProtection.CheckForEmptyTribes()
+
+ for id, pl in pairs( player.GetAll() ) do
+ if ( pl:Team() == ply:Team() && pl != ply ) then pl:SendMessage( ply:Name() .. " left the tribe.", 5, Color( 255, 255, 255, 255 ) ) end
+ end
+end
+concommand.Add( "gms_leave", GM.LeaveTribeCmd )
+
+/* Resource Box Touch */
+function big_gms_combineresource( ent_a, ent_b )
+ local ent_a_owner = ent_a:GetNWString( "Owner" )
+ local ent_b_owner = ent_b:GetNWString( "Owner" )
+ local ply = player.GetByID( ent_a:GetNWInt( "OwnerID" ) )
+ local plyb = player.GetByID( ent_b:GetNWInt( "OwnerID" ) )
+
+ if ( ent_a_owner != nil and ent_b_owner != nil and ply != nil ) then
+ if ( ent_a_owner == ent_b_owner or ( SPropProtection.PlayerCanTouch( ply, ent_b ) and SPropProtection.PlayerCanTouch( plyb, ent_a ) ) ) then
+ ent_a.Amount = ent_a.Amount + ent_b.Amount
+ ent_a:SetResourceDropInfoInstant( ent_a.Type, ent_a.Amount )
+ ent_b:Remove()
+ end
+ end
+end
+
+/* Resource box touches Resource pack */
+function big_gms_combineresourcepack( respack, ent_b )
+ local ent_a_owner = respack:GetNWString( "Owner" )
+ local ent_b_owner = ent_b:GetNWString( "Owner" )
+ local ply = player.GetByID( respack:GetNWInt( "OwnerID" ) )
+ local plyb = player.GetByID( ent_b:GetNWInt( "OwnerID" ) )
+
+ if ( ent_a_owner != nil and ent_b_owner != nil and ply != nil ) then
+ if ( ent_a_owner == ent_b_owner or ( SPropProtection.PlayerCanTouch( ply, ent_b ) and SPropProtection.PlayerCanTouch( plyb, respack ) ) ) then
+ if ( respack.Resources[ ent_b.Type ] ) then
+ respack.Resources[ ent_b.Type ] = respack.Resources[ ent_b.Type ] + ent_b.Amount
+ else
+ respack.Resources[ ent_b.Type ] = ent_b.Amount
+ end
+ respack:SetResPackInfo( ent_b.Type, respack.Resources[ ent_b.Type ] )
+ ent_b:Remove()
+ end
+ end
+end
+
+/* Food touches Fridge */
+function big_gms_combinefood( fridge, food )
+ local ent_a_owner = fridge:GetNWString( "Owner" )
+ local ent_b_owner = food:GetNWString( "Owner" )
+ local ply = player.GetByID( fridge:GetNWInt( "OwnerID" ) )
+ local plyb = player.GetByID( food:GetNWInt( "OwnerID" ) )
+ local foodname = string.gsub( food.Name, " ", "_" )
+
+ if ( ent_a_owner != nil and ent_b_owner != nil and ply != nil ) then
+ if ( ent_a_owner == ent_b_owner or ( SPropProtection.PlayerCanTouch( ply, food ) and SPropProtection.PlayerCanTouch( plyb, fridge ) ) ) then
+ if ( fridge.Resources[ foodname ] ) then
+ fridge.Resources[ foodname ] = fridge.Resources[ foodname ] + 1
+ else
+ fridge.Resources[ foodname ] = 1
+ end
+ fridge:SetResPackInfo( foodname, fridge.Resources[ foodname ] )
+ food:Remove()
+ end
+ end
+end
+
+/* Resource Box Buildsite Touch */
+function gms_addbuildsiteresource( ent_resourcedrop, ent_buildsite )
+ local ent_resourcedrop_owner = ent_resourcedrop:GetNWString( "Owner" )
+ local ent_buildsite_owner = ent_buildsite:GetNWString( "Owner" )
+ local ply = player.GetByID( ent_resourcedrop:GetNWInt( "OwnerID" ) )
+
+ if ( ent_resourcedrop_owner != nil and ent_buildsite_owner != nil and ply != nil and ent_resourcedrop:IsPlayerHolding() ) then
+ if ( SPropProtection.PlayerCanTouch( ply, ent_buildsite ) ) then
+ if ( ent_resourcedrop.Amount > ent_buildsite.Costs[ent_resourcedrop.Type] ) then
+ ent_resourcedrop.Amount = ent_resourcedrop.Amount - ent_buildsite.Costs[ent_resourcedrop.Type]
+ ent_resourcedrop:SetResourceDropInfo( ent_resourcedrop.Type, ent_resourcedrop.Amount )
+ ent_buildsite.Costs[ent_resourcedrop.Type] = nil
+ elseif ( ent_resourcedrop.Amount <= ent_buildsite.Costs[ent_resourcedrop.Type] ) then
+ ent_buildsite.Costs[ent_resourcedrop.Type] = ent_buildsite.Costs[ent_resourcedrop.Type] - ent_resourcedrop.Amount
+ ent_resourcedrop:Remove()
+ end
+ for k, v in pairs( ent_buildsite.Costs ) do
+ if ( ent_buildsite.Costs[ent_resourcedrop.Type] ) then
+ if ( ent_buildsite.Costs[ent_resourcedrop.Type] <= 0 ) then
+ ent_buildsite.Costs[ent_resourcedrop.Type] = nil
+ end
+ end
+ end
+
+ if ( table.Count( ent_buildsite.Costs ) > 0 ) then
+ local str = "You need: "
+ for k, v in pairs( ent_buildsite.Costs ) do
+ str = str .. " " .. string.Replace( k, "_", " " ) .. " ( " .. v .. "x )"
+ end
+
+ str = str .. " to finish."
+ ply:SendMessage( str, 5, Color( 255, 255, 255, 255 ) )
+ else
+ ply:SendMessage( "Finished!", 3, Color( 10, 200, 10, 255 ) )
+ ent_buildsite:Finish()
+ end
+
+ local str = ":"
+ for k, v in pairs( ent_buildsite.Costs ) do
+ str = str .. " " .. string.Replace( k, "_", " " ) .. " ( " .. v .. "x )"
+ end
+ ent_buildsite:SetNetworkedString( "Resources", str )
+ end
+ end
+end
+
+/* Resource Pack Buildsite Touch */
+function gms_addbuildsiteresourcePack( ent_resourcepack, ent_buildsite )
+ local ent_resourcedrop_owner = ent_resourcepack:GetNWString( "Owner" )
+ local ent_buildsite_owner = ent_buildsite:GetNWString( "Owner" )
+ local ply = player.GetByID( ent_resourcepack:GetNWInt( "OwnerID" ) )
+
+ if ( ent_resourcedrop_owner != nil and ent_buildsite_owner != nil and ply != nil and ent_resourcepack:IsPlayerHolding() ) then
+ if ( SPropProtection.PlayerCanTouch( ply, ent_buildsite ) ) then
+ for res, num in pairs( ent_resourcepack.Resources ) do
+ if ( ent_buildsite.Costs[res] and num > ent_buildsite.Costs[res] ) then
+ ent_resourcepack.Resources[res] = num - ent_buildsite.Costs[res]
+ ent_resourcepack:SetResPackInfo( res, ent_resourcepack.Resources[res] )
+ ent_buildsite.Costs[res] = nil
+ elseif ( ent_buildsite.Costs[res] and num <= ent_buildsite.Costs[res] ) then
+ ent_buildsite.Costs[res] = ent_buildsite.Costs[res] - num
+ ent_resourcepack:SetResPackInfo( res, 0 )
+ ent_resourcepack.Resources[res] = nil
+ end
+ for k, v in pairs( ent_buildsite.Costs ) do
+ if ( ent_buildsite.Costs[res] ) then
+ if ( ent_buildsite.Costs[res] <= 0 ) then
+ ent_buildsite.Costs[res] = nil
+ end
+ end
+ end
+ end
+
+ if ( table.Count( ent_buildsite.Costs ) > 0 ) then
+ local str = "You need: "
+ for k, v in pairs( ent_buildsite.Costs ) do
+ str = str .. " " .. string.Replace( k, "_", " " ) .. " ( " .. v .. "x )"
+ end
+
+ str = str .. " to finish."
+ ply:SendMessage( str, 5, Color( 255, 255, 255, 255 ) )
+ else
+ ply:SendMessage( "Finished!", 3, Color( 10, 200, 10, 255 ) )
+ ent_buildsite:Finish()
+ end
+
+ local str = ":"
+ for k, v in pairs( ent_buildsite.Costs ) do
+ str = str .. " " .. string.Replace( k, "_", " " ) .. " ( " .. v .. "x )"
+ end
+ ent_buildsite:SetNetworkedString( "Resources", str )
+ end
+ end
+end
+
+/* Resource Box versus Player Damage */
+hook.Add( "PlayerShouldTakeDamage", "playershouldtakedamage", function( victim, attacker )
+ if ( victim:IsPlayer() and ( attacker:GetClass() == "gms_resourcedrop" or attacker:IsPlayerHolding() or attacker:GetClass() == "gms_resourcepack" or attacker:GetClass() == "gms_fridge" or attacker:GetClass() == "gms_food" ) ) then
+ return false
+ end
+ return true
+end )
diff --git a/ftp_gmstranded/gamemode/processes.lua b/ftp_gmstranded/gamemode/processes.lua
new file mode 100644
index 0000000..468d03e
--- /dev/null
+++ b/ftp_gmstranded/gamemode/processes.lua
@@ -0,0 +1,1269 @@
+
+local PlayerMeta = FindMetaTable( "Player" )
+local EntityMeta = FindMetaTable( "Entity" )
+
+GMS.Processes = {}
+
+function GMS.RegisterProcess( name, tbl )
+ GMS.Processes[ name ] = tbl
+end
+
+GM.ProcessThinkHookTable = {}
+hook.Add( "Think", "gms_ProcessThinkHooks", function()
+ for k, v in pairs( GAMEMODE.ProcessThinkHookTable ) do
+
+ local think
+ if ( v.Think ) then think = v:Think() end
+
+ local basethink = v:BaseThink()
+
+ if ( think or basethink or IsStopped ) then
+ if ( v.Owner and v.Owner != NULL and v.Owner:IsValid() ) then
+ v.Owner:Freeze( false )
+ v.Owner:StopProcessBar()
+ v.Owner.InProcess = false
+ v.Owner:SendMessage( "Cancelled.", 3, Color( 200, 0, 0, 255 ) )
+ end
+
+ v.IsStopped = true
+ timer.Destroy( "GMS_ProcessTimer_" .. v.TimerID )
+ GAMEMODE:RemoveProcessThink( v )
+ end
+ end
+end )
+
+function GM:RemoveProcessThink( tbl )
+ for k, v in pairs( self.ProcessThinkHookTable ) do
+ if ( v == tbl ) then table.remove( self.ProcessThinkHookTable, k ) break end
+ end
+end
+
+function PlayerMeta:DoProcess( name, time, data )
+ if ( self.InProcess ) then self:SendMessage( "You can't do this much at once.", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( self:GetNWBool( "AFK" ) ) then self:SendMessage( "You can't do this while afk.", 3, Color( 200, 0, 0, 255 ) ) return end
+ if ( self:GetNWBool( "Sleeping" ) ) then self:SendMessage( "You can't do this while sleeping.", 3, Color( 200, 0, 0, 255 ) ) return end
+
+ self.ProcessTable = table.Merge( table.Copy( GMS.Processes.BaseProcess ), table.Copy( GMS.Processes[ name ] ) )
+ self.ProcessTable.Owner = self
+ self.ProcessTable.Time = time
+ self.ProcessTable.StartTime = CurTime()
+ self.ProcessTable.TimerID = self:UniqueID()
+ if ( data ) then self.ProcessTable.Data = data end
+
+ self.InProcess = true
+ if ( self.ProcessTable.Freeze ) then self:Freeze( true ) end
+ if ( self.ProcessTable.OnStart ) then self.ProcessTable:OnStart() end
+
+ table.insert( GAMEMODE.ProcessThinkHookTable, self.ProcessTable )
+
+ timer.Create( "GMS_ProcessTimer_" .. self:UniqueID(), time, 1, function() self:StopProcess() end )
+end
+
+function PlayerMeta:MakeProcessBar( name, time, cancel )
+ umsg.Start( "gms_MakeProcessBar", self )
+ umsg.String( name )
+ umsg.Short( time )
+ umsg.Bool( cancel )
+ umsg.End()
+end
+
+function PlayerMeta:StopProcessBar()
+ umsg.Start( "gms_StopProcessBar", self )
+ umsg.End()
+end
+
+function PlayerMeta:StopProcess()
+ if ( !IsValid( self ) or self.ProcessTable == nil ) then return end
+
+ local bool = self.ProcessTable:BaseStop()
+ if ( self.ProcessTable.Freeze ) then self:Freeze( false ) end
+ if ( self.ProcessTable.OnStop ) then self.ProcessTable:OnStop() end
+ if ( self.ProcessTable.Think ) then GAMEMODE:RemoveProcessThink( self.ProcessTable ) end
+
+ self.InProcess = false
+ self.ProcessTable = nil
+end
+
+function PlayerMeta:CancelProcess()
+ if ( !self.InProcess ) then return end
+
+ local v = self.ProcessTable
+ if ( !v.Cancel ) then return end
+
+ if ( v.Owner and v.Owner != NULL and IsValid( v.Owner ) ) then
+ v.Owner:Freeze( false )
+ v.Owner:StopProcessBar()
+ v.Owner.InProcess = false
+ v.Owner:SendMessage( "Cancelled.", 3, Color( 200, 0, 0, 255 ) )
+ end
+
+ v.IsStopped = true
+ timer.Destroy( "GMS_ProcessTimer_" .. v.TimerID )
+ GAMEMODE:RemoveProcessThink( v )
+end
+
+/* Base process */
+local PROCESS = {}
+
+function PROCESS:BaseThink()
+ if ( IsValid( ent ) ) then
+ if ( self == nil or self.Owner == nil ) then return true end
+ if ( !self.Owner:IsValid() or !self.Owner:IsConnected() or !self.Owner:Alive() ) then return true end
+ end
+end
+
+function PROCESS:BaseStop()
+ if ( !IsValid( self.Owner ) or !self.Owner:Alive() ) then return false end
+ self.Owner:StopProcessBar()
+ return true
+end
+
+PROCESS.Cancel = true
+PROCESS.Freeze = true
+
+GMS.Processes.BaseProcess = PROCESS
+
+/* Stealing */
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Stealing", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ if ( !self.Data.Ent ) then return end
+
+ SPropProtection.PlayerMakePropOwner( self.Owner, self.Data.Ent )
+ self.Owner:IncXP( "Stealing", math.Clamp( math.Round( self.Time * 5 / self.Owner:GetSkill( "Stealing" ) ), 1, 1000 ) )
+
+ self.Owner:SendMessage( "Successfully stolen.", 3, Color( 50, 200, 50, 255 ) )
+end
+
+GMS.RegisterProcess( "Steal", PROCESS )
+
+/* Fruit eating process */
+local PROCESS = {}
+
+PROCESS.SideGain = {}
+PROCESS.SideGain["melon"] = "Melon_Seeds"
+PROCESS.SideGain["orange"] = "Orange_Seeds"
+PROCESS.SideGain["banana"] = "Banana_Seeds"
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Eating Fruit", self.Time, self.Cancel )
+
+ self.Owner:EmitSound( Sound( "stranded/eat.wav" ) )
+
+ local owner = nil
+ local ent = self.Data.Entity
+ local plant = ent.PlantParent
+
+ if ( plant ) then owner = plant:GetNWEntity( "plantowner" ) end
+
+ if ( self.Data.Entity:GetModel() == "models/props_junk/watermelon01.mdl" ) then
+ self.SideGain = "Melon_Seeds"
+ elseif ( self.Data.Entity:GetModel() == "models/props/cs_italy/orange.mdl" ) then
+ self.SideGain = "Orange_Seeds"
+ elseif ( self.Data.Entity:GetModel() == "models/props/cs_italy/bananna_bunch.mdl" ) then
+ self.SideGain = "Banana_Seeds"
+ end
+
+ if ( plant ) then
+ plant.Children = plant.Children - 1
+ if ( plant.Children <= 0 ) then
+ plant:Fadeout()
+ if ( IsValid( owner ) ) then owner:SetNWInt( "plants", owner:GetNWInt( "plants" ) - 1 ) end
+ end
+ end
+
+ self.Data.Entity:Fadeout( 2 )
+end
+
+function PROCESS:OnStop()
+ if ( self.SideGain ) then
+ local numto = 1
+ local numstart = 0
+ if ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_woodenspoon" ) then
+ numto = numto + 2
+ numstart = numstart + 1
+ end
+ local num = math.random( numstart, numto )
+ if ( num ~= 0 ) then
+ self.Owner:IncResource( self.SideGain, num )
+ self.Owner:SendMessage( string.gsub( self.SideGain, "_", " " ) .. " ( " .. num .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ end
+ end
+
+ self.Owner:SetFood( self.Owner.Hunger + 250 )
+ self.Owner:SendMessage( "You feel a little less hungry now.", 3, Color( 255, 255, 255, 255 ) )
+end
+
+PROCESS.Cancel = false
+
+GMS.RegisterProcess( "EatFruit", PROCESS )
+
+/* Food eating process */
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Eating", self.Time, self.Cancel )
+ self.Owner:EmitSound( Sound( "stranded/eat.wav" ) )
+
+ local ent = self.Data.Entity
+ self.Value = ent.Value
+ ent:Fadeout( 2 )
+end
+
+function PROCESS:OnStop()
+ self.Owner:SendMessage( "Restored " .. tostring( ( self.Value / 1000 ) * 100 ) .. "% food.", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:SetFood( self.Owner.Hunger + self.Value )
+ self.Owner:Heal( self.Value / 20 )
+ self.Owner:SendMessage( "Regained " .. tostring( self.Value / 20 ) .. " hp.", 3, Color( 255, 0, 0, 255 ) )
+
+ self.Owner:SetFood( self.Owner.Hunger + 250 )
+ self.Owner:SendMessage( "You feel a little less hungry now.", 3, Color( 255, 255, 255, 255 ) )
+end
+
+PROCESS.Cancel = false
+
+GMS.RegisterProcess( "EatFood", PROCESS )
+
+/*---------------------------------------------------------
+ Eat Berry
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Eating some berries", self.Time, self.Cancel )
+ self.StartTime = CurTime()
+
+ self.Owner:EmitSound( Sound( "stranded/eat.wav" ) )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Berries", 1 )
+ self.Owner:SendMessage( "You're a little less hungry and thirsty now.", 3, Color( 10, 200, 10, 255 ) )
+ if ( self.Owner.Hunger <= 900 ) then
+ self.Owner:SetFood( self.Owner.Hunger + 100 )
+ elseif ( self.Owner.Hunger >= 900 ) then
+ self.Owner:SetFood( 1000 )
+ end
+
+ if ( self.Owner.Thirst <= 900 ) then
+ self.Owner:SetThirst( self.Owner.Thirst + 100 )
+ elseif ( self.Owner.Thirst >= 900 ) then
+ self.Owner:SetThirst( 1000 )
+ end
+end
+
+PROCESS.Cancel = false
+
+GMS.RegisterProcess( "EatBerry", PROCESS )
+
+/*---------------------------------------------------------
+ Foraging process
+---------------------------------------------------------*/
+local PROCESS = {}
+
+PROCESS.Results = {}
+PROCESS.Results[1] = "Melon Seeds"
+PROCESS.Results[2] = "Banana Seeds"
+PROCESS.Results[3] = "Orange Seeds"
+PROCESS.Results[4] = "Grain Seeds"
+PROCESS.Results[5] = "Herbs"
+PROCESS.Results[6] = "Berries"
+PROCESS.Results[7] = "Baits"
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Foraging", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( num > 50 - self.Owner:GetSkill( "Harvesting" ) ) then
+ local res = self.Results[math.random( 1, #self.Results )]
+
+ local amount = math.random( 1, 3 )
+ self.Owner:IncResource( string.gsub( res, " ", "_" ), amount )
+ self.Owner:IncXP( "Harvesting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Harvesting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( res .. " ( " .. amount .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ else
+ self.Owner:SendMessage( "Found nothing of interest", 3, Color( 255, 255, 255, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "Foraging", PROCESS )
+
+/*---------------------------------------------------------
+ Looting process
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Looting", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Data.Entity:Fadeout( 2 )
+
+ for k, v in pairs( self.Data.Resources ) do
+ self.Owner:SendMessage( k .. " ( " .. v .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncResource( k, v )
+ end
+
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+end
+
+GMS.RegisterProcess( "Loot", PROCESS )
+
+/*---------------------------------------------------------
+ Salvaging process
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Salvaging", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ local ent = self.Data.Entity
+ local ply = self.Owner
+
+ if ( ent.NormalProp == true && SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ local vol = ent:GetVolume()
+
+ local res = GMS.MaterialResources[ self.Data.MatType ]
+ //local cost = math.Round( 0.6 * math.ceil( vol * ( GetConVarNumber( "gms_CostsScale" ) / 2 ) ) )
+ local cost = math.Round( 0.6 * math.ceil( vol * 0.5 ) )
+ ply:IncResource( res, cost )
+ ply:SendMessage( "Gained " .. string.Replace( res, "_", " " ) .. " ( " .. cost .. "x ) from salvaging.", 3, Color( 255, 255, 255, 255 ) )
+ elseif ( table.HasValue( GMS.StructureEntities, ent:GetClass() ) && SPropProtection.PlayerCanTouch( ply, ent ) ) then
+ local structures = GMS.Combinations[ "Structures" ]
+ local costs = {}
+ for name, t in pairs( structures ) do
+ if ( t.Results == ent:GetClass() ) then costs = t.Req end
+ end
+
+ for res, num in pairs( costs ) do
+ local cost = math.Round( 0.6 * num )
+ ply:IncResource( res, cost )
+ ply:SendMessage( "Gained " .. string.Replace( res, "_", " " ) .. " ( " .. cost .. "x ) from salvaging.", 3, Color( 255, 255, 255, 255 ) )
+ end
+ end
+
+ ent:Fadeout()
+
+ ply:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+end
+
+GMS.RegisterProcess( "Salvage", PROCESS )
+
+/*---------------------------------------------------------
+ Digging
+---------------------------------------------------------*/
+local PROCESS = {}
+
+PROCESS.Rarities = {}
+PROCESS.Rarities[1] = "Iron"
+PROCESS.Rarities[2] = "Sand"
+PROCESS.Rarities[3] = "Rope"
+PROCESS.Rarities[4] = "Bass"
+PROCESS.Rarities[5] = "Sand"
+PROCESS.Rarities[6] = "Stone"
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Digging", self.Time, self.Cancel )
+ self.StartTime = CurTime()
+
+ self:PlaySound()
+end
+
+function PROCESS:PlaySound()
+ if ( CurTime() - self.StartTime > self.Time ) then return end
+ if ( !self.Owner.InProcess || self.StartTime != self.Owner.ProcessTable.StartTime ) then return end
+
+ if ( self.Owner:Alive() ) then
+ self.Owner:GetActiveWeapon():DoEffects( self.Owner:GetEyeTrace() )
+ self.Owner:EmitSound( Sound( "player/footsteps/gravel" .. math.random( 1, 4 ) .. ".wav" ) )
+
+ timer.Simple( 1.5, function() self:PlaySound() end )
+ end
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( num < 10 ) then
+ local res = self.Rarities[math.random( 1, #self.Rarities )]
+ if ( self.Data and self.Data.Sand and math.random() > 0.50 ) then res = "Sand" end
+ self.Owner:IncResource( res, 1 )
+ self.Owner:SendMessage( res .. " ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:SendMessage( "You found something weird!", 3, Color( 255, 255, 255, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ elseif ( num > 10 and num < 40 ) then
+ self.Owner:SendMessage( "Found nothing of interest", 3, Color( 255, 255, 255, 255 ) )
+ else
+ local tr = self.Owner:TraceFromEyes( 200 )
+
+ local ent = ents.Create( "prop_physics" )
+ ent:SetPos( tr.HitPos + Vector( 0, 0, 10 ) )
+ ent:SetModel( GMS.SmallRockModel )
+ ent:Spawn()
+ SPropProtection.PlayerMakePropOwner( self.Owner, ent )
+
+ ent:Fadein( 2 )
+ ent.Uses = 10
+ end
+end
+
+GMS.RegisterProcess( "Dig", PROCESS )
+
+/*---------------------------------------------------------
+ Filter ground process
+---------------------------------------------------------*/
+local PROCESS = {}
+PROCESS.Results = {}
+PROCESS.Results[1] = "Sand"
+PROCESS.Results[2] = "Sand"
+PROCESS.Results[3] = "Sand"
+PROCESS.Results[4] = "Glass"
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Filtering Ground", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( num > 50 - self.Owner:GetSkill( "Harvesting" ) ) then
+ local res = self.Results[math.random( 1, #self.Results )]
+
+ local amount = math.random( 1, 3 )
+ self.Owner:IncResource( string.gsub( res, " ", "_" ), amount )
+ self.Owner:IncXP( "Harvesting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Harvesting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( res .. " ( " .. amount .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ else
+ self.Owner:SendMessage( "Found nothing of interest", 3, Color( 200, 10, 10, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "FilterGround", PROCESS )
+
+/*---------------------------------------------------------
+ Grain harvesting
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Harvesting Grain", self.Time, self.Cancel )
+
+ local ent = self.Data.Entity
+
+ if ( IsValid( ent ) && !ent.Uses ) then
+ ent.Uses = math.random( 1, 3 )
+ end
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+ local add = 0
+ if ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_sickle" ) then add = add + 30 end
+
+ if ( num > 50 - self.Owner:GetSkill( "Harvesting" ) - add ) then
+ local amount = math.random( 1, 2 )
+ self.Owner:IncResource( "Grain_Seeds", amount )
+ self.Owner:IncXP( "Harvesting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Harvesting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Grain Seeds ( " .. amount .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ local ent = self.Data.Entity
+ local owner = ent:GetNWEntity( "plantowner" )
+
+ if ( IsValid( ent ) && ent.Uses ) then
+ ent.Uses = ent.Uses - 1
+ if ( ent.Uses <= 0 ) then
+ if ( IsValid( owner ) ) then owner:SetNWInt( "plants", owner:GetNWInt( "plants" ) - 1 ) end
+ ent:Fadeout()
+ end
+ end
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "HarvestGrain", PROCESS )
+
+/*---------------------------------------------------------
+ Berry harvesting
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Harvesting Bush", self.Time, self.Cancel )
+ local ent = self.Data.Entity
+
+ if ( IsValid( ent ) && !ent.Uses ) then
+ ent.Uses = math.random( 1, 3 )
+ end
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ local add = 0
+ if ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_sickle" ) then add = add + 25 end
+ if ( num > 50 - self.Owner:GetSkill( "Harvesting" ) - add ) then
+ local amount = math.random( 1, 2 )
+ self.Owner:IncResource( "Berries", amount )
+ self.Owner:IncXP( "Harvesting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Harvesting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Berries ( " .. amount .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ local ent = self.Data.Entity
+ local owner = ent:GetNWEntity( "plantowner" )
+
+ if ( IsValid( ent ) && ent.Uses ) then
+ ent.Uses = ent.Uses - 1
+ if ( ent.Uses <= 0 ) then
+ if ( IsValid( owner ) ) then owner:SetNWInt( "plants", owner:GetNWInt( "plants" ) - 1 ) end
+ ent:Fadeout()
+ end
+ end
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "HarvestBush", PROCESS )
+
+/*---------------------------------------------------------
+ Make Campfire process
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ if ( GetConVarNumber( "gms_campfire" ) <= 0 ) then return end
+ self.Owner:MakeProcessBar( "Making Campfire", self.Time, self.Cancel )
+ self.Owner:EmitSound( "stranded/start_campfire.wav" )
+end
+
+function PROCESS:OnStop()
+ if ( GetConVarNumber( "gms_campfire" ) <= 0 ) then return end
+ local num = math.random( 1, 3 )
+
+ if ( num == 1 ) then
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ else
+ self.Data.Entity:MakeCampfire()
+ self.Owner:SendMessage( "Made campfire.", 5, Color( 10, 200, 100, 255 ) )
+ self.Owner:DecResource( "Wood", 5 )
+ end
+end
+
+GMS.RegisterProcess( "Campfire", PROCESS )
+
+/*---------------------------------------------------------
+ Wood cutting
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Chopping Wood", self.Time, self.Cancel )
+
+ self.StartTime = CurTime()
+
+ self:PlaySound()
+ if ( !self.Data.Entity.Uses ) then self.Data.Entity.Uses = 100 end
+end
+
+function PROCESS:PlaySound()
+ if ( CurTime() - self.StartTime > self.Time ) then return end
+ if ( !self.Owner.InProcess || self.StartTime != self.Owner.ProcessTable.StartTime ) then return end
+
+ if ( self.Owner:Alive() ) then
+ self.Owner:GetActiveWeapon():DoEffects( self.Owner:GetEyeTrace() )
+ self.Owner:EmitSound( Sound( "physics/wood/wood_solid_impact_bullet" .. tostring( math.random( 1, 5 ) ) .. ".wav" ) )
+
+ timer.Simple( 1.5, function() self:PlaySound() end )
+ end
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( num < self.Data.Chance + self.Owner:GetSkill( "Lumbering" ) ) then
+ local num2 = math.random( self.Data.MinAmount, self.Data.MaxAmount )
+ self.Owner:IncResource( "Wood", num2 )
+ self.Owner:IncXP( "Lumbering", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Lumbering" ) ), 1 , 1000 ) )
+ self.Owner:SendMessage( "Wood ( " .. num2 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+
+ if ( self.Data.Entity and self.Data.Entity.Uses ) then self.Data.Entity.Uses = self.Data.Entity.Uses - num2 end
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+
+ if ( self.Data.Entity != NULL ) then
+ if ( self.Data.Entity.Uses <= 0 ) then
+ self.Data.Entity:EmitSound( "stranded/tree_fall.wav" )
+ self.Data.Entity:Fadeout()
+ end
+ end
+end
+
+GMS.RegisterProcess( "WoodCutting", PROCESS )
+
+/* ---------------------------------------------------------
+ Mining
+--------------------------------------------------------- */
+
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Mining", self.Time, self.Cancel )
+ self.StartTime = CurTime()
+
+ self:PlaySound()
+ if ( !self.Data.Entity.Uses ) then self.Data.Entity.Uses = 250 end
+end
+
+function PROCESS:PlaySound()
+ if ( CurTime() - self.StartTime > self.Time ) then return end
+ if ( !self.Owner.InProcess || self.StartTime != self.Owner.ProcessTable.StartTime ) then return end
+
+ if ( self.Owner:Alive() ) then
+ self.Owner:GetActiveWeapon():DoEffects( self.Owner:GetEyeTrace() )
+ self.Owner:EmitSound( Sound( "physics/glass/glass_bottle_impact_hard" .. tostring( math.random( 1, 3 ) ) .. ".wav" ) )
+
+ timer.Simple( 1.5, function() self:PlaySound() end )
+ end
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+ local num2 = 1
+
+ if ( num < self.Data.Chance + self.Owner:GetSkill( "Mining" ) ) then
+ if ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_stonepickaxe" ) then
+ num2 = math.random( 1, 2 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_copperpickaxe" ) then
+ num2 = math.random( 1, 3 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_ironpickaxe" ) then
+ num2 = math.random( 1, 4 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_techpickaxe" ) then
+ num2 = math.random( 1, 5 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_silverpickaxe" ) then
+ num2 = math.random( 1, 6 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_goldpickaxe" ) then
+ num2 = math.random( 1, 7 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_steelpickaxe" ) then
+ num2 = math.random( 1, 8 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_platinumpickaxe" ) then
+ num2 = math.random( 1, 9 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_pickaxeofdjarex" ) then
+ num2 = math.random( 85, 85 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_mithrilpickaxe" ) then
+ num2 = math.random( 1, 10 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_runeapickaxe" ) then
+ num2 = math.random( 1, 8 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_runeepickaxe" ) then
+ num2 = math.random( 1, 8 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_runefpickaxe" ) then
+ num2 = math.random( 1, 8 )
+ elseif ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_runewpickaxe" ) then
+ num2 = math.random( 1, 8 )
+ end
+
+
+ local num3 = math.random( self.Data.MinAmount, self.Data.MaxAmount )
+
+ if ( num2 == 1 ) then
+ self.Owner:IncResource( "Stone", num3 )
+ self.Owner:SendMessage( "Stone ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 2 ) then
+ self.Owner:IncResource( "Copper_Ore", num3 )
+ self.Owner:SendMessage( "Copper Ore ( "..num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 3 ) then
+ self.Owner:IncResource( "Iron_Ore", num3 )
+ self.Owner:SendMessage( "Iron Ore ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 4 ) then
+ self.Owner:IncResource( "Tech_Ore", num3 )
+ self.Owner:SendMessage( "Tech Ore ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 5 ) then
+ self.Owner:IncResource( "Silver_Ore", num3 )
+ self.Owner:SendMessage( "Silver Ore ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 6 ) then
+ self.Owner:IncResource( "Gold_Ore", num3 )
+ self.Owner:SendMessage( "Gold Ore ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 7 ) then
+ self.Owner:IncResource( "Steel_Ore", num3 )
+ self.Owner:SendMessage( "Steel Ore ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 8 ) then
+ self.Owner:IncResource( "Platinum_Ore", num3 )
+ self.Owner:SendMessage( "Platinum Ore ( " .. num3 .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num2 == 85 ) then
+ self.Owner:IncResource( "Strange_Stone", num3 )
+ self.Owner:SendMessage( "Strange Stone ( " .. num3 .. "x ) ", 3, Color( 0, 247, 255, 255) )
+ elseif ( num2 == 9 ) then
+ self.Owner:IncResource( "Mithril_Ore", num3 )
+ self.Owner:SendMessage( "Mithril Ore ( " .. num3 .. "x ) ", 3, Color(10, 200, 10, 255) )
+ elseif ( num2 == 10) then
+ self.Owner:IncResource( "Adamantine_Ore", num3 )
+ self.Owner:SendMessage( "Adamantine Ore( " .. num3 .. "x ) ", 3, Color(255,0, 111, 255) )
+ end
+
+ self.Owner:IncXP( "Mining", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Mining" ) ), 1, 1000 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ if ( self.Data.Entity and self.Data.Entity.Uses ) then self.Data.Entity.Uses = self.Data.Entity.Uses - num3 end
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+
+ if ( GetConVarNumber( "gms_FadeRocks" ) == 1 and self.Data.Entity != NULL ) then
+ if ( self.Data.Entity.Uses <= 0 ) then
+ self.Data.Entity:Fadeout()
+ end
+ end
+end
+
+GMS.RegisterProcess( "Mining", PROCESS )
+
+/*---------------------------------------------------------
+ Sprout collect
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ if ( self.Owner:HasUnlock( "Sprout_Collecting" ) ) then
+ self.Owner:MakeProcessBar( "Loosening sprout", self.Time, self.Cancel )
+ else
+ self.IsStopped = true
+ end
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+ local add = 0
+
+ if ( IsValid( self.Owner:GetActiveWeapon() ) && self.Owner:GetActiveWeapon():GetClass() == "gms_sickle" ) then add = add + 30 end
+
+ if ( num > 50 - self.Owner:GetSkill( "Harvesting" ) - add ) then
+ self.Owner:IncResource( "Sprouts", 1 )
+ self.Owner:IncXP( "Harvesting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Harvesting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Sprout ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "items/ammo_pickup.wav" ) )
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "SproutCollect", PROCESS )
+
+/*---------------------------------------------------------
+ Plant Melon
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Planting Watermelon", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Melon_Seeds", 1 )
+ self.Owner:IncXP( "Planting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Planting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Successfully planted.", 3, Color( 10, 200, 10, 255 ) )
+
+ local ent = ents.Create( "gms_seed" )
+ SPropProtection.PlayerMakePropOwner( self.Owner, ent )
+ ent:SetPos( self.Data.Pos )
+ ent:Setup( "melon", 160 - math.Clamp( self.Owner:GetSkill( "Planting" ), 0, 60 ) + math.random( -20, 20 ), self.Owner )
+ ent:Spawn()
+end
+
+GMS.RegisterProcess( "PlantMelon", PROCESS )
+
+/*---------------------------------------------------------
+ Plant Banana
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Planting Banana", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Banana_Seeds", 1 )
+ self.Owner:IncXP( "Planting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Planting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Successfully planted.", 3, Color( 10, 200, 10, 255 ) )
+
+ local ent = ents.Create( "gms_seed" )
+ SPropProtection.PlayerMakePropOwner( self.Owner , ent )
+ ent:SetPos( self.Data.Pos )
+ ent:Setup( "banana", 160 - math.Clamp( self.Owner:GetSkill( "Planting" ), 0, 60 ) + math.random( -20, 20 ), self.Owner )
+ ent:Spawn()
+end
+
+GMS.RegisterProcess( "PlantBanana", PROCESS )
+
+/*---------------------------------------------------------
+ Plant Orange
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Planting Orange", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Orange_Seeds", 1 )
+ self.Owner:IncXP( "Planting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Planting" ) ) , 1, 1000 ) )
+ self.Owner:SendMessage( "Successfully planted.", 3, Color( 10, 200, 10, 255 ) )
+
+ local ent = ents.Create( "gms_seed" )
+ SPropProtection.PlayerMakePropOwner( self.Owner, ent )
+ ent:SetPos( self.Data.Pos )
+ ent:Setup( "orange", 160 - math.Clamp( self.Owner:GetSkill( "Planting" ), 0, 60 ) + math.random( -20, 20 ), self.Owner )
+ ent:Spawn()
+end
+
+GMS.RegisterProcess( "PlantOrange", PROCESS )
+
+/*---------------------------------------------------------
+ Plant Grain
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Planting Grain", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Grain_Seeds", 1 )
+ self.Owner:IncXP( "Planting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Planting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Successfully planted.", 3, Color( 10, 200, 10, 255 ) )
+
+ local ent = ents.Create( "gms_seed" )
+ SPropProtection.PlayerMakePropOwner( self.Owner, ent )
+ ent:SetPos( self.Data.Pos )
+ ent:Setup( "grain", 160 - math.Clamp( self.Owner:GetSkill( "Planting" ), 0, 60 ) + math.random( -20, 20 ), self.Owner )
+ ent:Spawn()
+end
+
+GMS.RegisterProcess( "PlantGrain", PROCESS )
+
+/*---------------------------------------------------------
+ Plant Bush
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Planting Berry Bush", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Berries", 1 )
+ self.Owner:IncXP( "Planting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Planting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Successfully planted.", 3, Color( 10, 200, 10, 255 ) )
+
+ local ent = ents.Create( "gms_seed" )
+ SPropProtection.PlayerMakePropOwner( self.Owner, ent )
+ ent:SetPos( self.Data.Pos )
+ ent:Setup( "berry", 160 - math.Clamp( self.Owner:GetSkill( "Planting" ), 0, 60 ) + math.random( -20, 20 ), self.Owner )
+ ent:Spawn()
+end
+
+GMS.RegisterProcess( "PlantBush", PROCESS )
+
+/*---------------------------------------------------------
+ Plant Tree
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Planting Tree", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Sprouts", 1 )
+ self.Owner:IncXP( "Planting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Planting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Successfully planted.", 3, Color( 10, 200, 10, 255 ) )
+
+ local ent = ents.Create( "gms_seed" )
+ SPropProtection.PlayerMakePropOwner( self.Owner, ent )
+ ent:SetPos( self.Data.Pos )
+ ent:Setup( "tree", 240 - math.Clamp( self.Owner:GetSkill( "Planting" ), 0, 60 ) + math.random( -20, 20 ), self.Owner )
+ ent:Spawn()
+end
+
+GMS.RegisterProcess( "PlantTree", PROCESS )
+
+/*---------------------------------------------------------
+ Assembling
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Assembling", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:SendMessage( "Assembly successful.", 3, Color( 10, 200, 10, 255 ) )
+end
+
+PROCESS.Cancel = false
+
+GMS.RegisterProcess( "Assembling", PROCESS )
+
+/*---------------------------------------------------------
+ Fishing
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Fishing", self.Time, self.Cancel )
+ self.Owner:EmitSound( "stranded/start_fishing.wav" )
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( !self.Owner.Resources['Baits'] or self.Owner.Resources['Baits'] < 1 ) then
+ self.Data.Chance = self.Data.Chance * 0.25
+ end
+
+ if ( num < self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) then
+ if ( self.Owner.Resources['Baits'] and self.Owner.Resources['Baits'] > 0 ) then
+ self.Owner:DecResource( "Baits", 1 )
+ end
+
+ if ( num < ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.5 ) then
+ self.Owner:IncResource( "Bass", 1 )
+ self.Owner:SendMessage( "Bass ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num >= ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.5 && num < ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.2 ) then
+ self.Owner:IncResource( "Trout", 1 )
+ self.Owner:SendMessage( "Trout ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num >= ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.2 && num < self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) then
+ self.Owner:IncResource( "Salmon", 1 )
+ self.Owner:SendMessage( "Salmon ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ end
+
+ self.Owner:IncXP( "Fishing", math.Clamp( math.Round( 250 / self.Owner:GetSkill( "Fishing" ) ), 1, 1000 ) )
+ self.Owner:EmitSound( Sound( "ambient/water/water_splash" .. math.random( 1, 3 ) .. ".wav" ) )
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "Fishing", PROCESS )
+
+/*---------------------------------------------------------
+ Advanced Fishing
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Fishing", self.Time, self.Cancel )
+ self.Owner:EmitSound( "stranded/start_fishing.wav" )
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( !self.Owner.Resources['Baits'] or self.Owner.Resources['Baits'] < 1 ) then
+ self.Data.Chance = self.Data.Chance * 0.25
+ end
+
+ if ( num < self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) then
+ if ( self.Owner.Resources['Baits'] and self.Owner.Resources['Baits'] > 0 ) then
+ self.Owner:DecResource( "Baits", 1 )
+ end
+
+ if ( num < ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 2 ) then
+ self.Owner:IncResource( "Bass", 1 )
+ self.Owner:SendMessage( "Bass ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num >= ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 2 && num < ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.5 ) then
+ self.Owner:IncResource( "Trout", 1 )
+ self.Owner:SendMessage( "Trout ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num >= ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.5 && num < ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.2 ) then
+ self.Owner:IncResource( "Salmon", 1 )
+ self.Owner:SendMessage( "Salmon ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ elseif ( num >= ( self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) / 1.2 && num < self.Data.Chance + self.Owner:GetSkill( "Fishing" ) ) then
+ self.Owner:IncResource( "Shark", 1 )
+ self.Owner:SendMessage( "Shark ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ end
+
+ self.Owner:IncXP( "Fishing", math.Clamp( math.Round( 250 / self.Owner:GetSkill( "Fishing" ) ), 1, 1000 ) )
+ self.Owner:EmitSound( Sound( "ambient/water/water_splash" .. math.random( 1, 3 ) .. ".wav" ) )
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+ end
+end
+
+GMS.RegisterProcess( "AdvancedFishing", PROCESS )
+
+/*---------------------------------------------------------
+ Bottle Water
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Bottling Water", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ if (self.Owner:GetActiveWeapon():GetClass() == "gms_bucket") then
+ self.Owner:IncResource( "Water_Bottles", 10 )
+ self.Owner:SendMessage( "Water Bottle ( 10x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "ambient/water/water_spray" .. math.random( 1, 3 ) .. ".wav" ) )
+ else
+ self.Owner:IncResource( "Water_Bottles", 1 )
+ self.Owner:SendMessage( "Water Bottle ( 1x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:EmitSound( Sound( "ambient/water/water_spray" .. math.random( 1, 3 ) .. ".wav" ) )
+ end
+end
+
+GMS.RegisterProcess( "BottleWater", PROCESS )
+
+/*---------------------------------------------------------
+ Drink bottle
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Drinking Bottle", self.Time, self.Cancel )
+ self.StartTime = CurTime()
+
+ self:PlaySound()
+end
+
+function PROCESS:PlaySound()
+ if ( CurTime() - self.StartTime > self.Time ) then return end
+ if ( !self.Owner.InProcess || self.StartTime != self.Owner.ProcessTable.StartTime ) then return end
+
+ if ( self.Owner:Alive() ) then
+ self.Owner:EmitSound( Sound( "npc/barnacle/barnacle_gulp" .. math.random( 1, 2 ) .. ".wav" ) )
+ timer.Simple( 0.75, function() self:PlaySound() end )
+ end
+end
+
+function PROCESS:OnStop()
+ self.Owner:DecResource( "Water_Bottles", 1 )
+ self.Owner:SendMessage( "You're a little less thirsty now.", 3, Color( 10, 200, 10, 255 ) )
+ if ( self.Owner.Thirst <= 750 ) then
+ self.Owner:SetThirst( self.Owner.Thirst + 250 )
+ elseif ( self.Owner.Thirst >= 750 ) then
+ self.Owner:SetThirst( 1000 )
+ end
+end
+
+PROCESS.Cancel = false
+
+GMS.RegisterProcess( "DrinkBottle", PROCESS )
+
+/*---------------------------------------------------------
+ Take Medicine
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ if ( self.Owner:Health() >= 200 or ( self.Owner:Health() >= 150 and self.Owner:HasUnlock( "Master_Survivalist" ) != true ) or ( self.Owner:Health() >= 100 and self.Owner:HasUnlock( "Adept_Survivalist" ) != true ) ) then
+ self.Owner:SendMessage( "You're feeling good, why would you heal yourself.", 3, Color( 200, 0, 0, 255 ) )
+ else
+ self.Owner:MakeProcessBar( "Taking Medicine", self.Time, self.Cancel )
+ self.Owner:EmitSound( Sound( "items/smallmedkit1.wav" ) )
+ end
+end
+
+function PROCESS:OnStop()
+ if ( self.Owner:Health() >= 200 or ( self.Owner:Health() >= 150 and self.Owner:HasUnlock( "Master_Survivalist" ) != true ) or ( self.Owner:Health() >= 100 and self.Owner:HasUnlock( "Adept_Survivalist" ) != true ) ) then return end
+ self.Owner:DecResource( "Medicine", 1 )
+ self.Owner:SendMessage( "You're feeling a bit better now.", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:Heal( 10 )
+end
+
+GMS.RegisterProcess( "TakeMedicine", PROCESS )
+
+/*---------------------------------------------------------
+ Cooking
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Cooking " .. self.Data.Name, self.Time, self.Cancel )
+ self.Sound = CreateSound( self.Owner, Sound( "npc/headcrab/headcrab_burning_loop2.wav" ) )
+ self.Sound:Play()
+end
+
+function PROCESS:OnStop()
+ local num = math.random( 1, 100 )
+
+ if ( num + self.Owner:GetSkill( "Cooking" ) >= 50 ) then
+ self.Owner:SendMessage( "Successfully cooked.", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncXP( "Cooking", math.Clamp( math.Round( 150 / self.Owner:GetSkill( "Cooking" ) ), 1, 1000 ) )
+
+ local food = ents.Create( "gms_food" )
+ food:SetPos( self.Owner:TraceFromEyes( 70 ).HitPos + Vector( 0, 0, 5 ) )
+ SPropProtection.PlayerMakePropOwner( self.Owner, food )
+ food.Value = self.Data.FoodValue
+ food.Name = self.Data.Name
+ food:Spawn()
+ food:SetFoodInfo( self.Data.Name )
+
+ timer.Simple( math.random( 240, 320 ), function() if ( IsValid( food ) ) then food:Fadeout( 2 ) end end )
+
+ for k, v in pairs( self.Data.Cost ) do self.Owner:DecResource( k, v ) end
+ else
+ self.Owner:SendMessage( "Failed.", 3, Color( 200, 0, 0, 255 ) )
+
+ local num = math.random( 1, 2 )
+
+ if ( num == 1 ) then
+ for k, v in pairs( self.Data.Cost ) do
+ self.Owner:DecResource( k, v )
+ end
+ self.Owner:SendMessage( "The ingredients was wasted!", 3, Color( 200, 0, 0, 255 ) )
+ end
+ end
+
+ self.Sound:Stop()
+end
+
+GMS.RegisterProcess( "Cook", PROCESS )
+
+/*---------------------------------------------------------
+ Make Weapon
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Crafting " .. self.Data.Name, self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:SendMessage( "Made a " .. self.Data.Name .. ".", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncXP( "Weapon_Crafting", math.Clamp( math.Round( 50 / self.Owner:GetSkill( "Weapon_Crafting" ) ), 1, 1000 ) )
+
+ if ( self.Owner:HasWeapon( self.Data.Class ) ) then
+ local weap = ents.Create( self.Data.Class )
+ weap:SetPos( self.Owner:TraceFromEyes( 100 ).HitPos + Vector( 0, 0, 15 ) )
+ weap:Spawn()
+ SPropProtection.PlayerMakePropOwner( self.Owner, weap )
+ else
+ self.Owner:Give( self.Data.Class )
+ end
+
+ for k, v in pairs( self.Data.Cost ) do
+ self.Owner:DecResource( k, v )
+ end
+end
+
+GMS.RegisterProcess( "MakeWeapon", PROCESS )
+
+/*---------------------------------------------------------
+ MakeGeneric
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Making " .. self.Data.Name, self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ for k, v in pairs( self.Data.Cost ) do
+ self.Owner:DecResource( k, v )
+ end
+
+ for k, v in pairs( self.Data.Res ) do
+ self.Owner:SendMessage( "Made " .. string.gsub( k, "_", " " ) .. " ( " .. v .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncResource( k, v )
+ end
+end
+
+GMS.RegisterProcess( "MakeGeneric", PROCESS )
+
+/*---------------------------------------------------------
+ Make Building
+---------------------------------------------------------*/
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Setting up " .. self.Data.Name .. " site", self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ self.Owner:SendMessage( "Made a " .. self.Data.Name .. " site.", 3, Color( 10, 200, 10, 255 ) )
+
+ if ( self.Owner:GetBuildingSite() and self.Owner:GetBuildingSite():IsValid() ) then
+ ent = self.Owner:GetBuildingSite()
+ ent:Remove()
+ end
+
+ local site = self.Owner:CreateStructureBuildingSite( self.Data.Pos, self.Owner:GetAngles(), self.Data.BuildSiteModel, self.Data.Class, self.Data.Cost, self.Data.Name )
+end
+
+GMS.RegisterProcess( "MakeBuilding", PROCESS )
+
+/* Smelt */
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Smelting " .. self.Data.Name, self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ for k, v in pairs( self.Data.Cost ) do
+ self.Owner:DecResource( k, v )
+ end
+
+ for k, v in pairs( self.Data.Res ) do
+ self.Owner:SendMessage( "Made " .. string.gsub( k, "_", " " ) .. " ( " .. v .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncResource( k, v )
+
+ self.Owner:IncXP( "Smelting", math.Clamp( math.Round( ( v * 10 ) / self.Owner:GetSkill( "Smelting" ) ), 1, 1000 ) )
+ end
+end
+
+GMS.RegisterProcess( "Smelt", PROCESS )
+
+/* Crush */
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Crushing " .. self.Data.Name, self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ for k, v in pairs( self.Data.Cost ) do
+ self.Owner:DecResource( k, v )
+ end
+
+ for k, v in pairs( self.Data.Res ) do
+ self.Owner:SendMessage( "Made " .. string.gsub( k, "_", " " ) .. " ( " .. v .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncResource( k, v )
+ end
+end
+
+GMS.RegisterProcess( "Crush", PROCESS )
+
+/* Processing */
+local PROCESS = {}
+
+function PROCESS:OnStart()
+ self.Owner:MakeProcessBar( "Processing " .. self.Data.Name, self.Time, self.Cancel )
+end
+
+function PROCESS:OnStop()
+ for k, v in pairs( self.Data.Cost ) do
+ self.Owner:DecResource( k, v )
+ end
+
+ for k, v in pairs( self.Data.Res ) do
+ self.Owner:IncXP( "Weapon_Crafting", math.Clamp( math.Round( 150 / self.Owner:GetSkill( "Weapon_Crafting" ) ), 1, 1000 ) )
+ self.Owner:SendMessage( "Made " .. string.gsub( k, "_", " " ) .. " ( " .. v .. "x )", 3, Color( 10, 200, 10, 255 ) )
+ self.Owner:IncResource( k, v )
+ end
+end
+
+GMS.RegisterProcess( "Processing", PROCESS )
diff --git a/ftp_gmstranded/gamemode/resources.lua b/ftp_gmstranded/gamemode/resources.lua
new file mode 100644
index 0000000..780c3f5
--- /dev/null
+++ b/ftp_gmstranded/gamemode/resources.lua
@@ -0,0 +1,68 @@
+
+/*------------------------ Models ------------------------*/
+
+resource.AddFile( "models/weapons/v_fists.mdl" )
+resource.AddFile( "models/weapons/w_fists.mdl" )
+resource.AddFile( "models/weapons/v_shovel.mdl" )
+resource.AddFile( "models/weapons/w_shovel.mdl" )
+resource.AddFile( "models/weapons/v_copper_pickaxe.mdl" )
+resource.AddFile( "models/weapons/w_copper_pickaxe.mdl" )
+resource.AddFile( "models/weapons/v_iron_pickaxe.mdl" )
+resource.AddFile( "models/weapons/w_iron_pickaxe.mdl" )
+resource.AddFile( "models/weapons/v_stone_pickaxe.mdl" )
+resource.AddFile( "models/weapons/w_stone_pickaxe.mdl" )
+resource.AddFile( "models/weapons/v_copper_hatchet.mdl" )
+resource.AddFile( "models/weapons/v_iron_hatchet.mdl" )
+resource.AddFile( "models/weapons/v_stone_hatchet.mdl" )
+resource.AddFile( "models/weapons/w_copper_hatchet.mdl" )
+resource.AddFile( "models/weapons/w_iron_hatchet.mdl" )
+resource.AddFile( "models/weapons/w_stone_hatchet.mdl" )
+
+resource.AddFile( "models/gm_forest/tree_oak1.mdl" )
+
+/*------------------------ Materials ------------------------*/
+
+resource.AddFile( "materials/models/weapons/shovel/shovel1.vmt" )
+resource.AddFile( "materials/models/weapons/shovel/shovel1.vtf" )
+resource.AddFile( "materials/models/weapons/shovel/shovel1_n.vtf" )
+resource.AddFile( "materials/models/weapons/shovel/shovel2.vmt" )
+resource.AddFile( "materials/models/weapons/shovel/shovel2.vtf" )
+resource.AddFile( "materials/models/weapons/shovel/shovel2_n.vtf" )
+resource.AddFile( "materials/models/weapons/shovel/shovel3.vmt" )
+resource.AddFile( "materials/models/weapons/shovel/shovel3.vtf" )
+resource.AddFile( "materials/models/weapons/shovel/shovel3_n.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/copper/copper.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/copper/copper_n.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/copper/pickaxe01.vmt" )
+resource.AddFile( "materials/models/weapons/pickaxe/stone/pickaxe01.vmt" )
+resource.AddFile( "materials/models/weapons/pickaxe/stone/stone.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/stone/stone_n.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/iron/iron.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/iron/iron_n.vtf" )
+resource.AddFile( "materials/models/weapons/pickaxe/iron/pickaxe01.vmt" )
+resource.AddFile( "materials/models/weapons/hatchet/copper/axe.vmt" )
+resource.AddFile( "materials/models/weapons/hatchet/copper/Copper.vtf" )
+resource.AddFile( "materials/models/weapons/hatchet/copper/Copper_n.vtf" )
+resource.AddFile( "materials/models/weapons/hatchet/stone/axe.vmt" )
+resource.AddFile( "materials/models/weapons/hatchet/stone/stone.vtf" )
+resource.AddFile( "materials/models/weapons/hatchet/stone/stone_n.vtf" )
+resource.AddFile( "materials/models/weapons/hatchet/iron/axe.vmt" )
+resource.AddFile( "materials/models/weapons/hatchet/iron/iron.vtf" )
+resource.AddFile( "materials/models/weapons/hatchet/iron/iron_n.vtf" )
+resource.AddFile( "materials/models/weapons/hands.vmt" )
+resource.AddFile( "materials/models/weapons/hands.vtf" )
+resource.AddFile( "materials/models/weapons/hands_normal.vtf" )
+
+resource.AddFile( "materials/gm_forest/oak_brk.vmt" )
+resource.AddFile( "materials/gm_forest/brg_eik_brn2.vmt" )
+resource.AddFile( "materials/gm_forest/brg_eik_brn2.vtf" )
+
+/*------------------------ Sounds ------------------------*/
+
+resource.AddFile( "sound/citizen_beaten1.wav" )
+resource.AddFile( "sound/citizen_beaten4.wav" )
+resource.AddFile( "sound/citizen_beaten5.wav" )
+resource.AddFile( "sound/cough1.wav" )
+resource.AddFile( "sound/cough2.wav" )
+resource.AddFile( "sound/cough3.wav" )
+resource.AddFile( "sound/cough4.wav" )
diff --git a/ftp_gmstranded/gamemode/shared.lua b/ftp_gmstranded/gamemode/shared.lua
new file mode 100644
index 0000000..b8e7ac5
--- /dev/null
+++ b/ftp_gmstranded/gamemode/shared.lua
@@ -0,0 +1,1029 @@
+
+/*
+ Authors! The Stranded Team!
+ jA_cOp, prop_dynamic, Chewgum, Wokkel, robotboy655
+
+ READ THIS:
+ If you want to add custom content or edit anything in gamemode - DO NOT. Please read customcontent.lua!
+
+ ÏÐÎ×ÒÈ ÝÒÎ:
+ Åñëè òû ñîáèðàåøüñÿ òóò ÷òî ëèáî èçìåíÿòü - ÍÅ ÄÅËÀÉ ÝÒÎÃÎ. Ïðî÷òè ôàéë customcontent.lua!
+*/
+
+DeriveGamemode( "sandbox" )
+
+GM.Name = "Garry's Mod Stranded"
+GM.Author = "Stranded Team"
+GM.Email = "robotboy655@gmail.com"
+GM.Website = ""
+
+team.SetUp( 1, "The Stranded", Color( 200, 200, 0, 255 ) )
+team.SetUp( 2, "Survivalists", Color( 255, 255, 255, 255 ) )
+team.SetUp( 3, "Anonymous", Color( 0, 121, 145, 255 ) )
+team.SetUp( 4, "The Gummies", Color( 255, 23, 0, 255 ) )
+team.SetUp( 5, "The Dynamics", Color( 0, 72, 255, 255 ) )
+team.SetUp( 6, "Scavengers", Color( 8, 255, 0, 255 ) )
+
+GMS = GMS or {}
+
+include( "spp/sh_spp.lua" )
+include( "time_weather.lua" )
+
+-- Shared includes
+include( "unlocks.lua" )
+include( "combinations.lua" )
+include( "combinations2.lua" )
+include( "combirenbuy.lua" )
+include( "combirensell.lua" )
+
+/* ----------------------------------------------------------------------------------------------------
+ Utility functions
+---------------------------------------------------------------------------------------------------- */
+
+
+
+function string.Capitalize( str )
+ local str = string.Explode( "_", str )
+ for k, v in pairs( str ) do
+ str[ k ] = string.upper( string.sub( v, 1, 1 ) ) .. string.sub( v, 2 )
+ end
+
+ str = string.Implode( "_", str )
+ return str
+end
+
+function player.FindByName( str )
+ if ( str == nil or str == "" ) then return false end
+ for id, ply in pairs( player.GetAll() ) do
+ if ( string.find( string.lower( ply:Name() ), string.lower( str ) ) != nil ) then
+ return ply
+ end
+ end
+ return false
+end
+
+function GMS_IsAdminOnlyModel( mdl )
+ if ( mdl == GMS.SmallRockModel ) then return true end
+ if ( table.HasValue( GMS.EdibleModels, mdl ) ) then return true end
+ if ( table.HasValue( GMS.RockModels, mdl ) ) then return true end
+ if ( table.HasValue( GMS.AdditionalRockModels, mdl ) ) then return true end
+ if ( table.HasValue( GMS.TreeModels, mdl ) ) then return true end
+ if ( table.HasValue( GMS.AdditionalTreeModels, mdl ) ) then return true end
+ return false
+end
+
+function GMS.ClassIsNearby( pos, class, range )
+ local nearby = false
+ for k, v in pairs( ents.FindInSphere( pos, range ) ) do
+ if ( v:GetClass() == class and ( pos - Vector( v:LocalToWorld( v:OBBCenter() ).x, v:LocalToWorld( v:OBBCenter() ).y, pos.z ) ):Length() <= range ) then
+ nearby = true
+ end
+ end
+
+ return nearby
+end
+
+function GMS.IsInWater( pos )
+ local trace = {}
+ trace.start = pos
+ trace.endpos = pos + Vector( 0, 0, 1 )
+ trace.mask = bit.bor( MASK_WATER, MASK_SOLID )
+
+ local tr = util.TraceLine( trace )
+ return tr.Hit
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Player Functions
+---------------------------------------------------------------------------------------------------- */
+
+local PlayerMeta = FindMetaTable( "Player" )
+
+function PlayerMeta:IsDeveloper()
+ if ( self:SteamID() == "STEAM_0:0:18313012" ) then return true end
+ return false
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Entity Functions
+---------------------------------------------------------------------------------------------------- */
+
+local EntityMeta = FindMetaTable( "Entity" )
+
+function EntityMeta:IsTreeModel()
+ if ( !IsValid( self ) || !self.GetModel || !self:GetModel() ) then return false end
+
+ for k, v in pairs( GMS.TreeModels ) do
+ if ( string.lower( v ) == string.lower( self:GetModel() ) or string.gsub( string.lower( v ), "/", "\\" ) == string.lower( self:GetModel() ) ) then return true end
+ end
+
+ for k, v in pairs( GMS.AdditionalTreeModels ) do
+ if ( string.lower( v ) == string.lower( self:GetModel() ) or string.gsub( string.lower( v ), "/", "\\" ) == string.lower( self:GetModel() ) ) then return true end
+ end
+
+ -- Experemental
+ if ( SERVER && string.find( self:GetModel(), "tree" ) && self:CreatedByMap() ) then return true end
+
+ return false
+end
+
+function EntityMeta:IsRockModel()
+ if ( !IsValid( self ) ) then return false end
+
+ local mdl = string.lower( self:GetModel() )
+
+ if ( mdl == string.lower( GMS.SmallRockModel ) ) then return true end
+
+ for k, v in pairs( GMS.RockModels ) do
+ if ( string.lower( v ) == mdl or string.gsub( string.lower( v ), "/", "\\" ) == mdl ) then return true end
+ end
+
+ for k, v in pairs( GMS.AdditionalRockModels ) do
+ if ( string.lower( v ) == mdl or string.gsub( string.lower( v ), "/", "\\" ) == mdl ) then return true end
+ end
+
+ -- Experemental
+ if ( SERVER && string.find( self:GetModel(), "rock" ) && self:CreatedByMap() ) then return true end
+
+ return false
+end
+
+function EntityMeta:IsBerryBushModel()
+ if ( !IsValid( self ) ) then return false end
+
+ local mdl = "models/props/pi_shrub.mdl"
+ if ( mdl == self:GetModel() or string.gsub( mdl, "/", "\\" ) == self:GetModel() ) then return true end
+
+ return false
+end
+
+function EntityMeta:IsGrainModel()
+ if ( !IsValid( self ) ) then return false end
+
+ local mdl = "models/props_foliage/cattails.mdl"
+ if ( mdl == self:GetModel() or string.gsub( mdl, "/", "\\" ) == self:GetModel() ) then return true end
+
+ return false
+end
+
+function EntityMeta:IsFoodModel()
+ if ( !IsValid( self ) ) then return false end
+
+ for k, v in pairs( GMS.EdibleModels ) do
+ if ( string.lower( v ) == string.lower( self:GetModel() ) or string.gsub( string.lower( v ), "/", "\\" ) == string.lower( self:GetModel() ) ) then
+ return true
+ end
+ end
+
+ return false
+end
+
+function EntityMeta:IsProp()
+ if ( !IsValid( self ) ) then return false end
+
+ local cls = self:GetClass()
+ if ( cls == "prop_physics" or cls == "prop_physics_multiplayer" or cls == "prop_dynamic" ) then return true end
+
+ return false
+end
+
+function EntityMeta:GetVolume()
+ local min, max = self:OBBMins(), self:OBBMaxs()
+ local vol = math.abs( max.x - min.x ) * math.abs( max.y - min.y ) * math.abs( max.z - min.z )
+ return vol / ( 16 ^ 3 )
+end
+
+function EntityMeta:IsSleepingFurniture()
+ for _, v in ipairs( GMS.SleepingFurniture ) do
+ if ( string.lower( v ) == self:GetModel() or string.gsub( string.lower( v ), "/", "\\" ) == self:GetModel() ) then
+ return true
+ end
+ end
+
+ return false
+end
+
+function EntityMeta:IsPickupProhibitedModel()
+ if ( !IsValid( self ) ) then return end
+ return table.HasValue( GMS.PickupProhibitedClasses, self:GetClass() )
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Shared Hooks ( for prediction )
+---------------------------------------------------------------------------------------------------- */
+
+function GM:PlayerNoClip( pl, on )
+ if ( pl:InVehicle() ) then return false end
+ if ( pl:IsDeveloper() || game.SinglePlayer() ) then return true end
+ return false
+end
+
+function GM:PhysgunPickup( ply, ent )
+ if ( !IsValid( ent ) ) then return self.BaseClass.PhysgunPickup( self, ply, ent ) end
+ if ( ent:IsRockModel() || ent:IsNPC() || ent:IsTreeModel() || ent:IsPlayer() || ent:IsFoodModel() || ent:IsPickupProhibitedModel() ) then return false end
+
+ if ( !SPropProtection.PhysGravGunPickup( ply, ent ) ) then return false end
+
+ return self.BaseClass.PhysgunPickup( self, ply, ent )
+end
+
+function GM:GravGunPunt( ply, ent )
+ if ( !IsValid( ent ) ) then return self.BaseClass.GravGunPunt( self, ply, ent ) end
+ if ( ent:IsRockModel() || ent:IsNPC() || ent:IsTreeModel() || ent:IsPlayer() || ent:IsFoodModel() || ent:IsPickupProhibitedModel() || ent:GetClass() == "gms_buildsite" ) then return false end
+
+ if ( !SPropProtection.PhysGravGunPickup( ply, ent ) ) then return false end
+
+ return self.BaseClass.GravGunPunt( self, ply, ent )
+end
+
+function GM:GravGunPickupAllowed( ply, ent )
+ if ( !IsValid( ent ) ) then return self.BaseClass.GravGunPickupAllowed( self, ply, ent ) end
+ if ( ent:IsRockModel() || ent:IsNPC() || ent:IsTreeModel() || ent:IsPlayer() || ent:IsFoodModel() || ent:IsPickupProhibitedModel() || ent:GetClass() == "gms_buildsite" ) then return false end
+
+ if ( !SPropProtection.PhysGravGunPickup( ply, ent ) ) then return false end
+
+ return self.BaseClass.GravGunPickupAllowed( self, ply, ent )
+end
+
+function GM:CanTool( ply, tr, mode )
+
+ if ( mode == "gms_rope" ) then
+ if ( SERVER && ply:GetResource( "Rope" ) < 1 ) then ply:SendMessage( "You need rope to use this tool.", 3, Color( 200, 0, 0, 255 ) ) return false end
+ if ( CLIENT && ( !Resources[ "Rope" ] || Resources[ "Rope" ] < 1 ) ) then return false end
+ end
+
+ if ( mode == "weld" ) then
+ if ( SERVER && ply:GetResource( "Welder" ) < 1 ) then ply:SendMessage( "You need a Welder to use this tool.", 3, Color( 200, 0, 0, 255 ) ) return false end
+ if ( CLIENT && ( !Resources[ "Welder" ] || Resources[ "Welder" ] < 1 ) ) then return false end
+ end
+
+ if ( table.HasValue( GMS.ProhibitedStools, mode ) && !ply:IsAdmin() ) then ply:SendMessage( "This tool is prohibited.", 3, Color( 200, 0, 0, 255 ) ) return false end
+
+ local ent = tr.Entity
+ if ( !IsValid( ent ) && ent:GetClass() != "worldspawn" ) then return end
+
+ if ( !SPropProtection.PhysGravGunPickup( ply, ent ) ) then return false end
+
+ if ( ent:IsRockModel() || ent:IsNPC() || ent:IsTreeModel() || ent:IsPlayer() || ent:IsFoodModel() || ent:IsPickupProhibitedModel() || ent:GetClass() == "gms_buildsite" ) then return false end
+
+ return true
+end
+
+/* ----------------------------------------------------------------------------------------------------
+ Config
+---------------------------------------------------------------------------------------------------- */
+
+GMS_SpawnLists = GMS_SpawnLists or {}
+
+GMS_SpawnLists[ "Wood - Tables / Desks" ] = {
+ "models/props_c17/FurnitureDrawer003a.mdl",
+ "models/props_c17/FurnitureDrawer002a.mdl",
+ "models/props_c17/FurnitureTable003a.mdl",
+ "models/props_c17/FurnitureDrawer001a.mdl",
+ "models/props_c17/FurnitureTable001a.mdl",
+ "models/props_c17/FurnitureTable002a.mdl",
+ "models/props_interiors/Furniture_Desk01a.mdl",
+ "models/props_interiors/Furniture_Vanity01a.mdl",
+ "models/props_wasteland/cafeteria_table001a.mdl"
+}
+
+GMS_SpawnLists[ "Wood - Shelving / Storage" ] = {
+ "models/props_c17/FurnitureShelf001b.mdl",
+ "models/props_wasteland/prison_shelf002a.mdl",
+ "models/props_junk/wood_crate001a.mdl",
+ "models/props_junk/wood_crate001a_damaged.mdl",
+ "models/props_junk/wood_crate002a.mdl",
+ "models/props_wasteland/laundry_cart002.mdl",
+ "models/props_c17/FurnitureShelf001a.mdl",
+ "models/props_interiors/Furniture_shelf01a.mdl",
+ "models/props_c17/shelfunit01a.mdl",
+ "models/props_c17/FurnitureDresser001a.mdl"
+}
+
+GMS_SpawnLists[ "Wood - Seating" ] = {
+ "models/props_c17/FurnitureChair001a.mdl",
+ "models/props_interiors/Furniture_chair01a.mdl",
+ "models/props_c17/playground_swingset_seat01a.mdl",
+ "models/props_c17/playground_teetertoter_seat.mdl",
+ "models/props_wasteland/cafeteria_bench001a.mdl",
+ "models/props_trainstation/BenchOutdoor01a.mdl",
+ "models/props_c17/bench01a.mdl",
+ "models/props_trainstation/bench_indoor001a.mdl"
+}
+
+GMS_SpawnLists[ "Wood - Doors / Plating / Beams" ] = {
+ "models/props_debris/wood_board02a.mdl",
+ "models/props_debris/wood_board04a.mdl",
+ "models/props_debris/wood_board06a.mdl",
+ "models/props_debris/wood_board01a.mdl",
+ "models/props_debris/wood_board03a.mdl",
+ "models/props_debris/wood_board05a.mdl",
+ "models/props_debris/wood_board07a.mdl",
+ "models/props_junk/wood_pallet001a.mdl",
+ "models/props_wasteland/wood_fence02a.mdl",
+ "models/props_wasteland/wood_fence01a.mdl",
+ "models/props_c17/Frame002a.mdl",
+ "models/props_wasteland/barricade001a.mdl",
+ "models/props_wasteland/barricade002a.mdl",
+ "models/props_docks/channelmarker_gib01.mdl",
+ "models/props_docks/channelmarker_gib04.mdl",
+ "models/props_docks/channelmarker_gib03.mdl",
+ "models/props_docks/channelmarker_gib02.mdl",
+ "models/props_docks/dock01_pole01a_128.mdl",
+ "models/props_docks/dock02_pole02a_256.mdl",
+ "models/props_docks/dock01_pole01a_256.mdl",
+ "models/props_docks/dock02_pole02a.mdl",
+ "models/props_docks/dock03_pole01a_256.mdl",
+ "models/props_docks/dock03_pole01a.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Kitchen/Appliances" ] = {
+ "models/props_interiors/SinkKitchen01a.mdl",
+ "models/props_interiors/Radiator01a.mdl",
+ "models/props_c17/FurnitureWashingmachine001a.mdl",
+ "models/props_c17/FurnitureFridge001a.mdl",
+ "models/props_interiors/refrigerator01a.mdl",
+ "models/props_c17/FurnitureBoiler001a.mdl",
+ "models/props_c17/FurnitureFireplace001a.mdl",
+ "models/props_wasteland/kitchen_counter001d.mdl",
+ "models/props_wasteland/kitchen_counter001b.mdl",
+ "models/props_wasteland/kitchen_counter001a.mdl",
+ "models/props_wasteland/kitchen_counter001c.mdl",
+ "models/props_wasteland/kitchen_stove001a.mdl",
+ "models/props_wasteland/kitchen_stove002a.mdl",
+ "models/props_wasteland/kitchen_fridge001a.mdl",
+ "models/props_wasteland/laundry_dryer001.mdl",
+ "models/props_wasteland/laundry_dryer002.mdl",
+ "models/props_wasteland/laundry_washer003.mdl",
+ "models/props_wasteland/laundry_washer001a.mdl",
+ "models/props_wasteland/laundry_basket001.mdl",
+ "models/props_wasteland/laundry_basket002.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Shelving/Storage" ] = {
+ "models/props_c17/FurnitureShelf002a.mdl",
+ "models/props_lab/filecabinet02.mdl",
+ "models/props_wasteland/controlroom_filecabinet002a.mdl",
+ "models/props_wasteland/controlroom_storagecloset001a.mdl",
+ "models/props_wasteland/kitchen_shelf002a.mdl",
+ "models/props_wasteland/kitchen_shelf001a.mdl",
+ "models/props_c17/display_cooler01a.mdl"
+}
+
+/*GMS_SpawnLists[ "Iron - Cargo/Tanks" ] = {
+ "models/props_wasteland/cargo_container01.mdl",
+ "models/props_wasteland/cargo_container01b.mdl",
+ "models/props_wasteland/cargo_container01c.mdl",
+ "models/props_wasteland/horizontalcoolingtank04.mdl",
+ "models/props_wasteland/coolingtank02.mdl",
+ "models/props_wasteland/coolingtank01.mdl",
+ "models/props_junk/TrashDumpster01a.mdl",
+ "models/props_junk/TrashDumpster02.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Lighting" ] = {
+ "models/props_c17/light_cagelight02_on.mdl",
+ "models/props_c17/light_cagelight01_on.mdl",
+ "models/props_wasteland/prison_lamp001c.mdl",
+ "models/props_wasteland/prison_lamp001a.mdl",
+ "models/props_wasteland/prison_lamp001b.mdl",
+ "models/props_c17/lamp_standard_off01.mdl",
+ "models/props_c17/lamp_bell_on.mdl",
+ "models/props_c17/light_decklight01_on.mdl",
+ "models/props_c17/light_floodlight02_off.mdl",
+ "models/props_wasteland/light_spotlight02_base.mdl",
+ "models/props_wasteland/light_spotlight02_lamp.mdl",
+ "models/props_wasteland/light_spotlight01_base.mdl",
+ "models/props_wasteland/light_spotlight01_lamp.mdl",
+ "models/props_trainstation/Column_Light001b.mdl",
+ "models/props_trainstation/Column_Light001a.mdl",
+ "models/props_trainstation/light_128wallMounted001a.mdl",
+ "models/props_c17/LampFixture01a.mdl",
+ "models/props_c17/lamppost03a_on.mdl",
+ "models/props_c17/Traffic_Light001a.mdl",
+ "models/props_trainstation/TrackLight01.mdl",
+ "models/props_trainstation/light_Signal002a.mdl",
+ "models/props_trainstation/light_Signal001a.mdl",
+ "models/props_trainstation/light_Signal001b.mdl"
+}*/
+
+GMS_SpawnLists[ "Iron - Containers" ] = {
+ "models/props_junk/garbage_metalcan001a.mdl",
+ "models/props_junk/garbage_metalcan002a.mdl",
+ "models/props_junk/PopCan01a.mdl",
+ "models/props_interiors/pot01a.mdl",
+ "models/props_c17/metalPot002a.mdl",
+ "models/props_interiors/pot02a.mdl",
+ "models/props_c17/metalPot001a.mdl",
+ "models/props_junk/metal_paintcan001a.mdl",
+ "models/props_junk/metalgascan.mdl",
+ "models/props_junk/MetalBucket01a.mdl",
+ "models/props_junk/MetalBucket02a.mdl",
+ "models/props_trainstation/trashcan_indoor001b.mdl",
+ "models/props_trainstation/trashcan_indoor001a.mdl",
+ "models/props_c17/oildrum001.mdl",
+ "models/props_c17/canister01a.mdl",
+ "models/props_c17/canister02a.mdl",
+ "models/props_c17/canister_propane01a.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Signs" ] = {
+ "models/props_c17/streetsign005d.mdl",
+ "models/props_c17/streetsign005c.mdl",
+ "models/props_c17/streetsign005b.mdl",
+ "models/props_c17/streetsign004f.mdl",
+ "models/props_c17/streetsign004e.mdl",
+ "models/props_c17/streetsign003b.mdl",
+ "models/props_c17/streetsign002b.mdl",
+ "models/props_c17/streetsign001c.mdl",
+ "models/props_trainstation/TrackSign01.mdl",
+ "models/props_trainstation/clock01.mdl",
+ "models/props_trainstation/trainstation_clock001.mdl"
+}
+
+GMS_SpawnLists[ "Copper - Signs" ] = {
+ "models/props_trainstation/TrackSign02.mdl",
+ "models/props_trainstation/TrackSign03.mdl",
+ "models/props_trainstation/TrackSign10.mdl",
+ "models/props_trainstation/TrackSign09.mdl",
+ "models/props_trainstation/TrackSign08.mdl",
+ "models/props_trainstation/TrackSign07.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Rails" ] = {
+ "models/props_trainstation/handrail_64decoration001a.mdl",
+ "models/props_c17/Handrail04_short.mdl",
+ "models/props_c17/Handrail04_Medium.mdl",
+ "models/props_c17/Handrail04_corner.mdl",
+ "models/props_c17/Handrail04_long.mdl",
+ "models/props_c17/Handrail04_SingleRise.mdl",
+ "models/props_c17/Handrail04_DoubleRise.mdl"
+}
+
+GMS_SpawnLists[ "Copper - Fencing" ] = {
+ "models/props_wasteland/interior_fence002a.mdl",
+ "models/props_wasteland/interior_fence002e.mdl",
+ "models/props_wasteland/interior_fence001g.mdl",
+ "models/props_wasteland/interior_fence002f.mdl",
+ "models/props_wasteland/interior_fence002c.mdl",
+ "models/props_wasteland/interior_fence002d.mdl",
+ "models/props_wasteland/interior_fence004b.mdl",
+ "models/props_wasteland/interior_fence004a.mdl",
+ "models/props_wasteland/exterior_fence002a.mdl",
+ "models/props_wasteland/exterior_fence003a.mdl",
+ "models/props_wasteland/exterior_fence003b.mdl",
+ "models/props_wasteland/exterior_fence002c.mdl",
+ "models/props_wasteland/exterior_fence002d.mdl",
+ "models/props_wasteland/exterior_fence001a.mdl",
+ "models/props_wasteland/exterior_fence002e.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Doors/Plating/Beams" ] = {
+ "models/props_c17/door02_double.mdl",
+ "models/props_c17/door01_left.mdl",
+ "models/props_borealis/borealis_door001a.mdl",
+ "models/props_interiors/refrigeratorDoor02a.mdl",
+ "models/props_interiors/refrigeratorDoor01a.mdl",
+ "models/props_building_details/Storefront_Template001a_Bars.mdl",
+ "models/props_c17/gate_door01a.mdl",
+ "models/props_c17/gate_door02a.mdl",
+ "models/props_junk/ravenholmsign.mdl",
+ "models/props_debris/metal_panel02a.mdl",
+ "models/props_debris/metal_panel01a.mdl",
+ "models/props_junk/TrashDumpster02b.mdl",
+ "models/props_lab/blastdoor001a.mdl",
+ "models/props_lab/blastdoor001b.mdl",
+ "models/props_lab/blastdoor001c.mdl",
+ "models/props_trainstation/trainstation_post001.mdl",
+ "models/props_c17/signpole001.mdl",
+ "models/props_junk/harpoon002a.mdl",
+ "models/props_c17/metalladder002b.mdl",
+ "models/props_c17/metalladder002.mdl",
+ "models/props_c17/metalladder003.mdl",
+ "models/props_c17/metalladder001.mdl",
+ "models/props_junk/iBeam01a.mdl",
+ "models/props_junk/iBeam01a_cluster01.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Vehicles" ] = {
+ "models/props_junk/Wheebarrow01a.mdl",
+ "models/props_junk/PushCart01a.mdl",
+ "models/props_wasteland/gaspump001a.mdl",
+ "models/props_wasteland/wheel01.mdl",
+ "models/props_wasteland/wheel01a.mdl",
+ "models/props_wasteland/wheel03b.mdl",
+ "models/props_wasteland/wheel02b.mdl",
+ "models/props_wasteland/wheel02a.mdl",
+ "models/props_wasteland/wheel03a.mdl",
+ "models/props_citizen_tech/windmill_blade002a.mdl",
+ "models/airboat.mdl",
+ "models/buggy.mdl",
+ "models/props_vehicles/car002a_physics.mdl",
+ "models/props_vehicles/car001b_hatchback.mdl",
+ "models/props_vehicles/car001a_hatchback.mdl",
+ "models/props_vehicles/car003a_physics.mdl",
+ "models/props_vehicles/car003b_physics.mdl",
+ "models/props_vehicles/car004a_physics.mdl",
+ "models/props_vehicles/car004b_physics.mdl",
+ "models/props_vehicles/car005a_physics.mdl",
+ "models/props_vehicles/car005b_physics.mdl",
+ "models/props_vehicles/van001a_physics.mdl",
+ "models/props_vehicles/truck003a.mdl",
+ "models/props_vehicles/truck002a_cab.mdl",
+ "models/props_vehicles/trailer002a.mdl",
+ "models/props_vehicles/truck001a.mdl",
+ "models/props_vehicles/generatortrailer01.mdl",
+ "models/props_vehicles/apc001.mdl",
+ "models/combine_apc_wheelcollision.mdl",
+ "models/props_vehicles/trailer001a.mdl",
+ "models/props_trainstation/train003.mdl",
+ "models/props_trainstation/train002.mdl",
+ "models/props_combine/combine_train02a.mdl",
+ "models/props_combine/CombineTrain01a.mdl",
+ "models/props_combine/combine_train02b.mdl",
+ "models/props_trainstation/train005.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Seating" ] = {
+ "models/props_c17/chair_stool01a.mdl",
+ "models/props_c17/chair02a.mdl",
+ "models/props_c17/chair_office01a.mdl",
+ "models/props_wasteland/controlroom_chair001a.mdl",
+ "models/props_c17/chair_kleiner03a.mdl",
+ "models/props_trainstation/traincar_seats001.mdl",
+ "models/props_c17/FurnitureBed001a.mdl",
+ "models/props_wasteland/prison_bedframe001b.mdl",
+ "models/props_c17/FurnitureBathtub001a.mdl",
+ "models/props_interiors/BathTub01a.mdl"
+}
+
+GMS_SpawnLists[ "Iron - Misc/Buttons" ] = {
+ "models/props_c17/TrapPropeller_Lever.mdl",
+ "models/props_c17/TrapPropeller_Engine.mdl",
+ "models/props_c17/TrapPropeller_Blade.mdl",
+ "models/props_junk/sawblade001a.mdl",
+ "models/props_trainstation/payphone001a.mdl",
+ "models/props_wasteland/prison_throwswitchlever001.mdl",
+ "models/props_wasteland/prison_throwswitchbase001.mdl",
+ "models/props_wasteland/tram_lever01.mdl",
+ "models/props_wasteland/tram_leverbase01.mdl",
+ "models/props_wasteland/panel_leverHandle001a.mdl",
+ "models/props_wasteland/panel_leverBase001a.mdl",
+ "models/props_lab/tpplug.mdl",
+ "models/props_lab/tpplugholder_single.mdl",
+ "models/props_lab/tpplugholder.mdl",
+ "models/props_c17/cashregister01a.mdl"
+}
+
+GMS_SpawnLists[ "Wood - PHX" ] = {
+ "models/props_phx/construct/wood/wood_boardx1.mdl",
+ "models/props_phx/construct/wood/wood_boardx2.mdl",
+ "models/props_phx/construct/wood/wood_boardx4.mdl",
+ "models/props_phx/construct/wood/wood_panel1x1.mdl",
+ "models/props_phx/construct/wood/wood_panel1x2.mdl",
+ "models/props_phx/construct/wood/wood_panel2x2.mdl",
+ "models/props_phx/construct/wood/wood_panel2x4.mdl",
+ "models/props_phx/construct/wood/wood_panel4x4.mdl",
+ "models/props_phx/construct/wood/wood_wire1x1.mdl",
+ "models/props_phx/construct/wood/wood_wire1x1x1.mdl",
+ "models/props_phx/construct/wood/wood_wire1x1x2.mdl",
+ "models/props_phx/construct/wood/wood_wire1x1x2b.mdl",
+ "models/props_phx/construct/wood/wood_wire1x2.mdl",
+ "models/props_phx/construct/wood/wood_wire1x2b.mdl",
+ "models/props_phx/construct/wood/wood_wire1x2x2b.mdl",
+ "models/props_phx/construct/wood/wood_wire2x2.mdl",
+ "models/props_phx/construct/wood/wood_wire2x2b.mdl",
+ "models/props_phx/construct/wood/wood_wire2x2x2b.mdl"
+}
+
+GMS_SpawnLists[ "Iron - PHX" ] = {
+ "models/props_phx/construct/metal_plate1.mdl",
+ "models/props_phx/construct/metal_plate1x2.mdl",
+ "models/props_phx/construct/metal_plate2x2.mdl",
+ "models/props_phx/construct/metal_plate2x4.mdl",
+ "models/props_phx/construct/metal_plate4x4.mdl",
+ "models/props_phx/construct/metal_wire1x1.mdl",
+ "models/props_phx/construct/metal_wire1x1x1.mdl",
+ "models/props_phx/construct/metal_wire1x1x2.mdl",
+ "models/props_phx/construct/metal_wire1x1x2b.mdl",
+ "models/props_phx/construct/metal_wire1x2.mdl",
+ "models/props_phx/construct/metal_wire1x2b.mdl",
+ "models/props_phx/construct/metal_wire1x2x2b.mdl",
+ "models/props_phx/construct/metal_wire2x2.mdl",
+ "models/props_phx/construct/metal_wire2x2b.mdl",
+ "models/props_phx/construct/metal_wire2x2x2b.mdl"
+}
+
+GMS.SleepingFurniture = {
+ "models/props_interiors/Furniture_Couch01a.mdl",
+ "models/props_c17/FurnitureCouch002a.mdl",
+ "models/props_c17/FurnitureCouch001a.mdl",
+ "models/props_c17/FurnitureBed001a.mdl",
+ "models/props_wasteland/prison_bedframe001b.mdl",
+ "models/props_trainstation/traincar_seats001.mdl"
+}
+GMS_SpawnLists[ "Mixed - Sleeping Furniture" ] = GMS.SleepingFurniture
+
+GMS.TreeModels = {
+ "models/props_foliage/oak_tree01.mdl",
+ "models/props_foliage/tree_deciduous_01a-lod.mdl",
+ "models/props_foliage/tree_deciduous_01a.mdl",
+ "models/props_foliage/tree_deciduous_02a.mdl",
+ "models/props_foliage/tree_deciduous_03a.mdl",
+ "models/props_foliage/tree_deciduous_03b.mdl",
+ "models/props_foliage/tree_poplar_01.mdl",
+
+ "models/gm_forest/tree_oak1.mdl", -- These are in the content of the gamemode
+ "models/gm_forest/tree_orientalspruce1.mdl"
+}
+
+// These models cannot be dynamically spawned. Because if someone doesn't have them.
+GMS.AdditionalTreeModels = {
+ "models/props_foliage/tree_cliff_01a.mdl", -- Half-Life 2, We don't want these to be plantable, they are weird
+ "models/props_foliage/tree_cliff_02a.mdl",
+
+ "models/props_foliage/tree_pine04.mdl", -- Episode 2
+ "models/props_foliage/tree_pine05.mdl",
+ "models/props_foliage/tree_pine06.mdl",
+ "models/props_foliage/tree_dead01.mdl",
+ "models/props_foliage/tree_dead02.mdl",
+ "models/props_foliage/tree_dead03.mdl",
+ "models/props_foliage/tree_dead04.mdl",
+ "models/props_foliage/tree_dry01.mdl",
+ "models/props_foliage/tree_dry02.mdl",
+ "models/props_foliage/tree_pine_large.mdl",
+
+ "models/props_foliage/tree_pine_01.mdl", -- Episode 1
+ "models/props_foliage/tree_pine_02.mdl",
+ "models/props_foliage/tree_pine_03.mdl",
+
+ "models/props/de_inferno/tree_small.mdl", -- CSS
+ "models/props/de_inferno/tree_large.mdl",
+ "models/props/cs_militia/tree_large_militia.mdl",
+
+ "models/jtwoods/woods_spruce.mdl", -- Models from gms_paradise_islands_v1 / gm_forest
+ "models/gm_forest/trunk_a.mdl",
+ "models/gm_forest/tree_commonlinden_1.mdl",
+ "models/gm_forest/tree_alder.mdl",
+ "models/gm_forest/tree_birch1.mdl",
+ "models/gm_forest/tree_b.mdl",
+ "models/gm_forest/tree_g.mdl"
+}
+
+GMS.EdibleModels = {
+ "models/props/cs_italy/orange.mdl",
+ "models/props_junk/watermelon01.mdl",
+ "models/props/cs_italy/bananna_bunch.mdl"
+}
+
+GMS.RockModels = {
+ "models/props_wasteland/rockgranite02a.mdl",
+ "models/props_wasteland/rockgranite02b.mdl",
+ "models/props_wasteland/rockgranite02c.mdl",
+ "models/props_wasteland/rockgranite04b.mdl",
+ "models/props_wasteland/rockcliff_cluster01b.mdl",
+ "models/props_wasteland/rockcliff_cluster02a.mdl",
+ "models/props_wasteland/rockcliff_cluster02b.mdl",
+ "models/props_wasteland/rockcliff_cluster02c.mdl",
+ "models/props_wasteland/rockcliff_cluster03a.mdl",
+ "models/props_wasteland/rockcliff_cluster03b.mdl",
+ "models/props_wasteland/rockcliff_cluster03c.mdl",
+ "models/props_wasteland/rockcliff01b.mdl",
+ "models/props_wasteland/rockcliff01c.mdl",
+ "models/props_wasteland/rockcliff01e.mdl",
+ "models/props_wasteland/rockcliff01f.mdl",
+ "models/props_wasteland/rockcliff01g.mdl",
+ "models/props_wasteland/rockcliff01J.mdl",
+ "models/props_wasteland/rockcliff01k.mdl",
+ "models/props_wasteland/rockcliff05a.mdl",
+ "models/props_wasteland/rockcliff05b.mdl",
+ "models/props_wasteland/rockcliff05e.mdl",
+ "models/props_wasteland/rockcliff05f.mdl",
+ "models/props_wasteland/rockcliff06d.mdl",
+ "models/props_wasteland/rockcliff06i.mdl",
+ "models/props_wasteland/rockcliff07b.mdl"
+}
+
+GMS.AdditionalRockModels = {
+ "models/props_wasteland/rockgranite01a.mdl", -- Half-Life 2
+ "models/props_wasteland/rockgranite01b.mdl",
+ "models/props_wasteland/rockgranite01c.mdl",
+ "models/props_wasteland/rockgranite03a.mdl",
+ "models/props_wasteland/rockgranite03b.mdl",
+ "models/props_wasteland/rockgranite03c.mdl",
+ "models/props_wasteland/rockgranite04a.mdl",
+ "models/props_wasteland/rockgranite04c.mdl",
+ "models/props_canal/rock_riverbed01a.mdl",
+ "models/props_canal/rock_riverbed01b.mdl",
+ "models/props_canal/rock_riverbed01c.mdl",
+ "models/props_canal/rock_riverbed01d.mdl",
+ "models/props_canal/rock_riverbed02a.mdl",
+ "models/props_canal/rock_riverbed02b.mdl",
+ "models/props_canal/rock_riverbed02c.mdl",
+ "models/props_lab/bigrock.mdl",
+
+ "models/props_mining/caverocks_cluster01.mdl", -- Episode 2
+ "models/props_mining/caverocks_cluster02.mdl",
+ "models/Cliffs/rockcluster01.mdl",
+ "models/Cliffs/rockcluster02.mdl",
+ "models/Cliffs/rocks_large01.mdl",
+ "models/Cliffs/rocks_large01_veg.mdl",
+ "models/Cliffs/rocks_large02.mdl",
+ "models/Cliffs/rocks_large02_veg.mdl",
+ "models/cliffs/rocks_large03.mdl",
+ "models/cliffs/rocks_large03_veg.mdl",
+ "models/Cliffs/rocks_medium01.mdl",
+ "models/Cliffs/rocks_medium01_veg.mdl",
+ "models/Cliffs/rocks_xlarge01.mdl",
+ "models/Cliffs/rocks_xlarge01_veg.mdl",
+ "models/Cliffs/rocks_xlarge02.mdl",
+ "models/Cliffs/rocks_xlarge02_veg.mdl",
+ "models/Cliffs/rocks_xlarge03.mdl",
+ "models/Cliffs/rocks_xlarge03_veg.mdl",
+
+ "models/props/de_inferno/de_inferno_boulder_03.mdl", -- CSS
+ "models/props_canal/rock_riverbed02b.mdl",
+ "models/props/cs_militia/boulder01.mdl",
+ "models/props/cs_militia/militiarock01.mdl",
+ "models/props/cs_militia/militiarock02.mdl",
+ "models/props/cs_militia/militiarock03.mdl",
+ "models/props/cs_militia/militiarock05.mdl",
+ "models/props_wasteland/rockcliff07e.mdl",
+ "models/props_wasteland/rockcliff_cluster01a.mdl"
+}
+
+GMS.SmallRockModel = "models/props_junk/rock001a.mdl"
+
+GMS.MaterialResources = {}
+GMS.MaterialResources[ MAT_CONCRETE ] = "Concrete"
+GMS.MaterialResources[ MAT_METAL ] = "Iron"
+GMS.MaterialResources[ MAT_DIRT ] = "Wood"
+GMS.MaterialResources[ MAT_VENT ] = "Copper"
+GMS.MaterialResources[ MAT_GRATE ] = "Copper"
+GMS.MaterialResources[ MAT_TILE ] = "Stone"
+GMS.MaterialResources[ MAT_SLOSH ] = "Wood"
+GMS.MaterialResources[ MAT_WOOD ] = "Wood"
+GMS.MaterialResources[ MAT_COMPUTER ] = "Copper"
+GMS.MaterialResources[ MAT_GLASS ] = "Glass"
+GMS.MaterialResources[ MAT_FLESH ] = "Wood"
+GMS.MaterialResources[ MAT_BLOODYFLESH ] = "Wood"
+GMS.MaterialResources[ MAT_CLIP ] = "Wood"
+GMS.MaterialResources[ MAT_ANTLION ] = "Wood"
+GMS.MaterialResources[ MAT_ALIENFLESH ] = "Wood"
+GMS.MaterialResources[ MAT_FOLIAGE ] = "Wood"
+GMS.MaterialResources[ MAT_SAND ] = "Sand"
+GMS.MaterialResources[ MAT_PLASTIC ] = "Plastic"
+
+GMS.PickupProhibitedClasses = {
+ "gms_seed"
+}
+
+GMS.SavedClasses = {
+ "prop_physics",
+ "prop_physics_override",
+ "prop_physics_multiplayer",
+ "prop_dynamic",
+ "gms_stoneworkbench",
+ "gms_copperworkbench",
+ "gms_ironworkbench",
+ "gms_techworkbench",
+ "gms_silverworkbench",
+ "gms_goldworkbench",
+ "gms_steelworkbench",
+ "gms_platinumworkbench",
+ "gms_stove",
+ "gms_buildsite",
+ "gms_fridge",
+ "gms_resourcedrop",
+ "gms_resourcepack",
+ "gms_stonefurnace",
+ "gms_copperfurnace",
+ "gms_ironfurnace",
+ "gms_techfurnace",
+ "gms_silverfurnace",
+ "gms_goldfurnace",
+ "gms_steelfurnace",
+ "gms_platinumfurnace",
+ "gms_antlionbarrow",
+ "gms_loot",
+ "gms_factory",
+ "gms_gunchunks",
+ "gms_pistolgunlab",
+ "gms_smggunlab",
+ "gms_hightechgunlab",
+ "gms_transmutator",
+ "gms_advancedtransmutator",
+ "gms_seed",
+ "gms_grindingstone",
+ "gms_waterfountain",
+ "gms_clock_big",
+ "gms_renbuyshop",
+ "gms_rensellshop",
+ "gms_obelisk",
+ "gms_mithrilfactory",
+ "gms_mithrilworkbench",
+ "gms_runealtar",
+ "gms_runicinfuser"
+}
+
+GMS.StructureEntities = {
+ "gms_stoneworkbench",
+ "gms_stonefurnace",
+ "gms_copperworkbench",
+ "gms_copperfurnace",
+ "gms_ironworkbench",
+ "gms_ironfurnace",
+ "gms_techworkbench",
+ "gms_techfurnace",
+ "gms_silverworkbench",
+ "gms_silverfurnace",
+ "gms_goldworkbench",
+ "gms_goldfurnace",
+ "gms_steelworkbench",
+ "gms_steelfurnace",
+ "gms_platinumworkbench",
+ "gms_platinumfurnace",
+ "gms_pistolgunlab",
+ "gms_smggunlab",
+ "gms_hightechgunlab",
+ "gms_transmutator",
+ "gms_advancedtransmutator",
+ "gms_gunchunks",
+ "gms_stove",
+ "gms_fridge",
+ "gms_factory",
+ "gms_grindingstone",
+ "gms_waterfountain",
+ "gms_resourcepack",
+ "gms_buildsite",
+ "gms_renbuyshop",
+ "gms_rensellshop",
+ "gms_obelisk",
+ "gms_mithrilfactory",
+ "gms_mithrilworkbench",
+ "gms_runealtar",
+ "gms_runicinfuser"
+}
+
+GMS.ProhibitedStools = {
+ "hydraulic",
+ "motor",
+ "muscle",
+ "nail",
+ "pulley",
+ "slider",
+ "balloon",
+ "rope", // We use gms_rope
+ "button",
+ "duplicator",
+ "dynamite",
+ "emitter",
+ "hoverball",
+ "ignite",
+ "keepupright",
+ "magnetise",
+ //"nocollide",
+ "physprop",
+ "spawner",
+ "thruster",
+ "turret",
+ "wheel",
+ "eyeposer",
+ "faceposer",
+ "finger",
+ "inflator",
+ "statue",
+ "trails",
+ "camera",
+ "paint",
+ "rtcamera",
+ "rb655_lightsaber"
+}
+
+GMS.AllWeapons = {
+ "gms_stonepickaxe",
+ "gms_stonehatchet",
+ "gms_copperpickaxe",
+ "gms_wrench",
+ "gms_copperhatchet",
+ "gms_pickaxeofdjarex",
+ "gms_mithrilpickaxe",
+ "gms_chisel",
+ "gms_runeapickaxe",
+ "gms_runeepickaxe",
+ "gms_runefpickaxe",
+ "gms_runewpickaxe",
+ "gms_ironpickaxe",
+ "gms_ironhatchet",
+ "gms_techpickaxe",
+ "gms_techhatchet",
+ "gms_silverpickaxe",
+ "gms_silverhatchet",
+ "gms_goldpickaxe",
+ "gms_goldhatchet",
+ "gms_steelpickaxe",
+ "gms_steelhatchet",
+ "gms_platinumpickaxe",
+ "gms_platinumhatchet",
+ "gms_woodenfishingrod",
+ "gms_advancedfishingrod",
+ "gms_fryingpan",
+ "gms_shovel",
+ "gms_strainer",
+ "gms_sickle",
+ "gms_woodenspoon",
+ "gmod_tool",
+ "weapon_crowbar",
+ "weapon_stunstick",
+ "weapon_pistol",
+ "weapon_smg1",
+ "gms_bucket",
+ "gms_inventory"
+}
+
+GMS.NonDropWeapons = {
+ "gms_fists",
+ "gmod_tool",
+ "gmod_camera",
+ "weapon_physgun",
+ "weapon_physcannon",
+ "pill_pigeon",
+ "gms_bucket",
+ "gms_inventory",
+}
+
+/* ----------------------------------------------
+ Console Variables
+------------------------------------------------ */
+
+if ( GMSCVars ) then return end -- Auto-Refresh protection
+
+GMSCVars = {}
+
+function CreateGMSCVar( name, def, flag )
+ if ( SERVER ) then
+
+ table.insert( GMSCVars, "gms_" .. name )
+ CreateConVar( "gms_" .. name, def, flag )
+
+ cvars.AddChangeCallback( "gms_" .. name, function( cvar, old, new )
+
+ if ( math.floor( old ) == math.floor( new ) ) then return end
+ for id, pl in pairs( player.GetAll() ) do pl:ConCommand( "gms_" .. name .. " " .. math.floor( new ) ) end
+
+ end )
+
+ else
+
+ CreateConVar( "gms_" .. name, def )
+ cvars.AddChangeCallback( "gms_" .. name, function( cvar, old, new )
+
+ if ( math.floor( old ) == math.floor( new ) ) then return end
+ timer.Destroy( "gms_update" .. name )
+ timer.Create( "gms_update" .. name, 2, 1, function() RunConsoleCommand( "gms_update", name, math.floor( new ) ) end )
+
+ end )
+
+ end
+end
+
+CreateGMSCVar( "FreeBuild", "0" )
+CreateGMSCVar( "FreeBuildSA", "0" )
+CreateGMSCVar( "AllTools", "0", FCVAR_ARCHIVE )
+CreateGMSCVar( "AutoSave", "1", FCVAR_ARCHIVE )
+CreateGMSCVar( "AutoSaveTime", "3", FCVAR_ARCHIVE )
+CreateGMSCVar( "ReproduceTrees", "3" )
+CreateGMSCVar( "MaxReproducedTrees", "50", FCVAR_ARCHIVE )
+CreateGMSCVar( "SpreadFire", "0" )
+CreateGMSCVar( "FadeRocks", "0" )
+//CreateGMSCVar( "CostsScale", "1" )
+//CreateGMSCVar( "alerts", "1" )
+CreateGMSCVar( "campfire", "1" )
+CreateGMSCVar( "PlantLimit", "25", FCVAR_ARCHIVE )
+
+CreateGMSCVar( "PVPDamage", "0", FCVAR_ARCHIVE )
+CreateGMSCVar( "TeamColors", "1", FCVAR_ARCHIVE )
+
+-- Daynight
+CreateGMSCVar( "daynight", "1" )
+CreateGMSCVar( "night_cleanup", "1" )
+CreateGMSCVar( "zombies", "1" )
+
+if ( CLIENT ) then return end
+
+concommand.Add( "gms_update", function( ply, cmd, args )
+
+ if ( !ply:IsAdmin() ) then return end
+
+ local cmd = args[ 1 ]
+ local val = args[ 2 ]
+
+ if ( math.floor( GetConVarNumber( "gms_" .. cmd ) ) == math.floor( val ) ) then return end
+
+ RunConsoleCommand( "gms_" .. cmd, math.floor( val ) )
+
+end )
+
+hook.Add( "PlayerInitialSpawn", "gms.sync_cvars", function( ply )
+ for id, cvar in pairs( GMSCVars ) do ply:ConCommand( cvar .. " " .. math.floor( GetConVarNumber( cvar ) ) ) end
+end )
diff --git a/ftp_gmstranded/gamemode/spp/cl_init.lua b/ftp_gmstranded/gamemode/spp/cl_init.lua
new file mode 100644
index 0000000..ca14f49
--- /dev/null
+++ b/ftp_gmstranded/gamemode/spp/cl_init.lua
@@ -0,0 +1,101 @@
+
+function SPropProtection.PlayerIsPropOwner( ply, ent )
+ if ( !IsValid( ent ) or ent:IsPlayer() ) then return false end
+
+ if ( ent:GetNWString( "Owner" ) == ply:Nick() && ent:GetNWInt( "OwnerID" ) == ply:EntIndex() ) then
+ return true
+ end
+
+ local HisTribe = GAMEMODE.FindTribeByID( ent:GetNWString( "TribeID" ) )
+
+ if ( !HisTribe ) then return false end
+
+ if ( ent:GetNWString( "TribeID" ) == ply:Team() && HisTribe.pass == true ) then return true end
+ if ( ent:GetNWString( "TribeID" ) == ply:Team() && HisTribe.pass == true ) then return true end
+
+ return false
+end
+
+function SPropProtection.PlayerCanTouch( ply, ent )
+ if ( GetConVarNumber( "spp_enabled" ) == 0 or ent:GetClass() == "worldspawn" ) then return true end
+ if ( ent:IsPlayer() or ent:IsNPC() ) then return false end
+
+ /* Stranded Plants & Respacks*/
+ local isResource = ent:GetClass() == "gms_resourcepack" or ent:GetClass() == "gms_resourcedrop" or ent:GetClass() == "gms_fridge"
+ local isPlant = ent:IsBerryBushModel() or ent:IsGrainModel() or ent:IsFoodModel()
+ if ( ( ent:GetNWString( "Owner" ) == "World" or GetConVarNumber( "spp_use" ) <= 0 ) && ( isResource or isPlant ) ) then
+ return true
+ end
+
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_admin" ) == 1 && ent:GetNWString( "Owner" ) != "World" ) then return true end
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_admin_wp" ) == 1 && ent:GetNWString( "Owner" ) == "World" ) then return true end
+
+ if ( SPropProtection.PlayerIsPropOwner( ply, ent ) ) then return true end
+
+ -- Find the player
+ if ( !SPropProtection[ ply:SteamID() ] ) then return false end
+ for id, p in pairs( player.GetAll() ) do
+ if ( p:EntIndex() == ent:GetNWString( "OwnerID" ) ) then
+ if ( table.HasValue( SPropProtection[ ply:SteamID() ], p:SteamID() ) ) then return true end
+ end
+ end
+
+ return false
+end
+
+local UndoneStuff = {}
+hook.Add( "HUDPaint", "spp.hudpaint", function()
+ if ( !IsValid( LocalPlayer() ) ) then return end
+ if ( #UndoneStuff > 0 ) then for id, s in pairs( UndoneStuff ) do table.insert( SPropProtection[ LocalPlayer():SteamID() ], s ) end end
+ local tr = LocalPlayer():GetEyeTrace()
+
+ if ( !tr.HitNonWorld ) then return end
+ local ent = tr.Entity
+
+ if ( !IsValid( ent ) || ent:IsPlayer() || ent:IsNPC() || LocalPlayer():InVehicle() ) then return end
+
+ local OwnerName = ent:GetNWString( "Owner", "None" )
+ local OwnerObj = ent:GetNWEntity( "OwnerObj" )
+ if ( IsValid( OwnerObj ) ) then OwnerName = OwnerObj:Name() end
+
+ local TribeOwner = false
+ local PropOwner = "Owner: " .. OwnerName
+ local PropOwnerTribe = "Owner tribe: "
+
+ local HisTribe = GAMEMODE.FindTribeByID( ent:GetNWInt( "TribeID", 1 ) )
+ if ( HisTribe && HisTribe.pass == true ) then TribeOwner = true PropOwnerTribe = PropOwnerTribe .. HisTribe.name end
+
+ surface.SetFont( "DefaultBold" )
+ local tw = surface.GetTextSize( PropOwner )
+ local tw2 = surface.GetTextSize( PropOwnerTribe )
+
+ local w = math.max( ScrW() / 5, tw + 20, tw2 + 20 )
+ local h = ScrH() / 24
+ local x = ScrW() / 2 - w / 2
+ local y = ScrH() - ScrH() / 16
+
+ if ( TribeOwner ) then h = ScrH() / 18 end
+
+ surface.SetDrawColor( StrandedBackgroundColor )
+ surface.DrawRect( x, y, w, h )
+
+ surface.SetDrawColor( StrandedBorderColor )
+ surface.DrawOutlinedRect( x, y, w, h )
+
+ if ( TribeOwner ) then
+ draw.SimpleTextOutlined( PropOwner, "DefaultBold", x + w / 2, y + h / 4, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+ draw.SimpleTextOutlined( PropOwnerTribe, "DefaultBold", x + w / 2, y + h / 1.5, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+ else
+ draw.SimpleTextOutlined( PropOwner, "DefaultBold", x + w / 2, y + h / 2, StrandedTextColor, 1, 1, 0.5, StrandedTextShadowColor )
+ end
+end )
+
+usermessage.Hook( "spp_addbuddy", function( um )
+ if ( !IsValid( LocalPlayer() ) || !LocalPlayer().SteamID ) then table.insert( UndoneStuff, um:ReadString() ) return end
+ table.insert( SPropProtection[ LocalPlayer():SteamID() ], um:ReadString() )
+end )
+
+usermessage.Hook( "spp_clearbuddy", function( um )
+ if ( !IsValid( LocalPlayer() ) || !LocalPlayer().SteamID ) then UndoneStuff = {} return end
+ SPropProtection[ LocalPlayer():SteamID() ] = {}
+end )
diff --git a/ftp_gmstranded/gamemode/spp/sh_cppi.lua b/ftp_gmstranded/gamemode/spp/sh_cppi.lua
new file mode 100644
index 0000000..6bf923e
--- /dev/null
+++ b/ftp_gmstranded/gamemode/spp/sh_cppi.lua
@@ -0,0 +1,88 @@
+
+function CPPI:GetName()
+ return "Simple Prop Protection"
+end
+
+function CPPI:GetVersion()
+ return SPropProtection.Version
+end
+
+function CPPI:GetInterfaceVersion()
+ return 1.1
+end
+
+function CPPI:GetNameFromUID( uid )
+ return CPPI_NOTIMPLEMENTED
+end
+
+local Player = FindMetaTable( "Player" )
+if ( !Player ) then print( "EXTREME ERROR 1" ) return end
+
+function Player:CPPIGetFriends()
+ if ( SERVER ) then
+ local Table = {}
+ for k, v in pairs( player.GetAll() ) do
+ if ( table.HasValue( SPropProtection[ self:SteamID() ], v:SteamID() ) ) then table.insert( Table, v ) end
+ end
+ return Table
+ else
+ return CPPI_NOTIMPLEMENTED
+ end
+end
+
+local Entity = FindMetaTable( "Entity" )
+if ( !Entity ) then print( "EXTREME ERROR 2" ) return end
+
+function Entity:CPPIGetOwner()
+ local Player = self:GetNetworkedEntity( "OwnerObj", false )
+ if ( SERVER ) then Player = SPropProtection[ "Props" ][ self:EntIndex() ][ 3 ] end
+ if ( !IsValid( Player ) ) then return nil, CPPI_NOTIMPLEMENTED end
+ local UID = CPPI_NOTIMPLEMENTED
+ if ( SERVER ) then UID = Player:UniqueID() end
+ return Player, UID
+end
+
+if ( SERVER ) then
+ function Entity:CPPISetOwner( ply )
+ if ( !IsValid( ply ) or !ply:IsPlayer() ) then return false end
+ return SPropProtection.PlayerMakePropOwner( ply, self )
+ end
+
+ function Entity:CPPISetOwnerUID( uid )
+ if ( !uid ) then return false end
+ local ply = player.GetByUniqueID( tostring( uid ) )
+ if ( !ply ) then return false end
+ return SPropProtection.PlayerMakePropOwner( ply, self )
+ end
+
+ function Entity:CPPICanTool( ply, toolmode )
+ if ( !IsValid( ply ) or !ply:IsPlayer() or !toolmode ) then return false end
+ return SPropProtection.PlayerCanTouch( ply, self )
+ end
+
+ function Entity:CPPICanPhysgun( ply )
+ if ( !IsValid( ply ) or !ply:IsPlayer() ) then return false end
+ if ( SPropProtection.PhysGravGunPickup( ply, self ) == false ) then return false end
+ if ( self:GetClass() == "gms_gravestone" ) then return false end
+ return true
+ end
+
+ function Entity:CPPICanPickup( ply )
+ if ( !IsValid( ply ) or !ply:IsPlayer() ) then return false end
+ if ( SPropProtection.PhysGravGunPickup( ply, self ) == false ) then return false end
+ return true
+ end
+
+ function Entity:CPPICanPunt(ply)
+ if ( !IsValid( ply ) or !ply:IsPlayer() ) then return false end
+ if ( SPropProtection.PhysGravGunPickup( ply, self ) == false ) then return false end
+ return true
+ end
+end
+
+hook.Add( "Initialize", "CPPIInitGM", function()
+ function GAMEMODE:CPPIAssignOwnership( ply, ent )
+ end
+ function GAMEMODE:CPPIFriendsChanged( ply, ent )
+ end
+end )
diff --git a/ftp_gmstranded/gamemode/spp/sh_spp.lua b/ftp_gmstranded/gamemode/spp/sh_spp.lua
new file mode 100644
index 0000000..8421192
--- /dev/null
+++ b/ftp_gmstranded/gamemode/spp/sh_spp.lua
@@ -0,0 +1,97 @@
+
+AddCSLuaFile( "sh_cppi.lua" )
+AddCSLuaFile( "sh_spp.lua" )
+AddCSLuaFile( "cl_init.lua" )
+
+SPropProtection = SPropProtection or {}
+SPropProtection.Version = 2
+
+CPPI = CPPI or {}
+CPPI_NOTIMPLEMENTED = 26
+CPPI_DEFER = 16
+
+include( "sh_cppi.lua" )
+
+if ( SERVER ) then
+ include( "sv_init.lua" )
+else
+ include( "cl_init.lua" )
+end
+
+/* ----------------------------------------------
+ Keep these shared, so client can predict
+------------------------------------------------ */
+
+function SPropProtection.PhysGravGunPickup( ply, ent )
+ if ( !IsValid( ent ) && ent:GetClass() != "worldspawn") then return end
+ if ( ent:GetClass() == "gms_gravestone" and !ply:IsAdmin() ) then return end
+ if ( ent:GetNWString( "Owner" ) == "World" && ply:IsAdmin() && GetConVarNumber( "spp_admin_wp" ) == 1 ) then return true end
+ if ( SPropProtection.PlayerCanTouch( ply, ent ) ) then return true end
+end
+/*hook.Add( "GravGunPunt", "SPropProtection.GravGunPunt", PhysGravGunPickup )
+hook.Add( "GravGunPickupAllowed", "SPropProtection.GravGunPickupAllowed", PhysGravGunPickup )
+hook.Add( "PhysgunPickup", "SPropProtection.PhysgunPickup", PhysGravGunPickup )
+hook.Add( "CanTool", "SPropProtection.CanTool", PhysGravGunPickup )*/
+
+/* ----------------------------------------------
+ SPP Console Variables
+------------------------------------------------ */
+
+if ( SPPCVars ) then return end -- Auto-Refresh protection
+
+SPPCVars = {}
+
+function CreateSPPCVar( name, def )
+ if ( SERVER ) then
+
+ table.insert( SPPCVars, "spp_" .. name )
+ CreateConVar( "spp_" .. name, def, FCVAR_ARCHIVE )
+
+ cvars.AddChangeCallback( "spp_" .. name, function( cvar, old, new )
+
+ if ( math.floor( old ) == math.floor( new ) ) then return end
+ for id, pl in pairs( player.GetAll() ) do pl:ConCommand( "spp_" .. name .. " " .. math.floor( new ) ) end
+
+ end )
+
+ else
+
+ CreateConVar( "spp_" .. name, def )
+ cvars.AddChangeCallback( "spp_" .. name, function( cvar, old, new )
+
+ if ( math.floor( old ) == math.floor( new ) ) then return end
+ timer.Destroy( "spp_update" .. name )
+ timer.Create("spp_update" .. name, 2, 1, function() RunConsoleCommand( "spp_update", name, math.floor( new ) ) end )
+
+ end )
+
+ end
+end
+
+CreateSPPCVar( "enabled", "1" )
+CreateSPPCVar( "admin", "0" )
+CreateSPPCVar( "admin_wp", "0" )
+CreateSPPCVar( "use", "1" )
+CreateSPPCVar( "entdmg", "1" )
+CreateSPPCVar( "del_disconnected", "1" )
+CreateSPPCVar( "del_adminprops", "1" )
+CreateSPPCVar( "del_delay", "120" )
+
+if ( CLIENT ) then return end
+
+concommand.Add( "spp_update", function( ply, cmd, args )
+
+ if ( !ply:IsAdmin() ) then return end
+
+ local cmd = args[ 1 ]
+ local val = args[ 2 ]
+
+ if ( math.floor( GetConVarNumber( "spp_" .. cmd ) ) == math.floor( val ) ) then return end
+
+ RunConsoleCommand( "spp_" .. cmd, math.floor( val ) )
+
+end )
+
+hook.Add( "PlayerInitialSpawn", "spp.sync_cvars", function( ply )
+ for id, cvar in pairs( SPPCVars ) do ply:ConCommand( cvar .. " " .. math.floor( GetConVarNumber( cvar ) ) ) end
+end )
diff --git a/ftp_gmstranded/gamemode/spp/sv_init.lua b/ftp_gmstranded/gamemode/spp/sv_init.lua
new file mode 100644
index 0000000..a4df311
--- /dev/null
+++ b/ftp_gmstranded/gamemode/spp/sv_init.lua
@@ -0,0 +1,369 @@
+
+SPropProtection[ "Props" ] = SPropProtection[ "Props" ] or {}
+
+if ( cleanup ) then
+ local Clean = cleanup.Add
+ function cleanup.Add( ply, Type, ent )
+ if ( IsValid( ent ) && ply:IsPlayer() ) then SPropProtection.PlayerMakePropOwner( ply, ent ) end
+ Clean( ply, Type, ent )
+ end
+end
+
+local Meta = FindMetaTable("Player")
+if ( Meta.AddCount ) then
+ local Backup = Meta.AddCount
+ function Meta:AddCount( Type, ent )
+ SPropProtection.PlayerMakePropOwner( self, ent )
+ Backup( self, Type, ent )
+ end
+end
+
+function SPropProtection.NofityAll( Text )
+ for k, ply in pairs( player.GetAll() ) do
+ SPropProtection.Nofity( ply, Text )
+ end
+end
+
+function SPropProtection.Nofity( ply, Text )
+ ply:SendLua("GAMEMODE:AddNotify(\"" .. Text .. "\", NOTIFY_GENERIC, 5); surface.PlaySound(\"ambient/water/drip" .. math.random(1, 4) .. ".wav\")")
+ ply:PrintMessage( HUD_PRINTCONSOLE, Text )
+end
+
+function SPropProtection.PlayerMakePropOwner( ply, ent )
+ if ( !IsValid( ent ) or ent:IsPlayer() ) then return end
+
+ if ( ply && type( ply ) == "table" ) then
+ SPropProtection[ "Props" ][ ent:EntIndex() ] = { ply.SteamID, ent }
+ ent:SetNWString( "Owner", ply.Nick )
+ ent:SetNWInt( "OwnerID", ply.EntIndex )
+ ent:SetNWInt( "TribeID", ply.Team )
+ return true
+ end
+
+ if ( !IsValid( ply ) or !ply:IsPlayer() ) then return end
+
+ SPropProtection[ "Props" ][ ent:EntIndex() ] = { ply:SteamID(), ent }
+ ent:SetNWString( "Owner", ply:Nick() )
+ ent:SetNWInt( "OwnerID", ply:EntIndex() )
+ ent:SetNWInt( "TribeID", ply:Team() )
+ gamemode.Call( "CPPIAssignOwnership", ply, ent )
+ return true
+end
+
+function SPropProtection.PlayerIsPropOwner( ply, ent )
+ if ( !IsValid( ent ) or ent:IsPlayer() ) then return false end
+ if ( !SPropProtection[ "Props" ][ ent:EntIndex() ] ) then return false end
+
+ if ( SPropProtection[ "Props" ][ ent:EntIndex() ][ 1 ] == ply:SteamID() && ent:GetNWString( "Owner" ) == ply:Nick() && ent:GetNWInt( "OwnerID" ) == ply:EntIndex() ) then
+ return true
+ else
+ return false
+ end
+end
+
+function SPropProtection.IsBuddy( ply, ent )
+ if ( SPropProtection.PlayerIsPropOwner( ply, ent ) ) then return true end
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_admin" ) == 1 && ent:GetNWString( "Owner" ) != "World" ) then return true end
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_admin_wp" ) == 1 && ent:GetNWString( "Owner" ) == "World" ) then return true end
+ if ( ply:Team() == ent:GetNWInt( "TribeID", 1 ) && GAMEMODE.FindTribeByID( ply:Team() ).password != false ) then return true end
+ if ( ent:IsPlayer() or ent:IsNPC() ) then return false end
+ if ( ent:GetNWString( "Owner" ) == "World" ) then return false end
+
+ for k, v in pairs( player.GetAll() ) do
+ if ( IsValid( v ) && v != ply ) then
+ if ( !SPropProtection[ "Props" ][ ent:EntIndex() ] ) then continue end
+ if ( SPropProtection[ "Props" ][ ent:EntIndex() ][ 1 ] == v:SteamID() ) then
+ if ( !SPropProtection[ v:SteamID() ] ) then return false end
+
+ if ( table.HasValue( SPropProtection[ v:SteamID() ], ply:SteamID() ) ) then
+ return true
+ else
+ return false
+ end
+ end
+ end
+ end
+end
+
+function SPropProtection.PlayerCanTouch( ply, ent )
+ if ( GetConVarNumber( "spp_enabled" ) == 0 or ent:GetClass() == "worldspawn" ) then return true end
+ if ( ent:IsPlayer() or ent:IsNPC() ) then return false end
+
+ if ( ent:GetNWString( "Owner" ) == "Everyone" && !ent:IsPlayer() ) then
+ return true
+ end
+
+ /* Stranded Plants & Respacks*/
+ local isResource = ent:GetClass() == "gms_resourcepack" or ent:GetClass() == "gms_resourcedrop" or ent:GetClass() == "gms_fridge"
+ local isPlant = ent:IsBerryBushModel() or ent:IsGrainModel() or ent:IsFoodModel()
+ if ( ( ent:GetNWString( "Owner" ) == "World" or GetConVarNumber( "spp_use" ) <= 0 ) && ( isResource or isPlant ) ) then
+ return true
+ end
+
+ if ( ( !ent:GetNWString( "Owner" ) or ent:GetNWString( "Owner" ) == "" ) && !ent:IsPlayer() ) then
+ SPropProtection.PlayerMakePropOwner( ply, ent )
+ SPropProtection.Nofity( ply, "You now own this prop" )
+ return true
+ end
+
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_admin" ) == 1 && ent:GetNWString( "Owner" ) != "World" ) then return true end
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_admin_wp" ) == 1 && ent:GetNWString( "Owner" ) == "World" ) then return true end
+ if ( SPropProtection.IsBuddy( ply, ent ) ) then return true end
+ if ( SPropProtection[ "Props" ][ ent:EntIndex() ] != nil && SPropProtection[ "Props" ][ ent:EntIndex() ][ 1 ] == ply:SteamID() ) then
+ return true
+ end
+
+ return false
+end
+
+function SPropProtection.DRemove( SteamID, PlayerName )
+ for k, v in pairs( SPropProtection[ "Props" ] ) do
+ if ( v[ 1 ] == SteamID and IsValid( v[ 2 ] ) ) then
+ v[ 2 ]:Remove()
+ SPropProtection[ "Props" ][ k ] = nil
+ end
+ end
+ SPropProtection.NofityAll( tostring( PlayerName ) .. "'s props have been cleaned up" )
+end
+
+/* Tribe PP */
+
+SPropProtection.EmptifiedTribes = SPropProtection.EmptifiedTribes or {}
+function SPropProtection.RemoveTribeProps( TribeID )
+ for k, v in pairs( SPropProtection[ "Props" ] ) do
+ if ( IsValid(v[2]) and tonumber(v[2]:GetNWInt( "TribeID" ) ) == TribeID ) then
+ v[2]:Remove()
+ SPropProtection["Props"][k] = nil
+ end
+ end
+ SPropProtection.NofityAll( "Props of " .. GAMEMODE.FindTribeByID( TribeID ).name .. " have been cleaned up" )
+ SPropProtection.EmptifiedTribes[ TribeID ] = true
+end
+
+function SPropProtection.CheckForEmptyTribes()
+ for id, t in pairs( GAMEMODE.Tribes ) do
+ if ( team.NumPlayers( id ) == 0 && t.password != false && !timer.Exists( "SPropProtection.RemoveTribeProps: " .. id ) && !SPropProtection.EmptifiedTribes[ id ] ) then
+ timer.Create( "SPropProtection.RemoveTribeProps: " .. id, GetConVarNumber( "spp_del_delay" ), 1, function() SPropProtection.RemoveTribeProps( id ) end )
+ elseif ( team.NumPlayers( id ) > 0 ) then
+ SPropProtection.EmptifiedTribes[ id ] = false
+ timer.Remove( "SPropProtection.RemoveTribeProps: " .. id )
+ end
+ end
+end
+
+function SPropProtection.TribePP( ply )
+ for k, v in pairs( SPropProtection[ "Props" ] ) do
+ if ( v[ 1 ] == ply:SteamID() && IsValid( v[ 2 ] ) ) then
+ v[ 2 ]:SetNWInt( "TribeID", ply:Team() )
+
+ timer.Remove( "SPropProtection.RemoveTribeProps: " .. ply:Team() )
+ SPropProtection.CheckForEmptyTribes()
+ end
+ end
+end
+
+/* Hooks */
+
+hook.Add( "PlayerInitialSpawn", "SPropProtection.PlayerInitialSpawn", function( ply )
+ ply:SetNWString( "SPPSteamID", string.gsub( ply:SteamID(), ":", "_" ) )
+ SPropProtection[ ply:SteamID() ] = {}
+ SPropProtection.LoadBuddies( ply )
+ SPropProtection.TribePP( ply )
+
+ timer.Remove( "SPropProtection.DRemove: " .. ply:SteamID() )
+end )
+
+hook.Add( "PlayerDisconnected", "SPropProtection.Disconnect", function( ply )
+ if ( GetConVarNumber( "spp_del_disconnected" ) == 0 ) then return end
+ if ( ply:IsAdmin() && GetConVarNumber( "spp_del_adminprops" ) <= 0 ) then return end
+ if ( GAMEMODE.FindTribeByID( ply:Team() ).password == false ) then
+ local nick = ply:Nick()
+ local id = ply:SteamID()
+ timer.Create( "SPropProtection.DRemove: " .. ply:SteamID(), GetConVarNumber( "spp_del_delay" ), 1, function() SPropProtection.DRemove( id, nick ) end )
+ end
+ SPropProtection.CheckForEmptyTribes()
+end )
+
+hook.Add( "EntityTakeDamage", "SPropProtection.EntityTakeDamage", function( ent, inflictor, attacker, amount, dmginfo )
+ if ( !IsValid( ent ) || !IsValid( attacker ) ) then return end
+ if ( string.find( ent:GetClass(), "npc_" ) ) then return end
+ if ( GetConVarNumber( "spp_entdmg" ) == 0 ) then return end
+ if ( ent:IsPlayer() or !attacker:IsPlayer() ) then return end
+ if ( !SPropProtection.PlayerCanTouch( attacker, ent ) ) then
+ local total = ent:Health() + amount
+ if ( ent:GetMaxHealth() > total ) then ent:SetMaxHealth( total ) else ent:SetHealth( total ) end
+ end
+end )
+
+hook.Add( "PlayerUse", "SPropProtection.PlayerUse", function(ply, ent)
+ if ( ent:IsValid() && GetConVarNumber( "spp_use" ) >= 1 ) then
+ return SPropProtection.PlayerCanTouch( ply, ent )
+ end
+end )
+
+hook.Add( "OnPhysgunReload", "SPropProtection.OnPhysgunReload", function( weapon, ply )
+ local tr = ply:GetEyeTrace()
+ if ( !tr.HitNonWorld or !IsValid( tr.Entity ) or tr.Entity:IsPlayer() ) then return end
+ if ( !SPropProtection.PlayerCanTouch( ply, tr.Entity ) ) then return false end
+end )
+
+hook.Add( "EntityRemoved", "SPropProtection.EntityRemoved", function( ent )
+ SPropProtection[ "Props" ][ ent:EntIndex() ] = nil
+end )
+
+hook.Add( "PlayerSpawnedSENT", "SPropProtection.PlayerSpawnedSENT", function( ply, ent )
+ SPropProtection.PlayerMakePropOwner( ply, ent )
+end )
+
+hook.Add( "PlayerSpawnedVehicle", "SPropProtection.PlayerSpawnedVehicle", function( ply, ent )
+ SPropProtection.PlayerMakePropOwner( ply, ent )
+end )
+
+hook.Add( "InitPostEntity", "spp_map_ents", function()
+ local WorldEnts = 0
+ for k, v in pairs( ents.GetAll() ) do
+ if ( !v:IsPlayer() and !v:GetNWString( "Owner", false ) ) then
+ v:SetNetworkedString( "Owner", "World" )
+ WorldEnts = WorldEnts + 1
+ end
+ end
+ MsgC( Color( 64, 176, 255 ), "\n[ Simple Prop Protection ] " .. tostring( WorldEnts ) .. " props belong to world\n\n" )
+end )
+
+/* Commands */
+
+concommand.Add( "spp_cleanup_props_left", function( ply, cmd, args )
+ if ( !ply:IsAdmin() ) then return end
+ for k1, v1 in pairs( SPropProtection[ "Props" ] ) do
+ local FoundUID = false
+ for k2, v2 in pairs( player.GetAll() ) do
+ if( v1[ 1 ] == v2:SteamID() ) then
+ FoundUID = true
+ end
+ end
+ if ( FoundUID == false and IsValid( v1[ 2 ] ) ) then
+ v1[ 2 ]:Remove()
+ SPropProtection[ "Props" ][ k1 ] = nil
+ end
+ end
+ SPropProtection.NofityAll("Disconnected players props have been cleaned up")
+end )
+
+concommand.Add( "spp_cleanup_props", function( ply, cmd, args )
+ if ( !args[1] or args[1] == "" ) then
+ for k, v in pairs( SPropProtection["Props"] ) do
+ if (v[1] == ply:SteamID()) then
+ if (v[2]:IsValid()) then
+ v[2]:Remove()
+ SPropProtection["Props"][k] = nil
+ end
+ end
+ end
+ SPropProtection.Nofity(ply, "Your props have been cleaned up")
+ elseif ( ply:IsAdmin() ) then
+ for k, v in pairs(player.GetAll()) do
+ local NWSteamID = v:GetNWString( "SPPSteamID" )
+ if ( args[1] == NWSteamID or args[2] == NWSteamID or string.find( string.Implode( " ", args ), NWSteamID ) != nil) then
+ for a, b in pairs( SPropProtection[ "Props" ] ) do
+ if ( b[1] == v:SteamID() && IsValid( b[ 2 ] ) ) then
+ b[2]:Remove()
+ SPropProtection[ "Props" ][ a ] = nil
+ end
+ end
+ SPropProtection.NofityAll( v:Nick() .. "'s props have been cleaned up" )
+ end
+ end
+ end
+ ply:SetNWInt( "plants", 0 )
+end )
+
+/* Buddies */
+
+function SPropProtection.SyncBuddies( ply )
+ for id, pl in pairs( player.GetAll() ) do
+ umsg.Start( "spp_clearbuddy", pl ) umsg.End()
+ if ( table.HasValue( SPropProtection[ ply:SteamID() ], pl:SteamID() ) ) then
+ umsg.Start( "spp_addbuddy", pl )
+ umsg.String( ply:SteamID() )
+ umsg.End()
+ end
+ end
+end
+
+function SPropProtection.LoadBuddies( ply )
+ local PData = ply:GetPData( "SPPBuddies", "" )
+ if ( PData == "" ) then return end
+ for k, v in pairs( string.Explode( ";", PData ) ) do
+ local v = string.Trim( v )
+ if ( v != "" ) then table.insert( SPropProtection[ ply:SteamID() ], v ) end
+ end
+
+ SPropProtection.SyncBuddies( ply )
+end
+
+concommand.Add( "spp_apply_buddies", function( ply, cmd, args )
+ if ( table.Count( player.GetAll() ) > 1 ) then
+ local ChangedFriends = false
+ for k, v in pairs( player.GetAll() ) do
+ local PlayersSteamID = v:SteamID()
+ local PData = ply:GetPData( "SPPBuddies", "" )
+ if ( tonumber( ply:GetInfo( "spp_buddy_" .. v:GetNWString("SPPSteamID") ) ) == 1 ) then
+ if ( !table.HasValue( SPropProtection[ ply:SteamID() ], PlayersSteamID ) ) then
+ ChangedFriends = true
+ table.insert( SPropProtection[ ply:SteamID() ], PlayersSteamID )
+ if ( PData == "" ) then
+ ply:SetPData( "SPPBuddies", PlayersSteamID .. ";")
+ else
+ ply:SetPData( "SPPBuddies", PData .. PlayersSteamID .. ";")
+ end
+ end
+ else
+ if ( table.HasValue( SPropProtection[ ply:SteamID() ], PlayersSteamID ) ) then
+ for k2, v2 in pairs( SPropProtection[ply:SteamID() ] ) do
+ if ( v2 == PlayersSteamID ) then
+ ChangedFriends = true
+ table.remove( SPropProtection[ ply:SteamID() ], k2 )
+ ply:SetPData( "SPPBuddies", string.gsub( PData, PlayersSteamID .. ";", "" ) )
+ end
+ end
+ end
+ end
+ end
+
+ if ( ChangedFriends ) then
+ local Table = {}
+ for k, v in pairs( SPropProtection[ ply:SteamID() ] ) do
+ for k2, v2 in pairs( player.GetAll() ) do
+ if ( v == v2:SteamID() ) then
+ table.insert( Table, v2 )
+ end
+ end
+ end
+ gamemode.Call( "CPPIFriendsChanged", ply, Table )
+ end
+ end
+
+ SPropProtection.SyncBuddies( ply )
+ SPropProtection.Nofity( ply, "Your buddies have been updated" )
+end )
+
+concommand.Add( "spp_clear_buddies", function( ply, cmd, args )
+ local PData = ply:GetPData( "SPPBuddies", "" )
+ if ( PData != "" ) then
+ for k, v in pairs( string.Explode( ";", PData ) ) do
+ local v = string.Trim( v )
+ if ( v != "" ) then
+ ply:ConCommand( "spp_buddy_" .. string.gsub( v, ":", "_" ) .. " 0\n" )
+ end
+ end
+ ply:SetPData( "SPPBuddies", "" )
+ end
+
+ for k, v in pairs( SPropProtection[ ply:SteamID() ] ) do
+ ply:ConCommand( "spp_buddy_" .. string.gsub( v, ":", "_" ) .. " 0\n" )
+ end
+ SPropProtection[ ply:SteamID() ] = {}
+
+ SPropProtection.SyncBuddies( ply )
+ SPropProtection.Nofity( ply, "Your buddies have been cleared" )
+end )
diff --git a/ftp_gmstranded/gamemode/time_weather.lua b/ftp_gmstranded/gamemode/time_weather.lua
new file mode 100644
index 0000000..bc34fac
--- /dev/null
+++ b/ftp_gmstranded/gamemode/time_weather.lua
@@ -0,0 +1,185 @@
+
+NightLight = string.byte( "a" )
+DayLight = string.byte( "m" )
+
+NextPattern = NextPattern or DayLight
+CurrentPattern = CurrentPattern or DayLight
+
+RiseTime = 300
+DayTime = 480
+SetTime = 960
+NightTime = 1200
+
+StealTime = 0
+Time = Time or RiseTime + 1
+
+IsNight = false
+
+if ( CLIENT ) then
+ timer.Simple( 5, function()
+ RunConsoleCommand( "pp_sunbeams", "0" )
+ end )
+
+ hook.Add( "RenderScreenspaceEffects", "RenderSunbeams", function()
+ if ( !render.SupportsPixelShaders_2_0() ) then return end
+ local sun = util.GetSunInfo()
+
+ if ( !sun ) then return end
+ if ( sun.obstruction == 0 ) then return end
+
+ local sunpos = EyePos() + sun.direction * 4096
+ local scrpos = sunpos:ToScreen()
+
+ local dot = ( sun.direction:Dot( EyeVector() ) - 0.8 ) * 5
+ if ( dot <= 0 ) then return end
+
+ DrawSunbeams( 0.85, 1 * dot * sun.obstruction, 0.25, scrpos.x / ScrW(), scrpos.y / ScrH() )
+ end )
+
+ timer.Create( "DayTime.TimerClient", 1, 0, function()
+ if ( GetConVarNumber( "gms_daynight" ) <= 0 ) then return end
+
+ Time = Time + 1
+ if ( Time > 1440 ) then Time = 0 end
+ end )
+elseif ( SERVER ) then
+
+ RunConsoleCommand( "sv_skyname", "painted" )
+
+ local GMS_DayColorTop = Vector( 0.22, 0.51, 1.0 )
+ local GMS_DayColorBottom = Vector( 0.92, 0.93, 0.99 )
+ local GMS_DayColorDusk = Vector( 1.0, 0.2, 0.0 )
+ local GMS_Clouds = "skybox/clouds"
+ local GMS_Stars = "skybox/starfield"
+ local GMS_StarFade = 1//0.5
+ local GMS_StarScale = 1.75
+ local GMS_StarSpeed = 0.03
+ theSky = theSky or nil
+
+ hook.Add( "InitPostEntity", "gms_create_skypaint", function()
+ if ( table.Count( ents.FindByClass( "env_skypaint" ) ) >= 1 ) then theSky = ents.FindByClass( "env_skypaint" )[ 1 ] return end
+ theSky = ents.Create( "env_skypaint" )
+ theSky:Spawn()
+ end )
+
+ timer.Create( "DayTime.TimerServer", 1, 0, function()
+ if ( GetConVarNumber( "gms_daynight" ) <= 0 ) then return end
+
+ Time = Time + 1
+ if ( Time > 1440 ) then Time = 0 end
+
+ //Time = CurTime() - math.floor( CurTime() / 1440 ) * 1440
+
+ for id, sun in pairs( ents.FindByClass( "env_sun" ) or {} ) do
+ sun:SetKeyValue( "pitch", math.NormalizeAngle( ( Time / 1440 * 360 ) + 90 ) )
+ sun:Activate()
+ end
+
+ local coef = 0
+ if ( Time >= NightTime && Time < RiseTime ) then // Night
+ IsNight = true
+ coef = 0
+ elseif ( Time >= RiseTime && Time < DayTime ) then // Sunrise
+ IsNight = false
+ coef = 1 - ( DayTime - Time ) / ( DayTime - RiseTime ) // Calculate progress
+ elseif ( Time >= DayTime && Time < SetTime ) then // Day
+ IsNight = false
+ coef = 1
+ elseif ( Time >= SetTime && Time < NightTime ) then // Sunset
+ IsNight = false
+ coef = ( NightTime - Time ) / ( NightTime - SetTime ) // Calculate progress
+ end
+
+ local dusk_coef = coef
+ if ( dusk_coef > 0.5 ) then
+ dusk_coef = 1 - dusk_coef
+ if ( IsValid( theSky ) ) then
+ if ( theSky:GetStarTexture() != GMS_Clouds ) then
+ theSky:SetStarTexture( GMS_Clouds )
+ theSky:SetStarScale( GMS_StarScale )
+ end
+ end
+ else
+ if ( IsValid( theSky ) ) then
+ if ( theSky:GetStarTexture() != GMS_Stars ) then
+ theSky:SetStarTexture( GMS_Stars )
+ theSky:SetStarScale( 0.5 )
+ end
+ end
+ end
+
+ if ( IsValid( theSky ) ) then
+ theSky:SetTopColor( GMS_DayColorTop * coef )
+ theSky:SetBottomColor( GMS_DayColorBottom * coef )
+ theSky:SetStarFade( GMS_StarFade * ( 0.5 - dusk_coef ) )
+ theSky:SetSunSize( 1 )
+
+ if ( IsNight ) then dusk_coef = 0 end
+ theSky:SetDuskColor( GMS_DayColorDusk * dusk_coef )
+ end
+
+ NextPattern = math.Clamp( NightLight + math.ceil( ( DayLight - NightLight ) * coef ), NightLight, DayLight )
+
+ if ( NextPattern != CurrentPattern ) then
+ for _, light in pairs( ents.FindByClass( "light_environment" ) or {} ) do
+ light:Fire( "FadeToPattern", string.char( NextPattern ) )
+ light:Activate()
+ end
+
+ //engine.LightStyle( 0, string.char( NextPattern - 1 ) )
+ //for id, ply in pairs( player.GetAll() ) do ply:SendLua( "render.RedownloadAllLightmaps()" ) end
+
+ CurrentPattern = NextPattern
+ end
+
+ if ( Time == StealTime && GetConVarNumber( "gms_night_cleanup" ) >= 1 ) then
+ local drops = ents.FindByClass( "gms_resourcedrop" )
+ local weaps = ents.FindByClass( "gms_resourcedrop" )
+ local msg = false
+
+ if ( #drops > 8 ) then for id, ent in pairs( drops ) do msg = true ent:Fadeout() end end
+ if ( #weaps > 4 ) then for id, ent in pairs( weaps ) do msg = true ent:Fadeout() end end
+
+ if ( msg ) then
+ for id, ply in pairs( player.GetAll() ) do
+ ply:SendMessage( "Something happened outside...", 5, Color( 255, 10, 10, 255 ) )
+
+ timer.Simple( 10, function()
+ ply:SendMessage( "So they dont't get stolen at night.", 5, Color( 255, 150, 150, 255 ) )
+ ply:SendMessage( "Remember to store your resources in resoucepack, ", 5, Color( 255, 150, 150, 255 ) )
+ end )
+ end
+ end
+
+ for i = 0, math.random( 2, 6 ) do
+ local zombies = #ents.FindByClass( "npc_zombie" )
+ local fzombies = #ents.FindByClass( "npc_fastzombie" )
+ if ( zombies + fzombies > 14 ) then break end
+ local pos = Vector( math.random( -6000, 6000 ), math.random( -6000, 6000 ), 1800 )
+ local tr = util.TraceLine( {
+ start = pos, endpos = pos - Vector( 0, 0, 9999 )
+ } )
+
+ if ( tr.HitWorld ) then
+ local class = "npc_zombie"
+ if ( math.random( 0, 100 ) < 25 ) then class = "npc_fastzombie" end
+ local zombie = ents.Create( class )
+ zombie:SetPos( tr.HitPos + Vector( 0, 0, 64 ) )
+ zombie:SetHealth( 128 )
+ zombie:SetNWString( "Owner", "World" )
+ zombie:SetKeyValue( "spawnflags", "1280" )
+ zombie:Spawn()
+ zombie:Fire( "Wake" )
+ zombie:Activate()
+
+ local ourEnemy = player.GetByID( math.random( 1, #player.GetAll() ) )
+ if ( IsValid( ourEnemy ) ) then
+ zombie:SetEnemy( ourEnemy )
+ zombie:SetLastPosition( ourEnemy:GetPos() )
+ zombie:SetSchedule( SCHED_FORCED_GO )
+ end
+ end
+ end
+ end
+ end )
+end
diff --git a/ftp_gmstranded/gamemode/unlocks.lua b/ftp_gmstranded/gamemode/unlocks.lua
new file mode 100644
index 0000000..25d2050
--- /dev/null
+++ b/ftp_gmstranded/gamemode/unlocks.lua
@@ -0,0 +1,153 @@
+
+GMS.FeatureUnlocks = {}
+
+function GMS.RegisterUnlock( tbl )
+ GMS.FeatureUnlocks[ string.Replace( tbl.Name, " ", "_" ) ] = tbl
+end
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Sprinting I"
+UNLOCK.Description = "You can now hold down shift to sprint."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Survival" ] = 4
+
+function UNLOCK.OnUnlock( ply )
+ if ( !ply:HasUnlock( "Sprinting_II" ) ) then
+ if ( ply.CROW ) then ply.CROW.speeds.run = 250 ply.CROW.speeds.sprint = 400 return end
+ GAMEMODE:SetPlayerSpeed( ply, 250, 400 )
+ end
+end
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Sprinting II"
+UNLOCK.Description = "Your movement speed has got permanent increase. Also, your sprint is now walk."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Survival" ] = 12
+
+function UNLOCK.OnUnlock( ply )
+ if ( ply.CROW ) then ply.CROW.speeds.run = 400 ply.CROW.speeds.sprint = 100 return end
+ GAMEMODE:SetPlayerSpeed( ply, 400, 100 )
+end
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Adept Survivalist"
+UNLOCK.Description = "Your max health has been increased by 50%."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Survival" ] = 16
+
+function UNLOCK.OnUnlock( ply )
+ if ( ply:GetMaxHealth() < 150 ) then ply:SetMaxHealth( 150 ) end
+ ply:Heal( 50 )
+end
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Master Survivalist"
+UNLOCK.Description = "Your max health has been increased by 33%."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Survival" ] = 32
+
+function UNLOCK.OnUnlock( ply )
+ ply:SetMaxHealth( 200 )
+ ply:Heal( 50 )
+end
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Extreme Survivalist"
+UNLOCK.Description = "You can now become a crow and fly around."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Survival" ] = 48
+
+function UNLOCK.OnUnlock( ply )
+ ply:Give( "pill_pigeon" )
+end
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Sprout Collecting"
+UNLOCK.Description = "You can now press use on a tree to attempt to loosen a sprout.\nSprouts can be planted if you have the skill, and they will grow into trees."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Lumbering" ] = 5
+UNLOCK.Req[ "Harvesting" ] = 5
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Grain Planting"
+UNLOCK.Description = "You can now plant grain."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Planting" ] = 3
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Sprout Planting"
+UNLOCK.Description = "You can now plant sprouts, which will grow into trees."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Planting" ] = 5
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Adept Farmer"
+UNLOCK.Description = "Your melon, orange and banana vines can now carry up to 2 fruits instead of one."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Planting" ] = 12
+
+GMS.RegisterUnlock( UNLOCK )
+
+----------------------------------------------------------------------------------------------------
+
+local UNLOCK = {}
+
+UNLOCK.Name = "Expert Farmer"
+UNLOCK.Description = "Your melon, orange and banana vines can now carry up to 3 fruits instead of one."
+
+UNLOCK.Req = {}
+UNLOCK.Req[ "Planting" ] = 24
+
+GMS.RegisterUnlock( UNLOCK )