//
//  ___  ___   _   _   _    _     __  __ ____  __ __
// |_ _|| __| / \ | \_/ |  / \   /  \/ /| _  \ \ V /
//  | | | _| | o || \_/ | | o | / /\  / ||_| |  \ /
//  |_| |___||_n_||_| |_| |_n_|/_/  \/  |____/  |_|   2010
//										 
//
//########################################
//#####CORE CODE#### Don't touch this!!!##
//########################################
local X = -50
local Y = -100
local W = 100
local H = 200
local KeyPos =	{	{X+5, Y+100, 25, 25, -2.2, 3.45, 1.3, -0},
					{X+37.5, Y+100, 25, 25, -0.6, 1.85, 1.3, -0},
					{X+70, Y+100, 25, 25, 1.0, 0.25, 1.3, -0},

					{X+5, Y+132.5, 25, 25, -2.2, 3.45, 2.9, -1.6},
					{X+37.5, Y+132.5, 25, 25, -0.6, 1.85, 2.9, -1.6},
					{X+70, Y+132.5, 25, 25, 1.0, 0.25, 2.9, -1.6},

					{X+5, Y+165, 25, 25, -2.2, 3.45, 4.55, -3.3},
					{X+37.5, Y+165, 25, 25, -0.6, 1.85, 4.55, -3.3},
					{X+70, Y+165, 25, 25, 1.0, 0.25, 4.55, -3.3},

					{X+5, Y+67.5, 40, 25, -2.2, 4.25, -0.3, 1.6},
					{X+55, Y+67.5, 40, 25, 0.3, 1.65, -0.3, 1.6}
				}
-- HUD color
hudkeypadcolor = Color(255,50,20,200)
local hudkeypadred = CreateClientConVar( "hudkeypad_red", tostring(hudkeypadcolor.r), true, false )
local hudkeypadgreen = CreateClientConVar( "hudkeypad_green", tostring(hudkeypadcolor.g), true, false )
local hudkeypadblue = CreateClientConVar( "hudkeypad_blue", tostring(hudkeypadcolor.b), true, false )
local hudkeypadalpha = CreateClientConVar( "hudkeypad_alpha", tostring(hudkeypadcolor.a), true, false )
-- Font color
fontkeypadcolor = Color(255,255,255,255)
local fontkeypadred = CreateClientConVar( "fontkeypad_red", tostring(fontkeypadcolor.r), true, false )
local fontkeypadgreen = CreateClientConVar( "fontkeypad_green", tostring(fontkeypadcolor.g), true, false )
local fontkeypadblue = CreateClientConVar( "fontkeypad_blue", tostring(fontkeypadcolor.b), true, false )
local fontkeypadalpha = CreateClientConVar( "fontkeypad_alpha", tostring(fontkeypadcolor.a), true, false )
-- Font
local keypadfont = CreateClientConVar( "cl_keypadfont", "HudSelectionText", true, false )
-- Show keypad index
local keypadindex = CreateClientConVar( "show_keypadindex", "1", true, false )
local keypadindexdistance = CreateClientConVar( "keypadindex_distance", "2500", true, false )
-- Notifies, if a key was pressed
local keypadnotify = CreateClientConVar( "keypad_notify", "1", true, false )
local keypadnotifystyl = CreateClientConVar( "keypad_notify_styl", "0", true, false )
-- Keypad cracker sounds
local keypadsounds = CreateClientConVar( "keypad_sounds", "1", true, false )
---------------------------------------
local function keypadcount()
	count = 0
	for _,key in pairs(ents.GetAll()) do
		if ( key:GetClass() == "sent_keypad" || key:GetClass() == "sent_keypad_wire" ) then
			count = count + 1
		end
	end
	return count
