
TS.NextThink = 0;

function GM:Think()

	if( CurTime() < TS.NextThink ) then
	
		return;
	
	end

	TS.NextThink = CurTime() + .1;

	for k, v in pairs( player.GetAll() ) do

		if( v:GetTable().Initialized ) then
		
			if( v:Alive() ) then
		
				if( v:GetPlayerConscious() and v:GetPlayerConsciousness() <= 0 ) then
				
					v:Unconscious();
				
				end
				
			end
			
			--Drunk related shit
			if( v:GetPlayerDrunkMul() > 0 ) then
			
				if( CurTime() - v:GetTable().LastDrunkMulUpdate > 100 ) then
			
					v:GetTable().LastDrunkMulUpdate = CurTime();
					v:SetPlayerDrunkMul( math.Clamp( v:GetPlayerDrunkMul() - .11, 0, v:GetPlayerDrunkMul() ) );
				
				end
				
				if( CurTime() - v:GetTable().LastDrunkWalkUpdate > .8 ) then
				
					v:GetTable().LastDrunkWalkMul = math.random( -35 * v:GetPlayerDrunkMul(), 35 * v:GetPlayerDrunkMul() );
					v:GetTable().LastDrunkWalkUpdate = CurTime();
		
				end
				
				if( v:KeyDown( IN_FORWARD ) or v:KeyDown( IN_BACKWARD ) ) then
				
					v:SetVelocity( v:GetRight() * v:GetTable().LastDrunkWalkMul );
					
				end
				
				if( v:GetPlayerDrunkMul() >= 1.6 ) then
				
					v:SetPlayerDrunkMul( .6 );
					v:CallEvent( "HangOver" );
					v:SetPlayerConsciousness( math.Clamp( v:GetPlayerConsciousness() - 80, 0, 100 ) );
					v:Unconscious();
				
				end
				
			end
		
			--Consciousness related shit
			if( v:GetPlayerConscious() ) then
			
				if( CurTime() - v:GetTable().LastConsciousRecover > 5 and v:GetPlayerConsciousness() < 100 ) then
					v:SetPlayerConsciousness( math.Clamp( v:GetPlayerConsciousness() + 1, 0, 100 ) );
					v:GetTable().LastConsciousRecover = CurTime();
				end
			
			else
			
				if( CurTime() - v:GetTable().LastConsciousRecover > 1 and v:GetPlayerConsciousness() < 100 ) then
					v:SetPlayerConsciousness( math.Clamp( v:GetPlayerConsciousness() + 1, 0, 100 ) );
					v:GetTable().LastConsciousRecover = CurTime();
				end
				
				if( v:Alive() and v:Health() <= 0 ) then
				
					v:GetTable().BypassUnconscious = true;
					v:Die();
				
				end				
			
			end
			
			--Stance related shit
			if( v:GetTable().StanceSit ) then
	
				if( ( v:GetTable().StanceSitPlayerPos - v:GetPos() ):Length() > 3 ) then
	
					v:SnapOutOfStance();
				
				elseif( v:GetTable().StanceSitEnt:GetClass() ~= "worldspawn" and ( not v:GetTable().StanceSitEnt or not v:GetTable().StanceSitEnt:IsValid() ) ) then
	
					v:SnapOutOfStance();
				
				elseif( v:GetTable().StanceSitEntPos ~= v:GetTable().StanceSitEnt:GetPos() ) then
	
					v:SnapOutOfStance();
				
				end
	
			elseif( v:GetTable().StanceGroundSit ) then
	
				if( ( v:GetTable().StanceGroundSitPos - v:GetPos() ):Length() > 3 ) then
	
					v:SnapOutOfStance();
					
				end
				
			elseif( v:GetTable().StanceLean ) then
	
				if( ( v:GetTable().StanceLeanPos - v:GetPos() ):Length() > 3 ) then
	
					v:SnapOutOfStance();
					
				end
				
			elseif( v:GetTable().StanceATW ) then
			
				if( ( v:GetTable().StanceATWPlayerPos - v:GetPos() ):Length() > 3 ) then
	
					v:SnapOutOfStance();
				
				elseif( v:GetTable().StanceATWEnt:GetClass() ~= "worldspawn" and ( not v:GetTable().StanceATWEnt or not v:GetTable().StanceATWEnt:IsValid() ) ) then
	
					v:SnapOutOfStance();
				
				elseif( v:GetTable().StanceATWEntPos ~= v:GetTable().StanceATWEnt:GetPos() ) then
	
					v:SnapOutOfStance();
				
				end			
			
			end
	
			--Holster/unholster related shit
			local weap = v:GetActiveWeapon();
			
			if( weap:IsValid() ) then
			
				local class = weap:GetClass();
				
				if( v:GetTable().HandPickUpSent and v:GetTable().HandPickUpSent:IsValid() ) then
					if( class ~= "ts2_hands" ) then
						v:RemoveHandPickUp();
					end
				end
				
				if( v:GetTable().RightHandEntity and v:GetTable().RightHandEntity:IsValid() ) then
				
					if( class ~= "ts2_hands" ) then
						v:GetTable().RightHandEntity:Remove();
						v:GetTable().RightHandEntity = nil;
					end
				
				end
			
				if( v:GetTable().LastWeapon ~= class ) then
				
					v:DropTempWeapon();
		
					v:HandleWeaponChangeTo( class );
				
				end
			
			end
		
			--Process bar related shit
			for n, m in pairs( v:GetTable().ProcessBars ) do
			
				if( m.ThinkFunc and CurTime() > m.NextThink ) then
				
					local done = false;
					
					if( CurTime() > m.Time + m.TimeDone ) then
						done = true;
					end
				
					m.ThinkFunc( v, done );
				
					m.NextThink = CurTime() + m.ThinkDelay;
				
				end
				
				if( not m.ThinkFunc ) then
				
					if( CurTime() > m.Time + m.TimeDone and not m.Linger ) then
						DestroyProcessBar( n, v );
						player.GetByID( k ):GetTable().ProcessBars[n] = nil;
					end
				
				end
			
			end
			
			--Bleeding related shit
			if( v:GetPlayerBleeding() and v:Alive() ) then
			
				if( CurTime() - v:GetTable().LastBleedDmg > 3 ) then
				
					local dmg = v:GetTable().BleedingDmgPerSec;
					local incdmg = v:GetTable().BleedingIncDmgPerSec;
					
					local mul = .7;
					
					dmg = dmg * mul;
				
					if( dmg < 1 or v:GetTable().BleedingHealthCatcher > 0 ) then
					
						v:GetTable().BleedingHealthCatcher = v:GetTable().BleedingHealthCatcher + dmg;
					
						if( v:GetTable().BleedingHealthCatcher > 1 ) then
						
							v:SetHealth( v:Health() - math.ceil( v:GetTable().BleedingHealthCatcher ) );
							v:GetTable().BleedingHealthCatcher = 0;
						
						end
					
					else
					
						v:SetHealth( v:Health() - dmg );
					
					end
				
					v:SetPlayerConsciousness( math.Clamp( v:GetPlayerConsciousness() - incdmg, 0, 100 ) );
					
					if( v:Health() <= 0 ) then
					
						v:GetTable().BypassUnconscious = true;
						v:Die();
					
					end
					
					v:GetTable().LastBleedDmg = CurTime();
				
				end
				
				if( CurTime() - v:GetTable().LastBleedDecal > 2 ) then
			
					v:BleedOutADecal();
					v:GetTable().LastBleedDecal = CurTime();
			
				end
			
			end
		
			--Sprint bar related shit
			if( v:KeyDown( IN_SPEED ) and v:GetVelocity():Length() > 60 and v:GetPlayerCanSprint() ) then
			
				if( v:GetPlayerSprint() > 0 ) then
			
					if( not v:GetTable().LastSprintDegrade ) then
					
						v:GetTable().LastSprintDegrade = CurTime();
					
					elseif( CurTime() - v:GetTable().LastSprintDegrade > 1 ) then
					
						if( v:IsOWElite() ) then
						
							v:SetPlayerSprint( math.Clamp( v:GetPlayerSprint() - TS.SprintDegradeTable[v:GetPlayerEndurance()] * .3, 0, 100 ) );
							v:GetTable().LastSprintDegrade = CurTime();
						
						else
						
							v:SetPlayerSprint( math.Clamp( v:GetPlayerSprint() - TS.SprintDegradeTable[v:GetPlayerEndurance()], 0, 100 ) );
							v:GetTable().LastSprintDegrade = CurTime();
							
						end
					
					end
					
				else
			
					v:ComputePlayerSpeeds();
				
				end
				
			elseif( v:GetPlayerSprint() < 100 ) then --Regenerate sprint
		
				if( not v:GetTable().LastSprintFill ) then
				
					v:GetTable().LastSprintFill = CurTime();
				
				elseif( CurTime() - v:GetTable().LastSprintFill > 2 ) then
				
					v:SetPlayerSprint( math.Clamp( v:GetPlayerSprint() + TS.SprintFillTable[v:GetPlayerEndurance()], 0, 100 ) );
					v:GetTable().LastSprintFill = CurTime();
				
					v:ComputePlayerSpeeds();
				
				end
			
			
			end
			--End sprint bar related shit
	
		end	
	
	end

