--h
-- credits: NanoCat
-- give this any1 you want, this isn't uber-secret shit

local header = '\x7Fwalkbot\n' -- file header
local mode = -1 -- walkbot mode
local fs = nil -- file handle

-- i have no useful comments here, figure it out urself, i'm 2 lazy 2 maek coments

local play_direction = 1 
local next_waypoint = 1
local waypoints = {}

local red = Color( 255, 0, 0 )
local green = Color( 0, 255, 0 )

--[[

function file.Write( filename, contents )

	local f = file.Open( filename, "wb", "DATA" )
	if ( !f ) then return end

	f:Write( contents )
	f:Close()

end


]]

local function DrawFancyBox( v, c )
	surface.SetDrawColor( c )
	
	local b1 = ( v + Vector( 5, 5, 0 ) ):ToScreen()
	local b2 = ( v + Vector( 5, -5, 0 ) ):ToScreen()
	local b3 = ( v + Vector( -5, 5, 0 ) ):ToScreen()
	local b4 = ( v + Vector( -5, -5, 0 ) ):ToScreen()
	
	local t1 = ( v + Vector( 5, 5, 32 ) ):ToScreen()
	local t2 = ( v + Vector( 5, -5, 32 ) ):ToScreen()
	local t3 = ( v + Vector( -5, 5, 32 ) ):ToScreen()
	local t4 = ( v + Vector( -5, -5, 32 ) ):ToScreen()

	surface.DrawLine( b1.x, b1.y, b3.x, b3.y )
	surface.DrawLine( b2.x, b2.y, b4.x, b4.y )
	surface.DrawLine( b1.x, b1.y, b2.x, b2.y )
	surface.DrawLine( b3.x, b3.y, b4.x, b4.y )
	
	surface.DrawLine( b1.x, b1.y, t1.x, t1.y )
	surface.DrawLine( b2.x, b2.y, t2.x, t2.y )
	surface.DrawLine( b3.x, b3.y, t3.x, t3.y )
	surface.DrawLine( b4.x, b4.y, t4.x, t4.y )
	
	surface.DrawLine( t1.x, t1.y, t3.x, t3.y )
	surface.DrawLine( t2.x, t2.y, t4.x, t4.y )
	surface.DrawLine( t1.x, t1.y, t2.x, t2.y )
	surface.DrawLine( t3.x, t3.y, t4.x, t4.y )
end

local function RecordVector( v )
	fs:WriteFloat( v.x )
	fs:WriteFloat( v.y )
	fs:WriteFloat( v.z )
	fs:Flush()
end

local lastpos = Vector()
local lastyaw = 0
hook.Add( 'CreateMove', 'walkbot', function( cmd )
	local pl = LocalPlayer()
	local np = pl:GetPos()
	
	if fs then
		if mode == 0 then
			if math.abs( math.abs( lastyaw ) - math.abs( cmd:GetViewAngles().y ) ) > 10 and lastpos:Distance( np ) > 52 or lastpos:Distance( np ) > 392 then
				print( 'recorded new waypoint' )
				
				lastpos = np
				lastyaw = cmd:GetViewAngles().y
				
				RecordVector( util.QuickTrace( np + pl:OBBCenter(), np - Vector( 0, 0, 8192 ), pl ).HitPos )
			end
		end
	end
	
	if mode == 1 then
		local vec = waypoints[ next_waypoint ] - np
		if vec:Length2D() < pl:GetVelocity():Length2D() * 0.1 then
			if waypoints[ next_waypoint + play_direction ] then
				next_waypoint = next_waypoint + play_direction
			else
				play_direction = play_direction == 1 and -1 or 1
			end
		end
		
		local a = vec:Angle()
		
		local move = Vector( cmd:GetForwardMove(), cmd:GetSideMove(), 0 )
		local vec = ( move:Angle() + Angle( 0, cmd:GetViewAngles().y - a.y, 0 ) ):Forward() * move:Length()
		
		cmd:SetForwardMove( vec[1] )
		cmd:SetSideMove( vec[2] )
	end
end )

local rec
hook.Add( 'HUDPaint', 'walkbot', function()
	if mode == 0 and fs then
		if not rec then
			rec = Material( 'gmod/recording.png' )
		end

		surface.SetDrawColor( color_white )
		surface.SetMaterial( rec )
		surface.DrawTexturedRect( ScrW() - 512, 0, 512, 256, 0 )
	end
	
	if mode == 1 then
		local prev
		for k, v in pairs( waypoints ) do
			local scr = v:ToScreen()
			if not scr.visible then continue end
			
			if prev and prev.x and prev.y then
				surface.SetDrawColor( color_white )
				surface.DrawLine( prev.x, prev.y, scr.x, scr.y )
			end
			
			DrawFancyBox( v, next_waypoint == k and green or red )
			prev = scr
		end
	end
end )

concommand.Add( 'record_w', function( _, _, _, fn )
	fs = file.Open( 'shit' .. '.txt', 'wb', 'DATA' )
	
	if fs then
		fs:Write( header )
		fs:Write( game.GetMap() )
		
		lastpos = Vector()
		mode = 0
	else
		print( 'filestream was not created' )
	end
end )

concommand.Add( 'play_w', function( _, _, _, fn )
	local f = file.Open( 'shit' .. '.txt', 'rb', 'DATA' )
	
	if f then
		local h = f:Read( #header )
		local m = f:Read( #game.GetMap() )
		
		if h == header then
			if m == game.GetMap() then
				play_direction = 1
				next_waypoint = 1
				mode = 1
				
				table.Empty( waypoints )
				
				local x = f:ReadFloat()
				local y = f:ReadFloat()
				local z = f:ReadFloat()
				
				while x and y and z do
					table.insert( waypoints, Vector( x, y, z ) )
					
					x = f:ReadFloat()
					y = f:ReadFloat()
					z = f:ReadFloat()
				end
				
				RunConsoleCommand( '+forward' )
			else
				print( 'wrong map' )
			end
		else
			print( 'invalid header' )
		end
		
		f:Close()
	else
		print( 'unknown file' )
	end
end )

concommand.Add( 'stop_w', function()
	if fs then fs:Close() end
	
	RunConsoleCommand( '-forward' )
	mode = -1
end )