----------------------------
-- CakeScript (March 29, 2008)
-- by LuaBanana
--
-- Alpha Version
-- chat.lua
----------------------------

ChatCommands = {};
OOCDelay = 10;
local oldDelay = 10;
local allowDynamic = true;

-- used by admin_ooc to set the OOC delay
function CAKE.SetOOCDelay( amt )

	if( tonumber(amt) != nil ) then
		OOCDelay = tonumber(amt);
	end

end

function CAKE.AllowDynamicOOC( input )

	allowDynamic = input;

end

-- will be called on a timer, will reduce the OOC delay down to 10 seconds
function CAKE.CalcNewDelay()

	-- if enabled
	if( allowDynamic ) then
	
		-- if OOC is less than 10 seconds
		if( oldDelay <= 10 ) then
			-- if OOC less than 10, do nothing
			if( OOCDelay <= 10 ) then
				OOCDelay = 10;
				return;
			-- OOC not at ten, sync up
			else
				oldDelay = OOCDelay;
			end
			
		else
			-- either been increased by admin, or someone talked and it got bumped up
			-- do not decrease until we've encountered probable silience
			if( OOCDelay > oldDelay ) then
				oldDelay = OOCDelay;
			-- encountered silence, reduce the OOC delay by 1
			else
				oldDelay = oldDelay - 1;
				OOCDelay = oldDelay;
			end
		
		end
	
	end

end

function CAKE.AddChatCommand(cmd, func)

	local index = table.getn(ChatCommands) + 1;
	ChatCommands[index] = {};
	ChatCommands[index]["cmd"] = cmd;
	ChatCommands[index]["func"] = func;
	
end

-- If filter is false, sends to all players, else uses as player filter
-- text is text to send
-- channel is channel #
-- color is color to use
function CAKE.SendChat( filter, text, channel, color )

		--umsg.Start("AddChat"); -- no filter, sends to all
		--umsg.String( ply:Nick() .. ": [OOC] " .. text );
		--umsg.Short(2);
		--umsg.Vector( Vector(70,255,70) );
		--umsg.End();
		
		if( filter == false ) then
			filter = player.GetAll();
		end
		
		local textTwo = "";
		if( string.len(text) > 130 ) then
			textTwo = string.sub( text, 129 );
			text = string.sub( text, 1, 128 );
		end
		
		umsg.Start( "AddChat", filter );
		umsg.String( text );
		umsg.String( textTwo );
		umsg.Short( channel );
		umsg.Vector( color );
		umsg.End();
		
		Msg( text .. "\n");
end

function ChatTest(ply, text)

	-- in case I leave my testing command in, don't want idiots using it.
	if( !ply:IsSuperAdmin() ) then
		return "";
	end
	
	umsg.Start("TestDelta",ply);
	umsg.End();
	
	/*
	--Msg("Value is: " .. ply:GetNetworkedInt( "Count.props" ) .. "\n");
	ply:PrintMessage( HUD_PRINTCONSOLE, "Value is: " .. ply:GetCount("props") .. "\n");
	
	CAKE.LoadProps();
	
	local pos = ply:GetPos();
	ply:PrintMessage( HUD_PRINTCONSOLE, "X: " .. pos.x .. " Y: " .. pos.y .. " Z: " .. pos.z );
	
	umsg.Start("answer",ply);
	umsg.End();
	
	local traceVec = util.GetPlayerTrace( ply );
	local trace = util.TraceLine( traceVec );
	
	if(trace.HitNonWorld) then
			local target = trace.Entity;
			
		if( target:GetClass() == "prop_physics" ) then
			local min, max = target:WorldSpaceAABB();
			local offset = max - min;
			ply:PrintMessage( HUD_PRINTCONSOLE, "X: " .. offset.x .. " Y: " .. offset.y .. " Z: " .. offset.z );
		else
			ply:PrintMessage( HUD_PRINTCONSOLE, "Not a prop." );
		end
	end
	
	*/
	-- ply::PrintMessage( HUD_PRINTCONSOLE, " " );
	
	-- DUN REMOVE THIS YA NINNY
	return "";