end

function GM:PlayerSay( ply, text )

	if( not ply:GetTable().Initialized ) then return ""; end
 
	local correctcmd = nil;
	local crntlen;
	
	for k, v in pairs( TS.ChatCommands ) do
	
		local len = string.len( v.cmd );
		local chatsub = string.sub( text, 1, len );
		
		if( string.lower( chatsub ) == string.lower( v.cmd ) ) then
		
			if( correctcmd ) then
			
				if( crntlen < len ) then
				
					correctcmd = k;
					crntlen = len;
				
				end
			
			else
			
				correctcmd = k;
				crntlen = len;
		
			end
		
		end
	
	end
	
	if( correctcmd ) then
	
		local ret = ( TS.ChatCommands[correctcmd].cb( ply, TS.ChatCommands[correctcmd].cmd, string.sub( text, crntlen + 1 ) ) or "" );	
	
		if( ret ~= "" and ret ~= " " ) then
		
			if( CurTime() < ply:GetTable().NextTimeCanChat ) then
				return "";
			end	
		
			ply:GetTable().NextTimeCanChat = CurTime() + TS.ChatDelay;
				
			return "(" .. ply:GetRPName() .. ") " .. ply:SayGlobalChat( ret );
		
		end
	
	else
	
		ply:SayLocalChat( text );
	
	end
	
	return "";

