
local meta = FindMetaTable( "Player" );

function meta:Initialize()

	local ply = self;

	ply:SetTeam( 1 ); 
	ply:SnapOutOfStance();
	
	--VAR INITIALIZATION--
	
	ply:GetTable().Initialized = false; 
	ply:GetTable().HasSeenMOTD = false; 
	ply:SetNWBool( "IsTyping", false ); 
	ply:GetTable().ProcessBars = { }; 
	
	ply:GetTable().AttachedProps = { }
	
	ply:GetTable().AnimLastModel = "";
	ply:GetTable().LastWeapon = "";
	 
	ply:GetTable().SendItemNames = { }
	
	ply:GetTable().NextTimeCanChat = 0;
	ply:GetTable().NextTimeCanChatOOC = 0;
	
	ply:GetTable().CanUseDuplicator = false;
	
	ply:GetTable().LastCharCreateMenu = 0;
	ply:GetTable().LastCharCreation = 0;
	ply:GetTable().LastFlashSwitch = 0;
	ply:GetTable().LastStanceAction = 0;
	ply:GetTable().LastMOTDPrompt = 0;
	ply:GetTable().LastStorageItemAdd = 0;
	ply:GetTable().LastTargetIDUpdate = 0;
	ply:GetTable().LastItemUse = 0;
	ply:GetTable().LastKeyPress = 0;
	ply:GetTable().LastF4 = 0;
	ply:GetTable().LastHelp = 0;
	ply:GetTable().LastConsciousRecover = 0;
	
	ply:Observe( false );
	
	ply:SetPlayerBleeding( false );
	ply:SetPlayerCanSprint( true );
	ply:SetPlayerConscious( true );
	
	ply:GetTable().ItemsDownloaded = { }
	
	--END VAR INITIALIZATION--
	
	ply:MakeInvisible();
	ply:Lock();
	
	
	timer.Simple( .5, ply.CrosshairDisable, ply );
	timer.Simple( .6, ply.DrawViewModel, ply, false ); 
	
	-- i broke debugging, hurrr
	--Comment out this line if we aren't debugging
	--local debugging = true;
	
	if( not debugging ) then
	
		--Delay so that it doesn't fuck up
		timer.Simple( 1, ply.PromptAccountMenu, ply );
	
	else
	
		ply:CharacterInitialize();
		umsg.Start( "EFGI", ply ); umsg.End();
		
		ply:GetTable().CanInitialize = true;
		ply:GetTable().HasSeenMOTD = true;
	
	end

end

function GM:PlayerInitialSpawn( ply )

	ply:SetField( "charid", -1 );
	ply:SetField( "UniqueID", math.random( 0, 1000 ) );

	umsg.Start( "setUniqueID", ply );
		umsg.Short( ply:GetField( "UniqueID" ) );
	umsg.End();
	
	ply:SetNWString( "SteamID", ply:SteamID() )
	
	ply:ConCommand( "eng_charnumber" )
	
	ply:SetNWString( "RPName", "Connecting" )
	
	ply:HandleUID()
	

end	

function meta:RefreshShit()
	
	local ply = self;
	
	--Inventories
	ply:GetTable().Inventories = { }
	
	--Just a list of the items in our inventory
	ply:GetTable().InventoryList = { }
	
	--Serverside inventory grid.  CPU lag?  We'll see.
	ply:GetTable().InventoryGrid = { }
	
	for n = 1, TS.MaxInventories do
		
		ply:GetTable().Inventories[n] = { }
		ply:GetTable().Inventories[n].Name = "";
		ply:GetTable().Inventories[n].Width = 9;
		ply:GetTable().Inventories[n].Height = 6;
	
		ply:GetTable().InventoryGrid[n] = { }
	
		for x = 0, 8 do
		
			ply:GetTable().InventoryGrid[n][x] = { }
		
			for y = 0, 5 do
			
				ply:GetTable().InventoryGrid[n][x][y] = { }
				ply:GetTable().InventoryGrid[n][x][y].Filled = false;
			
			end
			
		end
		
	end
	
	ply:CallEvent( "ResetInventory" );
	
	ply:GetTable().CCModel = ""
	ply:GetTable().CCAge = ""
	ply:GetTable().CCName = ""
	
	ply:GetTable().CCStrength = 0
	ply:GetTable().CCEndurance = 0
	ply:GetTable().CCSpeed = 0
	ply:GetTable().CCAim = 0
	
	