end
concommand.Add("cl_show_keypad_hud", function()
	if (!ConVarExists("cl_keypad_cracker")) then
		CreateClientConVar( "cl_keypad_cracker", "0", false, false )
	end
	if (GetConVarNumber("cl_keypad_cracker") == 0) then
		RunConsoleCommand("cl_keypad_cracker", "1")
		LocalPlayer():EmitSound("buttons/button9.wav")
		LocalPlayer():EmitSound("HL1/fvox/activated.WAV")
		GAMEMODE:AddNotify("Found ".. keypadcount() .." keypad/s!", NOTIFY_GENERIC, 3)
	else
		RunConsoleCommand("cl_keypad_cracker", "0")
		LocalPlayer():EmitSound("buttons/button9.wav")
		LocalPlayer():EmitSound("HL1/fvox/deactivated.WAV")
		GAMEMODE:AddNotify("Keypad cracker offline!", NOTIFY_GENERIC, 3)

	end
	timer.Simple(0.2, function() 
		LocalPlayer():PrintMessage( HUD_PRINTTALK, "Client cvar 'cl_keypad_cracker' changed to ".. GetConVarNumber("cl_keypad_cracker") .."" )
	end)
end)
local function Think()
	for _,pad in pairs(ents.GetAll()) do
		if ( ValidEntity( pad ) ) then
			local class = pad:GetClass()
			if ( class == "sent_keypad" || class == "sent_keypad_wire" ) then
				if (pad:GetNetworkedBool("keypad_secure")) then
					pad.Number = pad:GetNetworkedInt("keypad_num")
				if (pad.Number != 0) then
					pad.TextLength = string.len(pad.Number)
				else
					pad.TextLength = 0
				end
				if ( pad.TextLengthLast == nil ) then pad.TextLengthLast = 0 end
				if (pad.TextLength != pad.TextLengthLast) then
					if (pad.PasswordArg == nil) then pad.PasswordArg = {} end
					for _,p in pairs(player.GetAll()) do
						if ( ValidEntity( p ) ) then
							local Distance = (p:GetShootPos() - pad:GetPos()):Length()
							if (Distance < 250) then
								ProtectedPassword(pad, p)
							end
						end
					end
					if (pad.keyPressed != nil) then
						if (pad.keyPressed <= 9) then
							if (pad.TextLength == 0) then pad.TextLength = 1 end
							pad.PasswordArg[pad.TextLength] = pad.keyPressed
						end
					end
					pad.TextLengthLast = string.len(pad:GetNetworkedInt("keypad_num"))
				end	
				if ( pad:GetNWBool( "keypad_access" ) && pad:GetNWBool( "keypad_showaccess" ) ) then
					if (pad.PasswordArg == nil) then return end
					pad.Password = tostring(pad.PasswordArg[1])..tostring(pad.PasswordArg[2])..tostring(pad.PasswordArg[3])..tostring(pad.PasswordArg[4])
					if string.find(pad.Password, "nilnilnilnil") then
						replace = string.Replace(pad.Password,"nilnilnilnil","")
						pad.Password = replace .." ..ERROR!"
					elseif string.find(pad.Password, "nil") then
						replace = string.Replace(pad.Password,"nil","")
						pad.Password = replace .." ..maybe!?"
					end
					if (!pad.Notified) then
						pad.Notified = true
						timer.Simple(5, function() pad.Notified = false end)
						if (GetConVarNumber("cl_keypad_cracker") == 1) then
							chat.AddText(
								"[Keypad cracker] ",
								Color(255,255,255), "Keypad index: ",
								Color(255,0,0), "".. pad:EntIndex() .."",
								Color(255,255,255), ". Keypad code: ",
								Color(0,255,0), "".. pad.Password .."")
							chat.PlaySound()
							if (GetConVarNumber("keypad_sounds") == 1) then
								LocalPlayer():EmitSound("../sound/4keypad_cracker/spot.wav")
							else
								LocalPlayer():EmitSound("buttons/blip1.wav")
							end
							if (GetConVarNumber( "keypad_notify" ) == 1) then
								GAMEMODE:AddNotify( "Successfully confirmed: ".. pad.Password, GetConVarNumber("keypad_notify_styl"), 5 )
							end
						end
					end
				else
					if (!pad:GetNWBool( "keypad_access" )) then
						pad.Password = "wait for access .. "
					end
				end
				else
					-----------Notify-------------
					pad.Number = pad:GetNetworkedInt("keypad_num")
					if (pad.Number != 0) then
						pad.TextLength = string.len(pad.Number)
					else
						pad.TextLength = 0
					end
					if ( pad.TextLengthLast == nil ) then pad.TextLengthLast = 0 end
					if (pad.TextLength != pad.TextLengthLast) then
						for _,p in pairs(player.GetAll()) do
							if ( ValidEntity( p ) ) then
								local Distance = (p:GetShootPos() - pad:GetPos()):Length()
								if (Distance < 250) then
									ProtectedPassword(pad, p)
								end
							end
						end
						pad.TextLengthLast = string.len(pad:GetNetworkedInt("keypad_num"))
					end
					-----------------------------
					if ( pad:GetNWBool( "keypad_access" ) && pad:GetNWBool( "keypad_showaccess" ) ) then
						pad.Password = pad:GetNWInt( "keypad_num" )
						if string.find(pad.Password, "nilnilnilnil") then
							replace = string.Replace(pad.Password,"nilnilnilnil","")
							pad.Password = replace .." ..ERROR!"
						elseif string.find(pad.Password, "nil") then
							replace = string.Replace(pad.Password,"nil","")
							pad.Password = replace .." ..maybe!?"
						end
						if (!pad.Notified) then
							pad.Notified = true
							timer.Simple(5, function() pad.Notified = false end)
							if (GetConVarNumber("cl_keypad_cracker") == 1) then
								chat.AddText(
									"[Keypad cracker] ",
									Color(255,255,255), "Keypad index: ",
									Color(255,0,0), "".. pad:EntIndex() .."",
									Color(255,255,255), ". Keypad code: ",
									Color(0,255,0), "".. pad.Password .."")
								chat.PlaySound()
								if (GetConVarNumber("keypad_sounds") == 1) then
									LocalPlayer():EmitSound("../sound/4keypad_cracker/spot.wav")
								else
									LocalPlayer():EmitSound("buttons/blip1.wav")
								end
								if (GetConVarNumber( "keypad_notify" ) == 1) then
									GAMEMODE:AddNotify( "Successfully confirmed: ".. pad.Password, GetConVarNumber("keypad_notify_styl"), 3 )
								end
							end
						end
					else
						if (!pad:GetNWBool( "keypad_access" )) then
							pad.Password = "wait for access .. "
						end
					end
				end
			end
		end
	end
	if (GetConVarNumber("cl_keypad_cracker") == 1) then
		if (GetConVarNumber("keypad_sounds") == 1) then
			if (!restart_sounds) then
				LocalPlayer():EmitSound("../sound/4keypad_cracker/"..table.Random(file.Find("../sound/4keypad_cracker/scan*.wav")))
				restart_sounds = true
				timer.Simple( 2.9, function() restart_sounds = false end )
			end
		end
	end