end

function GM:ShowSpare1( ply )

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

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

end

function GM:ShowSpare2( ply )

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

	if( CurTime() - ply:GetTable().LastF4 < 1 ) then
		return;
	end
	
	ply:GetTable().LastF4 = CurTime();

	local trace = { }
	trace.start = ply:EyePos();
	trace.endpos = trace.start + ply:GetAimVector() * 90;
	trace.filter = ply;
	
	local tr = util.TraceLine( trace );
	
	if( tr.Entity:IsValid() ) then
	
		if( tr.Entity:IsDoor() ) then
		
			if( ply:CanOwnDoor( tr.Entity ) ) then
		
				ply:OpenDoorMenu( tr.HitPos, tr.Entity );
			
			else
			
				ply:PrintMessage( 3, "You cannot own this door.  The property is either unownable or you must find another door." );
			
			end
			
		elseif( tr.Entity:IsPlayer() or tr.Entity:GetNWFloat( "IsRagDoll" ) == 1 ) then
		
			ply:OpenPlayerMenu( tr.HitPos, tr.Entity );
		
		end
	
	end

end

function GM:ShowHelp( ply )

	if( not ply:GetTable().Initialized ) then
		return;
	end
	
	if( CurTime() - ply:GetTable().LastHelp < 1 ) then
		return;
	end
	
	ply:GetTable().LastHelp = CurTime();		
	
	umsg.Start( "SH", ply ); umsg.End();

end


function GM:PhysgunPickup( ply, ent )

	return ply:CanPhysGunPickup( ent );

end

function GM:CanTool( ply, tr, mode )

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

	return ply:CanToolThis( tr.Entity, mode );
	
end

function GM:PlayerSpawnProp( ply, model ) 

	if( not ply:GetTable().Initialized ) then return false; end
	
	if( not TS.PropRecords[ply:SteamID()] ) then
		TS.PropRecords[ply:SteamID()] = 0;
	end
	
	-- if player is admin, he can't spawn more then 60 props 
	if( ply:CanUseCommand() and TS.PropRecords[ply:SteamID()] >= 60 ) then
	
		return false
		
	end	
	
	-- if ply has tooltrust and has 20 props spawned, he can't spawn anymore
	if( ply:HasTT() and TS.PropRecords[ply:SteamID()] >= 20 ) then
	
		return false	
		
	end
	
	-- if player doesn't have TT he can't spawn more than 10 props
	if( !ply:HasTT() and TS.PropRecords[ply:SteamID()] >= 10 ) then
	
		return false
		
	end	
	
	return true;

end