end

function meta:CharacterInitialize()
	
	local ply = self;
	
	--Inventories
	ply:GetTable().Inventories = { }
	
	--Just a list of the items in our inventory
	ply:GetTable().InventoryList = { }
	
	--Serverside inventory grid.  CPU lag?  We'll see.
	ply:GetTable().InventoryGrid = { }
	
	for n = 1, TS.MaxInventories do
		
		ply:GetTable().Inventories[n] = { }
		ply:GetTable().Inventories[n].Name = "";
		ply:GetTable().Inventories[n].Width = 9;
		ply:GetTable().Inventories[n].Height = 6;
	
		ply:GetTable().InventoryGrid[n] = { }
	
		for x = 0, 8 do
		
			ply:GetTable().InventoryGrid[n][x] = { }
		
			for y = 0, 5 do
			
				ply:GetTable().InventoryGrid[n][x][y] = { }
				ply:GetTable().InventoryGrid[n][x][y].Filled = false;
			
			end
			
		end
		
	end
	
	ply:CallEvent( "ResetInventory" );

	ply:SetHealth( 100 );
	ply:GetTable().MaxHealth = 100;
	
	ply:GetTable().StatusIsInjured = false;
	ply:GetTable().StatusIsCrippled = false;
	ply:GetTable().IsTied = false;
	
	ply:GetTable().LastDrunkMulUpdate = 0;
	ply:GetTable().LastDrunkWalkUpdate = 0;
	ply:GetTable().LastDrunkWalkMul = 0;
	
	ply:Conscious();

	--Compute player speeds on new character
	ply:ComputePlayerSpeeds();
	
	--Set model
	ply:SetModel( ply:GetTable().CCModel or ply:GetNWString( "PlayerModel" ) or "" );
	
	--[[if( ply:SteamID() == "STEAM_0:1:4976333" ) then
		ply:SetModel( "models/odessa.mdl" );
	end]]--
	
	ply:SetPlayerSprint( 100 );
	ply:SetPlayerConsciousness( 100 );
	ply:SetPlayerRubles( 200 );
	ply:SetPlayerTitle( "Citizen" );
	ply:SetPlayerSecondTitle( "Class D" );
	ply:SetField( "radiofreq", 0 )
	ply:SetPlayerBleeding( false );
	ply:SetPlayerCanSprint( true );
	ply:SetPlayerConscious( true );
	
	ply:ResetBleeding();
	
	ply:MakeNotInvisible();
	
	ply:SetTeam( 1 );
	
	--We're initialized and allow the player to move around again
	ply:GetTable().Initialized = true;
	ply:UnLock();
	
	ply:DrawViewModel( true );

	ply:CallEvent( "MapViewOff" );
	
	ply:KillSilent();
	ply:Spawn();
	
	ply:HandleUID()
	
	if( ply:CanUseCommand() ) then
		ply:SetField( "group_max_props", 200 );
	end	

end