end
CAKE.AddChatCommand("/test", ChatTest);

function ChatPassout(ply, text)

	if( ply:GetNWInt("ko") == 0 ) then

		ply:Knockout();
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] passed out.");
--		CAKE.Notify(ply, "To wakeup say /wakeup");
		ply:SetNWInt("ko", 1);
		
		/*
		function passoutDecrement()

			if( ply:GetNWInt("ko") > 1 ) then
				ply:SetNWInt("ko", ply:GetNWInt("ko")-1);
				timer.Simple(1, passoutDecrement);
			end
			
		end
		
		timer.Simple(1, passoutDecrement);
		*/
		
	end
	
	return "";

end
CAKE.AddChatCommand("/passout", ChatPassout);
CAKE.AddChatCommand("/sleep", ChatPassout);

function ChatWakeup(ply, text)

-- check for ko, if not ko'd will cause a respawn
	if( ply:GetNWInt("ko") == 1 ) then
		ply:Wakeup();
		ply:SetNWInt("ko", 0);
	else
		CAKE.Notify(ply, "Cannot wakeup yet, wait " .. ply:GetNWInt("ko") .. " second(s).");
	end
	
	--return "";

end
CAKE.AddChatCommand("/wakeup", ChatWakeup);
CAKE.AddChatCommand("/getup", ChatWakeup);


function DropCall(ply, text)

	ply:ConCommand("rp_dropweapon" );
	--return "";

end
CAKE.AddChatCommand("/drop", DropCall);
CAKE.AddChatCommand("/dropweapon", DropCall);
CAKE.AddChatCommand("/dropgun", DropCall);

function StripFirstSpace(text)

	if(string.sub(text,1,1) == " ") then
	
		return string.sub(text, 2, string.len(text));
		
	else
	
		return text;
		
	end
	
end

-- will be displayed to admins
function AdminChat(ply,text)

	local players = player.GetAll();
	local rp = RecipientFilter();
	
	for k, v in pairs(players) do
	
		if( v:IsAdmin() or v:IsSuperAdmin() ) then
		
			rp:AddPlayer( v );
			
		end
		
	end
	
	CAKE.SendChat( rp, ply:Nick() .. ": " .. text, 1, Vector(70,204,204) )
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (ADMIN): " .. text);

end
CAKE.AddChatCommand("@", AdminChat);

function OOCChat(ply, text)

	if((ply.LastOOC + OOCDelay) <= CurTime() or ply:IsAdmin() or ply:IsSuperAdmin()) then
	
		CAKE.SendChat( false, ply:Nick() .. ": [OOC] " .. text, 2, Vector(128,192,255) )
		
		-- about 33% chance of increasing OOC delay by 1 second per OOC done
		local goHigher = math.random(0,2);
		if( goHigher == 0 ) then
			OOCDelay = OOCDelay + 1;
		end
	
		ply.LastOOC = CurTime();
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (OOC): " .. text);
		
	else
	
		CAKE.Notify(ply, "Wait " .. math.Round(ply.LastOOC + OOCDelay - CurTime()) .. " seconds");
		--return "";
		
	end
	
	return "";
	
end
CAKE.AddChatCommand("/ooc", OOCChat);
CAKE.AddChatCommand("//", OOCChat);

function YellChat(ply, text)

	local players = player.GetAll();
	local rp = RecipientFilter();
	
	for k, v in pairs(players) do
	
		if(ply:GetPos():Distance(v:GetPos()) < 2000) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(ply:Nick() .. ": [YELL] " .. text);
			
		elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 800) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(ply:Nick() .. ": [YELL] " .. text);
			
		end
		
	end
	
	CAKE.SendChat( rp, ply:Nick() .. ": [YELL] " .. text, 1, Vector(0,215,127) )
	
	/*
	umsg.Start("AddChat",rp);
	umsg.String( ply:Nick() .. ": [YELL] " .. text );
	umsg.Short(1);
	umsg.Vector( Vector(255,52,47) );
	umsg.End();
	*/
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (YELL): " .. text);
	--return "";
	
