-- File to hold GM commands
-- many others are in init.lua
-- consolidating Gm commands in various other places to here
-- clientside GM commands are in cl_init.lua

function GM:ShowHelp(ply)

	local PlyCharTable = CharTable[ply:FormatSteamID()]

	for k, v in pairs(PlyCharTable) do
		
		if( tonumber(k) != nil ) then
		
			umsg.Start("ReceiveChar", ply);
				umsg.Long(k);
				umsg.String(v["rpname"]);
				umsg.String(v["info.model"]);
			umsg.End();
		end
		
	end

	umsg.Start("playermenu", ply);
	umsg.End()
	
end

function GM:PlayerDisconnected( ply )

	NotifyAll_Console( ply:Name() .. " disconnected.");
	local rag = ents.GetByIndex( ply:GetNWInt("ragdoll") );
	if(rag != nil and rag:IsValid()) then
	
		rag:Remove()

	end
	
	-- Do door ownership check
	for k, v in pairs( Doors ) do
	
		tempDoor = ents.GetByIndex(v);
	
		-- if dc'er is the owner
		if ( tempDoor:GetNWString("owner") == ply:SteamID() ) then
			
			-- if there are coowners ONLINE, transfer ownership, remove from coowners, add old owner to offline
			if ( table.Count( tempDoor.coowners ) > 0 ) then
				tempDoor:SetNWString("owner", table.remove(tempDoor.coowners, 1) );
			end
		-- if dc'er is the coowner
		elseif ( table.HasValue( tempDoor.coowners, ply:SteamID() ) ) then
		
			for m, n in pairs( tempDoor.coowners ) do
			
				-- remove player from online coowners list, move to offline list.
				if ( n == ply:SteamID() ) then
					table.remove(tempDoor.coowners, m);
				end
			
			end
		
		end
	
	end

end

function GM:PlayerGiveSWEP(ply)

	if(ply:IsAdmin() or ply:IsSuperAdmin()) then return true; end
	return false; 
	
end

function GM:PlayerSpawnSWEP(ply, class)

	if(ply:IsAdmin() or ply:IsSuperAdmin()) then
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] dropped SWEP " .. class);
		return true;
	else		
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] attempted to drop SWEP " .. class);
		return false;
	end
	
end

function GM:PlayerSpawnSENT(ply, class)

	if(ply:IsAdmin() or ply:IsSuperAdmin()) then
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] spawned SENT " .. class);
		return true; 
	else
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] attempted to spawn SENT " .. class);
		return false;
	end

end

/* reallowed!
-- Disallows suicide
function GM:CanPlayerSuicide(ply)

	ply:ChatPrint("Suicide is not the answer.")
	return false
	
end
*/

function GM:PlayerSpawnProp( ply, mdl )
	
	if( ply:GetNWInt( "tiedup" ) == 1 ) then 
		return false; 
	end
	
	if( !LimitReachedProcess( ply, "props" ) ) then
		return false;
	end

	--[[if( IsBannedModel( mdl ) and not( ply:IsAdmin() or ply:IsSuperAdmin() ) ) then --Should restrict explosive props
		CAKE.Notify( ply, "This prop is banned" );
		return false;
	end ]]--
	
	return true;

end

-- called after spawnProp if it succeeded
function GM:PlayerSpawnedProp(ply, model, ent)


	if( ent:GetPhysicsObject():GetMass() > 400 ) then
		
		if(not(ply:GetAccField("tooltrust") == 1) and not( ply:IsAdmin() or ply:IsSuperAdmin()) ) then --Should restrict non tooltrusted players from spawning huge props (and probably from spamming them)
		
			CAKE.Notify( ply, "Prop is too big");
			ent:Remove();
			return;
		
		end
	
	end
	
	ent:SetNWString( "CreatorName", ply:Nick() );
	ent:SetNWString( "CreatorSteam", ply:SteamID() );
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] spawned " .. model);
	NotifyAll_Console( ply:Name() .. " spawned prop " .. model);
	
	CAKE.AddPropSave( ply, ent );
	
	--ply:SetNWInt( "props", ply:GetNWInt("props") + 1 );

end

function GM:DoPlayerDeath( ply, attacker, dmginfo )

	-- We don't want kills, deaths, nor ragdolls being made. Kthx.
	NotifyAll_Console( ply:Name() .. " was killed");
	
end

-- Prevents shooting items with the gravgun.
function GM:GravGunOnDropped( ply, ent )

	if( ply:KeyDown( IN_ATTACK ) ) then
		ent:GetPhysicsObject():EnableMotion( false );
		timer.Simple( .001, ent:GetPhysicsObject().EnableMotion, ent:GetPhysicsObject(), true );
	end

end

