--[[
	nESP by Noiwex
	
	'nesp_enabled' 0|1 -- disable/enable nESP
	'nesp_spectators' 0|1 -- show spectators
	'nesp_radius' float -- radius, 0 to unlimited
]]

local next=next
local math=math
local draw=draw
local surface=surface
local string=string
local table=table
local player=player
local Vector=Vector
local LocalPlayer=LocalPlayer
local Color=Color
local PLAYER=FindMetaTable("Player")

nESP = {}
local nESP = _G.nESP
nESP.Enabled = CreateClientConVar("nesp_enabled", "1", true, false)
nESP.TargetID = CreateClientConVar("nesp_popup", "1", true, false)
nESP.Radius = CreateClientConVar("nesp_radius", "0", true, false)
nESP.Spec = CreateClientConVar("nesp_spectators", "0", true, false)
nESP.IntEnabled = nESP.IntEnabled or false --aha
nESP.Drawables = {}

nESP.Profiles = {
	player = function(e)
		return info
	end,
	
	ttt_c4 = function(e)
		local t = math.max(0, e:GetExplodeTime() - CurTime())
		nESP.DrawInfo(e,{},"Bomb",Color(255,0,0),t)
	end,
	
	prop_ragdoll = function(e)
		if CORPSE then
			local pl = CORPSE.GetPlayerNick(e,false)
			
			if not e.NoTarget then
				if CORPSE.GetFound(e, false) then
					nESP.DrawInfo(e, {}, pl, Color(255,128,0))
				else
					nESP.DrawInfo(e, {}, "Unknown body", Color(255,128,0))
				end
			end
		end
	end,
}

local pixVis = util.GetPixelVisibleHandle()

function nESP.DrawInfo(e,info,name,col,lbl)
	local wpos

	if e:LookupAttachment("eyes") ~= 0 then
		wpos = (e:GetAttachment(e:LookupAttachment("eyes")).Pos + Vector(0,0,5))
	else
		wpos = e:GetPos()
	end

	pos = wpos:ToScreen()
	pos.x = math.floor(pos.x)
	pos.y = math.floor(pos.y)
	
	if not pos.visible then return end

	local visibility = util.PixelVisible(wpos, 4, pixVis)

	surface.SetAlphaMultiplier(math.max(0.2, visibility))
				 
	surface.SetFont "DermaDefault"
	local w,h = surface.GetTextSize(name or (e:IsPlayer() and e:Name()) or e:GetClass())
	local infoheight = #info * h
	
	if e:IsPlayer() and e:GetFriendStatus() == "friend" then
		draw.SimpleText("[F]","DermaDefault",pos.x-h,pos.y - infoheight - h - 1,Color(255,255,0),TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
	end
	draw.RoundedBox(4,pos.x,pos.y - infoheight - h - 1,w+7,h+1,col or (e:IsPlayer() and team.GetColor(e:Team())) or Color(128,128,128))
	draw.SimpleText(name or (e:IsPlayer() and e:Name()) or e:GetClass(),"DermaDefault",pos.x+5,pos.y - infoheight - h,color_black,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
	draw.SimpleText(name or (e:IsPlayer() and e:Name()) or e:GetClass(),"DermaDefault",pos.x+4,pos.y - infoheight - h - 1,color_white,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
	
	draw.SimpleText("— " .. (lbl or (e:IsPlayer() and team.GetName(e:Team()))),"DermaDefault",pos.x+10+w,pos.y - infoheight - h,color_black,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
	draw.SimpleText("— " .. (lbl or (e:IsPlayer() and team.GetName(e:Team()))),"DermaDefault",pos.x+9+w,pos.y - infoheight - h - 1,color_white,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
	
	local i = 0
	
	for k,v in pairs(info) do
		i = i + 1 -- because using k will mess it up
		local ew,eh = surface.GetTextSize(v)
		surface.SetDrawColor(0,0,0,128)
		surface.DrawRect(pos.x,pos.y - infoheight + (i-1) * (h+1),ew,eh + 1)
		draw.SimpleText(v,"DermaDefault",pos.x,pos.y + 1 - infoheight + (i-1) * (h+1),color_white,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM)
	end

	surface.SetAlphaMultiplier(1)
end

hook.Add("Tick", "ESP", function()
	if nESP.IntEnabled and nESP.Enabled:GetBool() then
		for k in next, nESP.Drawables do
			nESP.Drawables[k] = nil
		end

		if not IsValid(LocalPlayer()) then
			return
		end

		local pos = LocalPlayer():GetPos()

		for k, e in pairs(player.GetAll()) do
			if e == LocalPlayer() then continue end
			if nESP.Spec:GetBool() == false and e:Team() == TEAM_SPECTATOR then continue end

			table.insert(nESP.Drawables, {
				ent = e,
				color = team.GetColor(e:Team()),
				info = {
					"Health: " .. e:Health(),
					(e:Armor() > 0 and "Armor: " .. e:Armor()) or nil,
					"Distance: " .. math.floor(e:GetPos():Distance(LocalPlayer():GetPos())),
					(e.DarkRPVars and
						(
							(e.DarkRPVars.money and e.DarkRPVars.salary and e.DarkRPVars.salary > 0 and Format("Money: %d (+%d)",e.DarkRPVars.money,e.DarkRPVars.salary) )
								or
							(e.DarkRPVars.money and "Money: " .. e.DarkRPVars.money)
						)
					) or nil,
					(e:GetActiveWeapon() and IsValid(e:GetActiveWeapon()) and "Weapon: " .. e:GetActiveWeapon():GetClass()) or nil,
					(e:IsSuperAdmin() and "Super Admin") or (e:IsAdmin() and "Admin") or nil
				},
			 })
		end

		table.sort(nESP.Drawables, function(a, b) return a.ent:GetPos():Distance(pos) > b.ent:GetPos():Distance(pos) end)
	end
end)

hook.Add("HUDPaint","ESP",function()
	if nESP.IntEnabled and nESP.Enabled:GetBool() then
		for k, v in pairs(nESP.Drawables) do
			if IsValid(v.ent) then
				--local e = v.ent
				nESP.DrawInfo(v.ent, v.info, --[[e._Name and (e:_Name() ~= e:Name() and Format("%s (%s)", e:_Name(), e:Name()) or e:_Name()) or e:Name()]] nil, (PLAYER.IsTraitor and v.ent:IsTraitor() and Color(255,0,0)) or (PLAYER.IsDetective and v.ent:IsDetective() and Color(0,0,255)) or v.color)
			end
		end
	end
end)

hook.Add("KeyPress","nESP_ShowItUp",function() -- AAAAAAAA LAAAAG CRAAAASH, ah nope
	nESP.IntEnabled = true
	
	hook.Remove("KeyPress","nESP_ShowItUp")
end)