Getting player to aim towards crosshair in off-center third person camera

EDIT: After lots of discussion I’ve decided to take a different approach:

I want the player to be unaffected by mouse control. I want the camera to be controlled by the mouse. I want the player to look towards the HitPos of the crosshair.

Below is my original post!

https://dl.dropboxusercontent.com/u/965202/ShareX/2014-06/Garry's_Mod_2014-06-04_17-06-55.jpg

So, I can create a crosshair where I’m already aiming, but I’d rather have him consistently aim towards the center of the screen. This has proven to boggle my mind.

Is there anyway I can do this?


function thirdPerson( ply, pos, angles, fov )
    
    local view = { }

    view.origin = pos - ( angles:Forward( ) * 100 ) + ( angles:Right( ) * 25 ) - ( angles:Up( ) * 5 )
    view.angles = angles
    view.fov = fov
 
    return view
    
end
 
hook.Add( "CalcView", "thirdPerson", thirdPerson )
 
hook.Add( "ShouldDrawLocalPlayer", "thirdPersonDrawLocalPlayer", function( ply )
    return true
end )

i think it involves trigonometry. you’re trying to find the angle between a point (the shootpos) and where you are looking. in this case, i think your right angle would be where your camera is, so you just have to find the angle between the player and where you are looking.

here’s your picture

http://puu.sh/9fvXs/5a6a4c7885.png

Create an eye trace, get where the trace hit and then, get the cords on the screen about where the trace it’s

[lua]

local tr = LocalPlayer():GetEyeTrace()
if(tr.Hit) then
pos = tr.HitPos:ToScreen()
end

MsgN(“Pos on your screen in X “,pos.x,” Pos on your screen in Y”,pos.y)

[/lua]

Alright, I have all the variables I need. I just need to figure out how to implement them.


function thirdPerson( ply, pos, angles, fov )
    
    -- camPos is the position of the camera
    -- camDistFromCH is distance from camera to crosshair
    -- campDistFromPly is distance from camrea to player
    
    local camPos    = pos - ( angles:Forward( ) * 100 ) + ( angles:Right( ) * 25 ) - ( angles:Up( ) * 5 )
    
    local camTr  = util.TraceLine( {
        start = camPos,
        endpos = camPos + ( angles:Forward( ) * 9999999 ),
        filter = function( ent )
            if ( ent:GetClass() == "player" ) and player == ply then
                return true
            end
        end
    } )
    
    local camDistFromCH = camPos:Distance( camTr.HitPos )
    local camDistFromPly = camPos:Distance( pos )
    
    local view = { }

    view.origin = camPos
    view.angles = angles
    view.fov = fov
    
    return view
    
end
 
hook.Add( "CalcView", "thirdPerson", thirdPerson )
 
hook.Add( "ShouldDrawLocalPlayer", "thirdPersonDrawLocalPlayer", function( ply )
    return true
end )

I don’t know how to turn the player towards the crosshair without turning the camera. I want him to shoot towards the crosshair at all times.

[editline]4th June 2014[/editline]

All that would do is find the position of where the player is already aiming at, which isn’t useful for what I’m trying to do, unfortunately. That’s the “incorrect” aiming trace I’m trying to correct.

EDIT: I think I have a better understanding of what I want to do now: I want the player to look towards the crosshair but have no direct influence from the mouse. I want the mouse to control the camera.

Correct me if i’m wrong, but wouldn’t this be easier?

http://wiki.garrysmod.com/page/gui/ScreenToVector

http://maurits.tv/data/garrysmod/wiki/wiki.garrysmod.com/indexe4b0.html

(aimpos - playerpos):Angle( ) = desired aim angle?

Is there any way I could disable looking around on the player and move the CalcView independently? If I can do that then the entire problem is solved because I can just set the player’s eye-angles to point to the HitPos of the crosshair trace.

You’re over-thinking and over-complicating a problem.

CalcView and CreateMove are used.

In CreateMove with one argument _cmd, if thirdperson is enabled, assign _dMx = _cmd:GetMouseX( ) for rotation. This controls a variable you have for yaw; use a Vector and just modify yaw or create a separate variable, it doesn’t matter. Make sure to math.NormalizeAngle( yaw - dMx ); this lets you simply subtract, or add the change in position resulting in rotation of the camera angle.