end
CAKE.AddChatCommand("/y", YellChat);
CAKE.AddChatCommand("/yell", YellChat);

function WhisperChat(ply, text)

	local players = player.GetAll();
	local rp = RecipientFilter();
	
	for k, v in pairs(players) do
	
		if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 150) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(ply:Nick() .. ": [WHISPER] " .. text);
			
		elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 75) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(ply:Nick() .. ": [WHISPER] " .. text);
			
		end
		
	end
	
	CAKE.SendChat( rp, ply:Nick() .. ": [WHISPER] " .. text, 1, Vector(72,178,161) )
	
	/*
	umsg.Start("AddChat",rp);
	umsg.String( ply:Nick() .. ": [WHISPER] " .. text );
	umsg.Short(1);
	umsg.Vector( Vector(117,18,213) );
	umsg.End();
	*/
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (WHISPER): " .. text);
	--return "";
	
end
CAKE.AddChatCommand("/w", WhisperChat);
CAKE.AddChatCommand("/whisper", WhisperChat);

function LOOCChat(ply, text)

	local players = player.GetAll();
	local rp = RecipientFilter();
	
	for k, v in pairs(players) do
	
		if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 500) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(ply:Name() .. " | " .. ply:Nick() .. ": [LOCAL-OOC] " .. text);
			
		elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 400) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(ply:Name() .. " | " .. ply:Nick() .. ": [LOCAL-OOC] " .. text);
			
		end
		
	end
	
	CAKE.SendChat( rp, ply:Nick() .. ": [LOCAL-OOC] " .. text, 1, Vector(165,207,255) );
	
	/*
	umsg.Start("AddChat",rp);
	umsg.String( ply:Nick() .. ": [LOCAL-OOC] " .. text );
	umsg.Short(1);
	umsg.Vector( Vector(165,207,255) );
	umsg.End();
	*/
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (LOCALOOC): " .. text);
	--return "";
	
end
CAKE.AddChatCommand(".//", LOOCChat);
CAKE.AddChatCommand("[[", LOOCChat);

function PM(ply, text)

	local args = string.Explode(" ", text);
	
	local target = CAKE.SearchForPlayer(1, args[1]); -- checking by name
	
	if(target != nil and target:IsPlayer()) then -- Target found, is player
	
		local msg = table.concat(args, " ", 2, table.getn(args));
		--target:ChatPrint("[PM from " .. ply:Nick() .. "]: " .. msg);
		--ply:ChatPrint("[PM to " .. target:Nick() .. "]: " .. msg);
		
		CAKE.SendChat( ply, "[PM to " .. target:Nick() .. "]: " .. msg, 3, Vector(0,247,92) );
		
		/*
		umsg.Start("AddChat",ply);
		umsg.String( "[PM to " .. target:Nick() .. "]: " .. msg );
		umsg.Short(3);
		umsg.Vector( Vector(212,18,154) );
		umsg.End();
		*/
		
		CAKE.SendChat( target, "[PM from " .. ply:Nick() .. "]: " .. msg, 3, Vector(0,247,92) );
		
		/*
		umsg.Start("AddChat",target);
		umsg.String( "[PM from " .. ply:Nick() .. "]: " .. msg );
		umsg.Short(3);
		umsg.Vector( Vector(212,18,154) );
		umsg.End();
		*/
		
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] sent PM to " .. target:Name() .. " [" .. target:SteamID() .. "] saying: " .. text);
		return "";
		
	elseif(target == nil) then -- Target was not found
	
		CAKE.Notify(ply,"Cannot find target!");
		return "";
		
	elseif(target == "err") then -- More than one player of the same name
	
		CAKE.Notify(ply,"Multiple targets selected!");
		return "";
		
	end
	
	--return "";
	