function GM:PlayerSpawn( ply )	

	if( not ply:GetTable().Initialized ) then
		ply:SetModel( "models/odessa.mdl" );
		ply:SetNoDraw( true );
		ply:SetNotSolid( true );
		return;
	end
	
	if( ply:GetTable().RagdollEntity and ply:GetTable().RagdollEntity:IsValid() ) then
		if( ply:GetTable().BypassUnconscious ) then
			ply:RemoveRagdoll();
			ply:GetTable().BypassUnconscious = false;
		else
			ply:MakeInvisible();
			ply:CrosshairDisable();
			ply:SetPos( ply:GetTable().RagdollEntity:GetPos() );
			ply:Freeze( true );
			return;
		end
	end
	
	if( ply:GetTable().SpawnPosition ) then
	
		ply:SetPos( ply:GetTable().SpawnPosition );
		ply:GetTable().SpawnPosition = nil;
	
	end
	
	ply:SetPlayerDrunkMul( 0 );
	ply:CallEvent( "NoDrunk" );
	
	ply:GetTable().IsTied = false;
	

	umsg.Start( "TOFFOWS", ply ); umsg.End();

	ply:CrosshairDisable();
	
	ply:GetTable().LastWeapon = nil;
	
	ply:ResetBodyDamage();
	ply:ResetBleeding();
	
	ply:HandleTeamSpawn();
	--timer.Simple( .2, ply.HandleTeamSpawn, ply );

	ply:SetPlayerSprint( 100 );
	ply:SetPlayerConsciousness( 100 );
	
	if( ply:HasTT() ) then
		ply:Give( "gmod_tool" );
	end
	
	ply:Give( "weapon_physgun" );
	ply:Give( "weapon_physcannon" );
	ply:Give( "ts2_hands" );
	ply:Give( "ts2_keys" );
	
	ply:SelectWeapon( "ts2_hands" );
	
	ply:ComputePlayerSpeeds();

end

function GM:PlayerDeathSound()
	
	return true;

end

function GM:CanPlayerSuicide( ply )

	if( ply:IsTied() or not ply:GetPlayerConscious() ) then
	
		return false;
	
	end
	
	return true;

end

function GM:PlayerDeath( ply, weapon, attacker )



	local makeragdoll = true;
	
	ply:GetTable().ForceDeath = false;

	if( not ply:GetTable().BypassUnconscious ) then

		if( not ply:GetPlayerConscious() ) then
			ply:PrintMessage( 3, "Killing yourself during KO removes all your weapons" );
			ply:TakeAllInventoryWeapons();
			ply:Freeze( false );
			return;
		end
		
	elseif( not ply:GetPlayerConscious() ) then

		ply:Conscious();
		makeragdoll = false;
		
	end
	

	for k, v in pairs( ply:GetTable().ProcessBars ) do
	
		ply:GetTable().ProcessBars[k] = nil;
	
	end
	
	umsg.Start( "RAPB", ply ); umsg.End();
	
	ply:GetTable().HasTempWeapon = false;
	
	local trace = { }
	trace.start = ply:EyePos()
	trace.endpos = trace.start + ply:GetAimVector() * 55
	trace.filter = ply
			
	local tr = util.TraceLine( trace )
	
	if( attacker:IsPlayer() ) then
		
		if( attacker ~= ply ) then
			
			if( ply:GetActiveWeapon():IsValid() ) then
	
				local class = ply:GetActiveWeapon():GetClass();
			
				if( string.find( class, "ts2_" ) and
					class ~= "ts2_base" and
					class ~= "ts2_hands" and
					class ~= "ts2_kanyewest" and
					class ~= "ts2_keys" and
					class ~= "ts2_mapeditor" ) then
									
					TS.CreateItemProp( class, ply:GetActiveWeapon():GetPos(), ply:GetActiveWeapon():GetAngles() );
					ply:TakeAllInventoryWeapons();
					ply:RemoveAllInventoryItems()
					
					ply:CreateLootableRagdoll()
								
				end
				
			end

		end
		
	end	

	ply:SnapOutOfStance();

	if( makeragdoll ) then
		ply:CreateRagdoll();
	end
		
end		


function GM:PlayerConnect( name, address )

	umsg.Start( "PlyCon" );
		umsg.String( name );
	umsg.End();
	
	TS.PrintMessageAll( 2, name .. " has connected" );

end
 
function GM:PlayerDisconnected( ply )

	ply:SnapOutOfStance();

	if( ply:GetTable().RagdollEntity and ply:GetTable().RagdollEntity:IsValid() ) then
		ply:GetTable().RagdollEntity:Remove();
	end

	--[[umsg.Start( "PlyDisc" );
		umsg.String( ply:GetRPName() );
		umsg.String( ply:Nick() );
		umsg.String( ply:SteamID() );
	umsg.End();	--]]
	