function GM:PlayerSpawnedProp( ply, model, ent ) 

	TS.PropRecords[ply:SteamID()] = TS.PropRecords[ply:SteamID()] + 1;
	
	ent:GetTable().Creator = ply;
	ent:GetTable().CreatorSteamID = ply:SteamID();
	ent:GetTable().CreatorIsRick = ply:IsAwesome();
	ent:GetTable().CreatorIsSuperAdmin = self:IsSuperAdmin()
	ent:GetTable().CreatorHasTT = ply:HasTT();
	--ent:GetTable().CreatorHasBasicTT = ply:HasBasicTT();
	
	ent:SetNWString( "CS", ent:GetTable().Creator:GetRPName() .. " (" .. ent:GetTable().CreatorSteamID .. ")" );
	
	if( ply:IsAwesome() ) then
		TS.PrintMessageAll( 2, "** [PROP]" .. ply:Nick() .. " spawned: " .. model );
	end

end

function GM:PlayerSpawnSENT( ply, class ) 

	if( not ply:GetTable().Initialized ) then return false; end
	
	if( ply:IsAdmin() or ply:IsAwesome() ) then return true; end
	
	return false;

end

function GM:EntityRemoved( ent )

	if( not ent or not ent:IsValid() ) then return; end

	if( ent and ent.GetTable and ent:GetTable().CreatorSteamID ) then
		if( TS.PropRecords and TS.PropRecords[ent:GetTable().CreatorSteamID] ) then
			TS.PropRecords[ent:GetTable().CreatorSteamID] = TS.PropRecords[ent:GetTable().CreatorSteamID] - 1;
		end
	end
	
end

function GM:KeyPress( ply, key )

	if( key == IN_JUMP ) then
	
		if( ply:OnGround() and ply:WaterLevel() < 4 ) then
			ply:SetPlayerSprint( math.Clamp( ply:GetPlayerSprint() - TS.JumpDegradeTable[ply:GetPlayerEndurance()], 0, 100 ) );
		end
		
	end
	

	if( CurTime() - ply:GetTable().LastKeyPress < .8 ) then
	
		return;
	
	end
	
	ply:GetTable().LastKeyPress = CurTime();
	
	if( key == IN_USE ) then
	
		if( ply:IsTied() ) then return; end
	
		local trace = { }
		trace.start = ply:EyePos();
		trace.endpos = trace.start + ply:GetAimVector() * 90;
		trace.filter = ply;
		
		local tr = util.TraceLine( trace );
		
		if( tr.Entity and tr.Entity:IsValid() ) then
		
			if( tr.Entity:IsDoor() ) then
			
				if( not tr.Entity:GetTable().Locked ) then
			
					if( tr.Entity:GetTable().DoorFlags and string.find( tr.Entity:GetTable().DoorFlags, "s" ) and tr.Entity:GetTable().ItemData ) then
					
					if( tr.Entity:GetTable().Unlocked ) then
						CreateActionMenu( tr.Entity:GetTable().DoorName or "", ply, tr.HitPos - Vector( 0, 0, 10 ) );
							SetActionMenuEntity( tr.Entity );
							--AddActionOption( "Look inside", "eng_lookinsidemapstorage", 1 );
						EndActionMenu();
					end
					
					end	
					
				end
				
				if( tr.Entity:GetTable().DoorFlags and string.find( tr.Entity:GetTable().DoorFlags, "n" ) and ply:IsCombine() or ply:HasInventory( "Metrocop Jacket" ) ) then
				
					--tr.Entity:Fire( "open", "", 0 );
					tr.Entity:Fire( "toggle", "", 0 );
				
				end
			
			end
		
			
			if( tr.Entity:GetNWInt( "IsLootableRagdoll" ) == 1 ) then
			
				CreateActionMenu( "Options", ply, tr.HitPos - Vector( 0, 0, 10 ) );
						SetActionMenuEntity( tr.Entity );
						AddActionOption( "Identify Corpse", "eng_ib" )
					if( tr.Entity:GetNWInt( "IsLootable"  ) == 1 ) then
						AddActionOption( "Loot Body", "eng_loot" );
					else
						AddActionOption( "This body has already been looted", "" );
					end	
				EndActionMenu();
			
			end
		
		
		end
		
	end

end

-- Ragdoll --
-- 10 - head
-- 1 - torso
-- 2, 6, 7, 3, 4, 5, 11, 12, 13, 14, 9, 8 - arms/legs