-- Prevents flinging items with the physgun
--[[
function GM:PhysgunDrop( ply, ent )

	if( ent:IsValid() and not ply:KeyDown( IN_ATTACK2 ) ) then
	
		ent:GetPhysicsObject():EnableMotion( false );
		timer.Simple( .001, ent:GetPhysicsObject().EnableMotion, ent:GetPhysicsObject(), true );
	
	end

end
]]--

-- Prevents punting items. Did I really need to say this?
function GM:GravGunPunt( ply ) 
	return false;
end

function GM:PlayerUse(ply, entity)
	/*
	if(CAKE.IsDoor(entity)) then
		local doorgroups = CAKE.GetDoorGroup(entity)
		for k, v in pairs(doorgroups) do
			if(table.HasValue(Teams[ply:Team()]["DoorGroup"], v)) then
				return false;
			end
		end
	end
	*/
	return self.BaseClass:PlayerUse(ply, entity);
end

-- Check door first, moving them would messup how the door system works, don't care to change position data.
--[[
function GM:PhysgunPickup( ply, ent )
	
	if( CAKE.IsDoor(ent) ) then return false; end
	if( ply:IsSuperAdmin() ) then return true; end
		
	return self.BaseClass:PhysgunPickup(ply,ent);

end
]]--

function LimitReachedProcess( ply, str ) 
   
 	return ply:CheckLimit( str );
   
end

/*---------------------------------------------------------
   Name: gamemode:PlayerSpawnNPC( ply, npc_type )
   Desc: Return true if player is allowed to spawn the NPC
---------------------------------------------------------*/
function GM:PlayerSpawnNPC( ply, npc_type, equipment )

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

	return LimitReachedProcess( ply, "npcs" )	
	
end

/*---------------------------------------------------------
   Name: gamemode:PlayerSpawnSENT( ply, name )
   Desc: Return true if player is allowed to spawn the SENT
---------------------------------------------------------*/
function GM:PlayerSpawnSENT( ply, name )
	
	if( ply:IsSuperAdmin() or ply:IsAdmin() ) then return true; end
	
	return LimitReachedProcess( ply, "sents" )	
	
end

/*---------------------------------------------------------
   Name: gamemode:PlayerSpawnVehicle( ply )
   Desc: Return true if it's allowed 
---------------------------------------------------------*/
function GM:PlayerSpawnVehicle( ply )

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

	return LimitReachedProcess( ply, "vehicles" )
	
end

/*---------------------------------------------------------
   Name: gamemode:PlayerSpawnEffect( ply, model )
   Desc: Return true if it's allowed 
---------------------------------------------------------*/
function GM:PlayerSpawnEffect( ply, model )

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

	return LimitReachedProcess( ply, "effects" )

end

 /*---------------------------------------------------------
   Name: gamemode:PlayerSpawnRagdoll( ply, model )
   Desc: Return true if it's allowed 
---------------------------------------------------------*/
function GM:PlayerSpawnRagdoll( ply, model )

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

	return LimitReachedProcess( ply, "ragdolls" )
	
end

-- hooks into GM:PlayerHurt, prevents their regen a while
local function catchDamage( ply, attacker, healthRemaining, damageDealt )

	ply:SetNWInt("lasthurt", CurTime() );

end
hook.Add( "PlayerHurt", catchDamage );


local function paperDollCatcher( ply, hitgroup, dmginfo )

	local hitName = "generic";
	
	if( hitgroup == HITGROUP_HEAD ) then
		hitName = "head";
	elseif( hitgroup == HITGROUP_CHEST ) then
		hitName = "chest";
	elseif( hitgroup == HITGROUP_STOMACH ) then
		hitName = "chest";
	elseif( hitgroup == HITGROUP_LEFTARM ) then
		hitName = "larm";
	elseif( hitgroup == HITGROUP_RIGHTARM ) then
		hitName = "rarm";
	elseif( hitgroup == HITGROUP_LEFTLEG ) then
		hitName = "lleg";
	elseif( hitgroup == HITGROUP_RIGHTLEG ) then
		hitName = "rleg";
	end

	umsg.Start("damageDone", ply);
		umsg.String( hitName );
		umsg.Short( dmginfo:GetDamage() );
	umsg.End();

end
-- wouldn't work!!!
--hook.Add( "ScalePlayerDamage", paperDollCatcher );

 /*--------------------------------------------------------- 
    Name: gamemode:PlayerTraceAttack( ) 
    Desc: A bullet has been fired and hit this player 
 		 Return true to completely override internals 
 ---------------------------------------------------------*/ 
 function GM:PlayerTraceAttack( ply, dmginfo, dir, trace ) 
   
 	if ( SERVER ) then 
 		paperDollCatcher( ply, trace.HitGroup, dmginfo )
 		GAMEMODE:ScalePlayerDamage( ply, trace.HitGroup, dmginfo ) 
 	end 
   
 	return false 
 end 