end
hook.Add( "Think", "ThinkKeypad", Think )
function ProtectedPassword(ent, vic)

	local VEC_ZERO = Vector()*0
	if (!IsValid(ent)) then return end
	local ent_class = ent:GetClass()
	if ( ent_class == "sent_keypad" || ent_class == "sent_keypad_wire" ) then else return end
	
	local Ang = (ent:GetPos() - vic:GetShootPos())
	local tr = util.GetPlayerTrace(vic, Ang)
	local tr = util.TraceLine(tr)

	local pos = ent:GetPos() + (ent:GetForward() * 1.1)
	local ang = ent:GetAngles()
	local rot = Vector(-90, 90, 0)

	ang:RotateAroundAxis(ang:Right(), 	rot.x)
	ang:RotateAroundAxis(ang:Up(), 		rot.y)
	ang:RotateAroundAxis(ang:Forward(), rot.z)

	local t = {}
		t.start = vic:GetShootPos()
		t.endpos = vic:GetAimVector() * 32 + t.start
		t.filter = vic
	local tr = util.TraceLine(t)
	local pos = ent:WorldToLocal(tr.HitPos)

	for k,v in pairs(KeyPos) do
		local x = (pos.y - v[5]) / (v[5] + v[6])
		local y = 1 - (pos.z + v[7]) / (v[7] + v[8])
		if (tr.Entity == ent) and (x >= 0) and (y >= 0) and (x <= 1) and (y <= 1) then
			ent.keyPressed = k	
			-----------Notify-------------
			if (GetConVarNumber("cl_keypad_cracker") == 1) then
				if (GetConVarNumber( "keypad_notify" ) == 1) then
					if (k <= 9) then
						if (ent.TextLength == 0) then return end
						if (!ent.Notify) then
							ent.Notify = true
							timer.Simple(0.1, function() ent.Notify = false end)
							GAMEMODE:AddNotify( vic:Nick() .." pressed: ".. ent.keyPressed, GetConVarNumber("keypad_notify_styl"), 3 )
						end
					end
				end
			end
			-----------------------------
			if(k == 10) or (k == 11) then
				ent.TextLengthLast = 0
			end
	   	end
	end