end
CAKE.AddChatCommand("/pm", PM)
CAKE.AddChatCommand("/msg", PM)

function Me(ply, text)

	local players = player.GetAll()
	local rp = RecipientFilter();
	
	for k, v in pairs(players) do
	
		if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 500) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(" *** " .. ply:Nick() .. " " .. text);
			
		elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 400) then
		
			rp:AddPlayer( v );
			
			--v:ChatPrint(" *** " .. ply:Nick() .. " " .. text);
			
		end
		
	end
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (me): " .. text);
	
	CAKE.SendChat( rp, " *** " .. ply:Nick() .. " " .. text, 1, Vector(138,155,198) );
	
	/*
	umsg.Start("AddChat",rp);
	umsg.String( " *** " .. ply:Nick() .. " " .. text );
	umsg.Short(1);
	umsg.Vector( Vector(138,155,198) );
	umsg.End();
	*/
	--return "";
	
end
CAKE.AddChatCommand("/me", Me);

function chatIt(ply, text)

	local players = player.GetAll()
	local rp = RecipientFilter();
	
	for k, v in pairs(players) do
	
		if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 500) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(" ** " .. text);
			--CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (it): " .. text);
			
		elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 400) then
		
			rp:AddPlayer( v );
			--v:ChatPrint(" ** " .. text);
			--CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (it): " .. text);
		end
	end
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (it): " .. text);
	
	CAKE.SendChat( rp, " ** " .. text, 1, Vector(255,100,0) );
	
	/*
	umsg.Start("AddChat",rp);
	umsg.String( " ** " .. text );
	umsg.Short(1);
	umsg.Vector( Vector(255,100,0) );
	umsg.End();
	*/
	--return "";

end
CAKE.AddChatCommand("/it", chatIt);

function AnonChat(ply, text)

	local players = player.GetAll()
	local rp = RecipientFilter();
	
	for k,v in pairs(players) do
	
		if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 500) then
		
			rp:AddPlayer( v );
			--v:ChatPrint("??? " .. text);
			
		elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 400) then
		
			rp:AddPlayer( v );
			--v:ChatPrint("??? " .. text);
			
		end
	end
	
	CAKE.SendChat( rp, "??? " .. text, 1, Vector(22,196,246) );
	
	/*
	umsg.Start("AddChat",rp);
	umsg.String( "??? " .. text );
	umsg.Short(1);
	umsg.Vector( Vector(22,196,246) );
	umsg.End();
	*/
	--return "";
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (anon): " .. text);
	
end
CAKE.AddChatCommand("/an", AnonChat);
CAKE.AddChatCommand("/?", AnonChat);

function JobChat(ply, text)

	ply:ConCommand("rp_job " .. text );
	
end
CAKE.AddChatCommand("/job", JobChat);
CAKE.AddChatCommand("/title", JobChat);

function GM:PlayerSay(ply,text,toall)

		--ply:PrintMessage( HUD_PRINTCONSOLE, "Received is: " .. text .. "\n");

		for k, v in pairs(ChatCommands) do
		
			if( string.sub(text, 1, string.len(v["cmd"])) == v["cmd"] ) then
				--return v["func"](ply, StripFirstSpace(string.sub(text, string.len(v["cmd"]) + 1, string.len(text))));
				v["func"](ply, StripFirstSpace(string.sub(text, string.len(v["cmd"]) + 1, string.len(text))));
				return "";
			end
			
		end
		
		-- If we got this far, its none of the above, this is IC chat.
		local players = player.GetAll();
		local rp = RecipientFilter();
		
		for k, v in pairs(players) do
		
			if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 400) then
				--v:ChatPrint("ChatPrint: ".. ply:Nick() .. ": " .. text);
				rp:AddPlayer( v );
				
			elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 300) then
				--v:ChatPrint("ChatPrint: ".. ply:Nick() .. ": " .. text);
				rp:AddPlayer( v );
				
			end
			
		end
		
		CAKE.SendChat( rp, ply:Nick() .. ": " .. text, 1, Vector(227,246,255) );
		
		/*
		umsg.Start("AddChat",rp);
		umsg.String( ply:Nick() .. ": " .. text);
		umsg.Short(1);
		umsg.Vector( Vector(255,255,255) );
		umsg.End();
		*/
		
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said: " .. text);

		return "";
		