function GM:EntityTakeDamage( ent, inflictor, attacker, amount ) 

	if( ent:GetTable().IsPlayerRagdoll and inflictor:IsPlayer() and ent:GetTable().Player:Alive() ) then
	
		local tr = inflictor:GetEyeTrace();
		local ply = ent:GetTable().Player;
		
		local weap = inflictor:GetActiveWeapon();
		
		if( weap:IsValid() and weap:GetTable().Primary and weap:GetTable().Primary.Damage ) then
			
			local dmginfo = { Dmg = weap:GetTable().Primary.Damage };
			
			dmginfo.GetDamage = function( self )
				return self.Dmg;
			end
			
			dmginfo.SetDamage = function( self, val )
				self.Dmg = val;
			end
			
			if( tr.Entity == ent ) then
			
				if( tr.PhysicsBone == 10 ) then
				
					ply:ScaleDamageFromAttack( inflictor, weap, HITGROUP_HEAD, dmginfo );
				
				elseif( tr.PhysicsBone == 1 ) then
				
					ply:ScaleDamageFromAttack( inflictor, weap, HITGROUP_STOMACH, dmginfo );
				
				elseif( ( tr.PhysicsBone >= 11 and tr.PhysicsBone <= 13 ) or tr.PhysicsBone == 14 or tr.PhysicsBone == 9 or tr.PhysicsBone == 8 ) then
				
					ply:ScaleDamageFromAttack( inflictor, weap, HITGROUP_RIGHTLEG, dmginfo );
				
				else
				
					ply:ScaleDamageFromAttack( inflictor, weap, HITGROUP_RIGHTARM, dmginfo );
				
				end
				
				ply:TakeHealth( dmginfo:GetDamage() );
			
			end
			
		end
	
	end

	if( ent:GetModel() == "models/props_c17/door01_left.mdl" ) then
	
		local weap = inflictor:GetActiveWeapon();
		
		if( weap:IsValid() and weap:GetTable().Primary and weap:GetTable().Primary.DoorBreach ) then
		
			local trace = { }
			trace.start = inflictor:EyePos();
			trace.endpos = trace.start + inflictor:GetAimVector() * ( ent:GetPos() - inflictor:GetPos() ):Length();
			trace.filter = inflictor;
			
			local tr = util.TraceLine( trace );
			
			local knob = ent:GetPos() - Vector( 0, 0, 10 ) - ent:GetAngles():Right() * 42;
		
			if( ( tr.HitPos - knob ):Length() < 3 ) then
			
				--Lock breaking code
				ent:Fire( "unlock", "", 0 );
				ent:GetTable().KnobBroken = true;
				ent:EmitSound( Sound( "doors/door_metal_thin_close2.wav" ) );
				if( ent:GetTable().BoobyTrapped ) then
					ent:SplodeDoor();	
				end
			
			end
		
		end
	
	end
	
end

function TS.CIDIsTaken( cid )

	for k, v in pairs( TS.CIDs ) do
	
		if( v == cid ) then
			return true;
		end
	
	end
	
	return false;

end

function GM:InitPostEntity()

	TS2InitializedOnce = true;

	TS.LoadMapData();

	local weaps = weapons.GetList();
	for k, v in pairs( weaps ) do
	ITEM = nil; ITEM = { }; ITEM.ID = v.ClassName; ITEM.Flags = "w"; ITEM.UseDelay = 1; ITEM.PickupDelay = .1; ITEM.Name = v.PrintName or ""; ITEM.Description = ""; ITEM.Model = v.WorldModel or ""; ITEM.CamPos = v.IconCamPos or Vector( 0, 0, 0 ); ITEM.LookAt = v.IconLookAt or Vector( 0, 0, 0 ); ITEM.FOV = v.IconFOV or 90; ITEM.Width = v.ItemWidth or 1; ITEM.Height = v.ItemHeight or 1; ITEM.Price = v.Price or 0;
	ITEM.Pickup = function( self )		
	self.Owner:Give( self.ID );		
	end		
	ITEM.Drop = function( self ) 
	if( not self.Owner:HasMultipleCopiesOfItem( self.ID ) ) then
		self.Owner:StripWeapon( self.ID );	
	end		
	end		
	ITEM.Use = ITEM.Use or function() end
	TS.ItemsData[ITEM.ID] = ITEM;		
	end
	TS.FormatedWeaponsToItems = true; timer.Simple( 2, function() TS.WeaponGivingDelay = false; end );
	

end



