I’m trying to find a function that returns the entity the player is looking at. The only thing I found were methods tryggered by aiming at entity but no looking. If you know how to do it please write an answer
Hey there,
it’s not a single native but you can do it using a bit of trigonometry / vector calculations. Dunno if a few of the things I do can be done using a native but I know my method works
Let’s look at it from the end:
You want to hit a ped, so for this you need the native StartShapeTestRay()
together with GetShapeTestResult()
. If you choose the parameters of the function correctly the result will look like this:
function GetPedInDirection(coordFrom, coordTo)
local rayHandle = StartShapeTestRay(coordFrom.x, coordFrom.y, coordFrom.z, coordTo.x, coordTo.y, coordTo.z, 4, GetPlayerPed(-1), 0)
local _,flag_PedHit,PedCoords,_,PedHit = GetShapeTestResult(rayHandle)
return flag_PedHit, PedCoords, PedHit
end
This will return a ped that is positioned in a straight line between point A (named coordFrom
) and point B (named coordTo
) while excluding the player ped.
Now we will need to position the line such that the gameplay camera is the starting point, the direction the camera is looking to is the end point.
The starting point is easy: Use the native GetGameplayCamCoord()
, which will give you the camera’s position.
So how does a line look like which starts from the camera position and goes straight where the player is looking? Answer is simple: It’s basically your crosshair, a single point on your screen.
The issue is: We’ll need to find a second point at a given distance to use in the function GetPedInDirection()
as we can’t just input camera directions.
Now this is where a few natives come into play:
GetGameplayCamRelativeHeading()
gives the heading of the camera relative to the player ped
GetEntityHeading()
will give us the heading of the player ped
GetGameplayCamRelativePitch()
gives the pitch relative to the player ped.
Thankfully the pitch of our character is 0 for basically everything (a few exceptions, e.g. being ragdolled), as such we can ignore the pitch of the character.
Once we have these data, we can utilize the spherical coordinate system. You probably know the cartesian coordinate system with fixed axis X, Y, Z. Any given object is placed in the coordinate system by its coordinates relative to a point (0, 0, 0) , e.g. (1000, 1001, 30).
In spherical coordinate system we also define points with three parameters. In this case we ask for the distance or radius to a given point (0, 0, 0) as well as the horizontal angle (heading) and vertical angle (pitch). We can easily calculate missing data in one coordinate system if we know the data in the other system. If you don’t know about spherical coordinates I really recommend checking it out.
Here I’m going to skip the mathematical explanation and will rather just comment out a few lines of the resulting code. Note that the function name isn’t necessarily correct. Rather than getting the looking vector itself you are getting a second point on the vector, implying you know the first one as the camera coordinates themselves.
You give your player ped as well as a radius (how far to look for another ped, e.g. 30 (metres) ).
-- returns the vector in which direction the player is looking (middle of the screen). Works first and third person
-- only use this for the local player, not other players' peds
-- usage: Vector3 = GetPlayerLookingVector(GetPlayerPed(-1), INT)
function GetPlayerLookingVector(playerped, radius)
local pedyaw = GetEntityHeading(playerped)
local camyaw = GetGameplayCamRelativeHeading()
local pitch = 90.0-GetGameplayCamRelativePitch()
local yaw = pedyaw + camyaw -- entity heading + relative camera heading = absolute camera heading
-- this is a crude way to make sure that the heading is between -180° and 180°. This is necessary for the mathematical functions following
if yaw > 180 then
yaw = yaw - 360
elseif yaw < -180 then
yaw = yaw + 360
end
-- the transformation from spherical coordinates to cartesian coordinates as taken from wikipedia.
-- note that there is an important difference in x and y.
-- reason is that in mathematics the angle 0° is defined by looking into positive x direction.
-- in GTA V the angle 0° has your character facing north, thus in positive y direction.
-- the transformation has to respect this fact.
local pitch = pitch * math.pi / 180
local yaw = yaw * math.pi / 180
local x = radius * math.sin(pitch) * math.sin(yaw)
local y = radius * math.sin(pitch) * math.cos(yaw)
local z = radius * math.cos(pitch)
-- the following code calculates the second coordinate which is then returned.
-- note the minus in the correction for x.
-- The above transformation didn't properly respect the different definition of the angle making the minus necessary.
local playerpedcoords = GetGameplayCamCoord()
local xcorr = -x+ playerpedcoords.x
local ycorr = y+ playerpedcoords.y
local zcorr = z+ playerpedcoords.z
local Vector = vector3(tonumber(xcorr), tonumber(ycorr), tonumber(zcorr))
return Vector
end
Now that we have the second point nothing stops us from putting everything together. I don’t know how much coding experience you have but I’m certain that you can do that without me pasting my solution
If you have any questions or can’t work it out feel free to answer, I’ll surely check out how you are progressing.
Answering to a DM I got.
print(GetPlayerLookingVector(playerPed, 50))
print(GetPedInDirection(GetGameplayCamCoord(), GetPlayerLookingVector(playerPed, 50)))
the issue here is that playerPed
isn’t defined. Put a playerPed = GetPlayerPed(-1)
in front of your code.
The ped is defined in other rows. This is not the problem… Any tip?
Paste the whole source code please
playerPed
is from the core part of the script the return the current player ped
Citizen.CreateThread(function ()
while true do
print(GetPlayerLookingVector(playerPed, 50))
print(GetPedInDirection(GetGameplayCamCoord(), GetPlayerLookingVector(playerPed, 50)))
Citizen.Wait(0)
end
end)
The code is working. It’s just the camera needs to look at a ped which you don’t do currently.
Copy the following code as a test:
local texturedict = "srange_gen"
local texturename = "medaldot_32"
local ButtonPressed = false
RequestStreamedTextureDict(texturedict, true)
CreateThread(function()
while true do
if IsControlJustPressed(0, 170) then
ButtonPressed = not ButtonPressed
end
Wait(0)
end
end)
CreateThread(function()
while true do
while ButtonPressed do
DrawSprite(texturedict, texturename, 0.5, 0.5, 0.009, 0.0165, 0.0, 0, 0, 0, 190)
DrawSprite(texturedict, texturename, 0.5, 0.5, 0.007, 0.013, 0.0, 255, 255, 255, 190)
Wait(0)
end
Wait(10)
end
end)
Press F3
to bring up a “crosshair” or a point in the middle of the screen. Put that point over the ped and the functions should work.
Just tested. Same result.
function GetPedInDirection(coordFrom, coordTo)
local rayHandle = StartShapeTestRay(coordFrom.x, coordFrom.y, coordFrom.z, coordTo.x, coordTo.y, coordTo.z, 4, GetPlayerPed(-1), 0)
local _,flag_PedHit,PedCoords,_,PedHit = GetShapeTestResult(rayHandle)
return flag_PedHit, PedCoords, PedHit
end
function GetPlayerLookingVector(playerped, radius)
local pedyaw = GetEntityHeading(playerped)
local camyaw = GetGameplayCamRelativeHeading()
local pitch = 90.0-GetGameplayCamRelativePitch()
local yaw = pedyaw + camyaw -- entity heading + relative camera heading = absolute camera heading
-- this is a crude way to make sure that the heading is between -180° and 180°. This is necessary for the mathematical functions following
if yaw > 180 then
yaw = yaw - 360
elseif yaw < -180 then
yaw = yaw + 360
end
-- the transformation from spherical coordinates to cartesian coordinates as taken from wikipedia.
-- note that there is an important difference in x and y.
-- reason is that in mathematics the angle 0° is defined by looking into positive x direction.
-- in GTA V the angle 0° has your character facing north, thus in positive y direction.
-- the transformation has to respect this fact.
local pitch = pitch * math.pi / 180
local yaw = yaw * math.pi / 180
local x = radius * math.sin(pitch) * math.sin(yaw)
local y = radius * math.sin(pitch) * math.cos(yaw)
local z = radius * math.cos(pitch)
-- the following code calculates the second coordinate which is then returned.
-- note the minus in the correction for x.
-- The above transformation didn't properly respect the different definition of the angle making the minus necessary.
local playerpedcoords = GetGameplayCamCoord()
local xcorr = -x+ playerpedcoords.x
local ycorr = y+ playerpedcoords.y
local zcorr = z+ playerpedcoords.z
local Vector = vector3(tonumber(xcorr), tonumber(ycorr), tonumber(zcorr))
return Vector
end
local texturedict = "srange_gen"
local texturename = "medaldot_32"
local ButtonPressed = false
RequestStreamedTextureDict(texturedict, true)
CreateThread(function()
while true do
if IsControlJustPressed(0, 170) then
ButtonPressed = not ButtonPressed
end
Wait(0)
end
end)
CreateThread(function()
while true do
while ButtonPressed do
DrawSprite(texturedict, texturename, 0.5, 0.5, 0.009, 0.0165, 0.0, 0, 0, 0, 190)
DrawSprite(texturedict, texturename, 0.5, 0.5, 0.007, 0.013, 0.0, 255, 255, 255, 190)
Wait(0)
end
Wait(10)
end
end)
Citizen.CreateThread(function ()
while true do
print(GetPlayerLookingVector(playerPed, 50))
print(GetPedInDirection(GetGameplayCamCoord(), GetPlayerLookingVector(playerPed, 50)))
Citizen.Wait(0)
end
end)```
playerPed
is not defined. You need to put in playerPed = GetPlayerPed(-1)
in that file.
I finally get why the code didn’t work.
I the script I’ve made for the creating of peds i put
SetEntityCollision(ped, false, true)
That doesn’t interact with StartShapeTestRay
After removing the line the code works well.