You can also _cmd:GetMouseWheel( ) within CreateMove to control zoom. If you plan on using roll, you’ll want to ensure it always Lerps to 0 ( so when a player jumps, it’ll always return to 0; or just leave it as is and don’t play with it, let the game do it by itself )

For CalcView with 6 arguments for player, origin, angles, fov, znear, zfar - I call them _p, _origin, _ang, _fov, _znear, _zfar. If thirdperson is enabled, and they are not in a vehicle ( let the vehicle class manage the view while in a vehicle ). Create a new list; view or _view. set _view.drawviewer to true, this allows us to avoid hooking into ShouldDrawLocalPlayer.

We’ll want to use the yaw we created and are managing with CreateMove to rotate the camera around the player, and only when the player uses a movement key or attack key to update the player yaw to the camera yaw.

To rotate only the camera, you just SetEyeAngles on the player to the old yaw ( one more thing to manage ), when we move the player we update the old angle first and set angle in an if statement else we update the eye angles for the player using the old yaw.

Something like this:
[lua] if ( ply:KeyDown( bit.bor( IN_FORWARD, IN_BACK, IN_MOVELEFT, IN_MOVERIGHT, IN_ATTACK2 ) ) ) then
ply:SetFlag( “view_angle_old”, Angle( angles.p, _angle.y, 0 ), true );
ply:SetEyeAngles( Angle( angles.p, _angle.y, 0 ) );
else
local _old = ply:GetFlag( “view_angle_old”, Angle( 0, 0, 0 ), true );
ply:SetEyeAngles( Angle( angles.p, _old.y, 0 ) );
end[/lua]

That handles rotating the camera, but we’re still not “thirdperson”. Target origin, so _view.origin should be all of the following:
( _angles from CalcView arg + the current view-angle ( where we manage yaw ) + another angle to offset us if you want I use yaw 15 ):Forward( ) * -_dist
where _dist is the distance behind the player we want to be. I use 100 units.

[lua]local _targetOrigin = origin + ( ( angles + _angle + Angle( 0, 15, 0 ) ):Forward( ) * -_dist );[/lua]

Then, just do a trace to ensure the camera can never go into a wall; done.

I’m going to continue trying to get what you said to work, but everything you just said is very terribly confusing. I’m breaking it down step by step but I’m extremely lost. I added you on Steam if you’re willing to accept it and help out through there. I was looking at your old posts for help on this issue as well.

[editline]5th June 2014[/editline]

With _Kilburn all of your dreams can come true. Too bad I’m spilling the beans, baby:


function thirdPerson( ply, pos, ang, fov, znear, zfar )
    
    local camPos    = pos - ( ply.camera_ang:Forward( ) * 100 ) + ( ply.camera_ang:Right( ) * 45 ) - ( ply.camera_ang:Up( ) * -15 )
    
    local camTr  = util.TraceLine( {
        start = camPos,
        endpos = camPos + ( ply.camera_ang:Forward( ) * 9999999 ),
        filter = ply,
    } )
    
    local view = { }

    view.origin = camPos
    view.angles = ply.camera_ang
    view.fov = fov
    view.drawviewer = true
    
    ply:SetEyeAngles( ( camTr.HitPos - ply:EyePos( ) ):Angle( ) )
    
    return view
end

hook.Add( "CalcView", "thirdPerson", thirdPerson )

function thirdPersonCreateMove( cmd )
    
    return false
    
end

hook.Add( "CreateMove", "thirdPersonCreateMove", thirdPersonCreateMove )

hook.Add( "InputMouseApply", "thirdPersonDisableNormalAim", function( cmd, x, y, ang )
    
    local ply = LocalPlayer( )
        
    if !ply.camera_ang then
        ply.camera_ang = Angle( 0, 0, 0 )
    end
        
    ply.camera_ang.p = math.NormalizeAngle( ply.camera_ang.p + y / 50 )
    ply.camera_ang.y = math.NormalizeAngle( ply.camera_ang.y - x / 50 )
        
	return true
 
end)

Thanks Acecool and Kilburn!