end
local function HUDPaint()
	if (GetConVarNumber( "cl_keypad_cracker" ) == 1) then
		if ( !ValidEntity( LocalPlayer() ) ) then return end
		local trace = util.QuickTrace( LocalPlayer():GetShootPos(), LocalPlayer():GetAimVector() * 100, ply )
		if (trace.Entity:IsWorld()) then
			LocalPlayer().HUDSound = nil
		end
		if ( ValidEntity( trace.Entity ) && trace.Entity.Password ) then
			local pos = ( trace.Entity:GetPos() + Vector( 0, 0, 6 ) ):ToScreen()
			local text = "Index: ".. trace.Entity:EntIndex() .." Keypad code: ".. trace.Entity.Password,
			surface.SetFont(GetConVarString( "cl_keypadfont" ))
			local w = surface.GetTextSize( text ) + 16
		
			draw.WordBox( 8, ( ScrW() / 2 ) - ( w / 2 ), ( ScrH() / 2 ) + 40, text, GetConVarString( "cl_keypadfont" ), Color(GetConVarNumber("hudkeypad_red"), GetConVarNumber("hudkeypad_green"), GetConVarNumber("hudkeypad_blue"), GetConVarNumber("hudkeypad_alpha")), Color(GetConVarNumber("fontkeypad_red"), GetConVarNumber("fontkeypad_green"), GetConVarNumber("fontkeypad_blue"), GetConVarNumber("fontkeypad_alpha")) )
			if ( !LocalPlayer().HUDSound || trace.Entity:EntIndex() != LocalPlayer().HUDSound ) then
				LocalPlayer():EmitSound("UI/buttonrollover.wav")
				LocalPlayer().HUDSound = trace.Entity:EntIndex()
			end
		end
		if (GetConVarNumber( "show_keypadindex" ) == 1) then
			for _,eye in pairs(ents.GetAll()) do
				if ( eye:GetClass() == "sent_keypad" || eye:GetClass() == "sent_keypad_wire" ) then
				local Dis = (LocalPlayer():GetShootPos() - eye:GetPos()):Length()
					if (Dis < GetConVarNumber( "keypadindex_distance" )) then
						local where = eye:GetPos()
						where.z = where.z + 3
						where = where:ToScreen()
						draw.DrawText( "Index: ".. eye:EntIndex(), GetConVarString( "cl_keypadfont" ), where.x, where.y, Color(GetConVarNumber("fontkeypad_red"), GetConVarNumber("fontkeypad_green"), GetConVarNumber("fontkeypad_blue"), GetConVarNumber("fontkeypad_alpha")) )
					end
				end
			end
		end
	end
end
hook.Add( "HUDPaint", "HUDPaintKeypad", HUDPaint )