--	ply:UpdateCharacter()

	TS.PrintMessageAll( 2, ply:GetRPName() .. " (SF: " .. ply:Nick() .. " ID: " .. ply:SteamID() .. ") has left the server" );
		
end

function GM:PlayerTraceAttack()

	return false;

end

function GM:ScalePlayerDamage( ply, hitgroup, dmginfo )

	if( not ply:GetTable().Initialized ) then return; end

	if( not dmginfo:GetAttacker():IsPlayer() and not dmginfo:GetAttacker():IsNPC() ) then
		return;
	end

	if( ply:GetTable().ObserveMode ) then
		dmginfo:SetDamage( -1000 );
		return dmginfo;
	end

	if( ply:GetTable().NoclipMode ) then
		dmginfo:SetDamage( -1000 );
		return dmginfo;
	end

	if( ply:GetActiveWeapon():IsValid() and ply:GetActiveWeapon():GetClass() == "ts2_kanyewest" ) then
		dmginfo:SetDamage( -1000 );
		return dmginfo;
	end

	ply:SnapOutOfStance();
	
	local weapon = dmginfo:GetInflictor();
	
	if( weapon:IsPlayer() or weapon:IsNPC() ) then
		weapon = weapon:GetActiveWeapon();
	end

	if( weapon:IsValid() and weapon:IsWeapon() ) then
	
		return ply:ScaleDamageFromAttack( dmginfo:GetInflictor(), weapon, hitgroup, dmginfo );
	
	end	
	
	dmginfo:SetDamage( -1000 );
	return dmginfo;
	
end


function GM:PlayerFootstep( ply, pos, foot, sound, volume, rf )  

    if( ply:IsCP() and ply:IsSprinting() ) then      
	   local num = math.random( 1, 6 );		
	   ply:EmitSound( Sound( "npc/metropolice/gear" .. num .. ".wav" ), 50, 100 );	  
    elseif( ply:IsCP() and ply:IsWalking() ) then     
       local ft = math.random( 1, 3 );		  	
       ply:EmitSound( Sound( "player/footsteps/tile"..ft..".wav" ), 45, 100 );	
	end   
	
	if( ply:IsCOTA() and ply:IsSprinting() ) then
	   local num = math.random( 1, 6 );
	   ply:EmitSound( Sound( "npc/combine_soldier/gear" .. num .. ".wav" ), 50, 100 );	   
	end

end	


function GM:Move( ply, mv )

	if( ply:GetTable().InStanceAction ) then
	
		return true;
	
	end

end

function GM:GravGunPunt( ply ) 

	if( ply:IsAwesome() ) then
		return true;
	end
	
	return false;
	
end

function meta:CheckLimit( str ) 
   
 	local c = self:GetField( "group_max_" .. str ) or server_settings.Int( "sbox_max"..str, 0 );
 	
 	if( self:GetField( "group_max_" .. str ) ) then
 	
 		if( server_settings.Int( "sbox_max"..str, 0 ) > self:GetField( "group_max_" .. str ) ) then
 		
 			c = server_settings.Int( "sbox_max"..str, 0 );
 		
 		end
 	
 	end
 	 
 	if ( c < 0 ) then return true end 
 	if ( self:GetCount( str ) > c-1 ) then self:LimitHit( str ) return false end 
   
 	return true 
   
 end 
   
function LimitReachedProcess( ply, str ) 
   
 	return ply:CheckLimit( str );
   
 end 
 
function GM:PlayerSpawnRagdoll( ply, model )

	return LimitReachedProcess( ply, "ragdolls" )
	
end

function GM:PlayerSpawnEffect( ply, model )

	return LimitReachedProcess( ply, "effects" )

end

function GM:PlayerSpawnVehicle( ply )

	return LimitReachedProcess( ply, "vehicles" )
	
end

function GM:PlayerSpawnSENT( ply, name )
		
	return LimitReachedProcess( ply, "sents" )	
	
end

function GM:PlayerSpawnNPC( ply, npc_type, equipment )

	if( ply:IsAdmin() ) then return true; end

	return LimitReachedProcess( ply, "npcs" )	
	
end