end

function Broadcast(ply, text)

	if(Teams[ply:Team()]["CanBroadcast"] == true) then
	
		/*
		local players = player.GetAll();
		
		for k, v in pairs(players) do
		
			v:ChatPrint("[BROADCAST] " .. ply:Nick() .. ": " .. text);
		end
		*/
		
		CAKE.SendChat( false, "[BROADCAST] " .. ply:Nick() .. ": " .. text, 1, Vector(127,189,113) );
		
		/*
		umsg.Start("AddChat"); -- no filter, all players
		umsg.String( "[BROADCAST] " .. ply:Nick() .. ": " .. text );
		umsg.Short(1);
		umsg.Vector( Vector(127,189,113) );
		umsg.End();
		*/
		
		CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (BC): " .. text);	
	end

	--return "";
	
end
CAKE.AddChatCommand("/bc", Broadcast);

function Radio(ply, text)

	local players = player.GetAll();
	local rp = RecipientFilter();
	local station = ply:GetNWFloat("radioChannel");
	
	-- means they have no radio
	if( station == 0 ) then
		CAKE.Notify( ply, "You do not have a radio." );
		return;
	end

	for k, v in pairs(players) do
	
		if( v:GetNWFloat("radioChannel") == station ) then
		
			rp:AddPlayer( v );
		
		end
	
	end
	
	CAKE.SendChat( rp, "[RADIO] " .. ply:Nick() .. ": " .. text, 1, Vector(123,184,0) );

	rp = RecipientFilter();

	for k, v in pairs(players) do
		
		--if(!table.HasValue(heardit, v)) then
			if(ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 500) then
		
				rp:AddPlayer( v );
				--v:ChatPrint(ply:Nick() .. ": " .. text);
			
			elseif(!ply:CanTraceTo(v) and ply:GetPos():Distance(v:GetPos()) < 300) then
			
				rp:AddPlayer( v );
				--v:ChatPrint(ply:Nick() .. ": " .. text);
				
			end
		--end
		
	end

	CAKE.SendChat( rp, ply:Nick() .. ": " .. text, 1, Vector(255,255,255) );
	
	CAKE.DayLog(ply:Name() .. " [" .. ply:SteamID() .. "] said (RADIO): " .. text);
	--return "";

end
CAKE.AddChatCommand("/r", Radio)
CAKE.AddChatCommand("/radio", Radio)

function ConsoleCommandChat(ply, text)

	ply:ConCommand("rp_" .. text .. "\n");
	if( ply:IsAdmin() or ply:IsSuperAdmin() ) then
		ply:ConCommand("admin_" .. text .. "\n");
	end
	--return "";
	
end
CAKE.AddChatCommand("!", ConsoleCommandChat);

function EventText(ply, text)

	if( ply:IsAdmin() or ply:IsSuperAdmin() ) then
		CAKE.SendChat( false, "*EVENT* " .. text, 1, Vector(128,128,237) );
	end
	
end
CAKE.AddChatCommand("/ev", EventText);

/* conflicts with /admin till command detection system is revamped
function DeathCall(ply, text)

	ply:ConCommand("rp_acceptdeath");
	--return "";

end
CAKE.AddChatCommand("/ad", DeathCall);
*/
