This is an implementation of GetOffsetFromEntityInWorldCoords:
-- server.lua
function getEntityMatrix(element)
local rot = GetEntityRotation(element) -- ZXY
local rx, ry, rz = rot.x, rot.y, rot.z
rx, ry, rz = math.rad(rx), math.rad(ry), math.rad(rz)
local matrix = {}
matrix[1] = {}
matrix[1][1] = math.cos(rz)*math.cos(ry) - math.sin(rz)*math.sin(rx)*math.sin(ry)
matrix[1][2] = math.cos(ry)*math.sin(rz) + math.cos(rz)*math.sin(rx)*math.sin(ry)
matrix[1][3] = -math.cos(rx)*math.sin(ry)
matrix[1][4] = 1
matrix[2] = {}
matrix[2][1] = -math.cos(rx)*math.sin(rz)
matrix[2][2] = math.cos(rz)*math.cos(rx)
matrix[2][3] = math.sin(rx)
matrix[2][4] = 1
matrix[3] = {}
matrix[3][1] = math.cos(rz)*math.sin(ry) + math.cos(ry)*math.sin(rz)*math.sin(rx)
matrix[3][2] = math.sin(rz)*math.sin(ry) - math.cos(rz)*math.cos(ry)*math.sin(rx)
matrix[3][3] = math.cos(rx)*math.cos(ry)
matrix[3][4] = 1
matrix[4] = {}
local pos = GetEntityCoords(element)
matrix[4][1], matrix[4][2], matrix[4][3] = pos.x, pos.y, pos.z - 1.0
matrix[4][4] = 1
return matrix
end
function GetOffsetFromEntityInWorldCoords(entity, offX, offY, offZ)
local m = getEntityMatrix(entity)
local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]
local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
return vector3(x, y, z)
end
The example below illustrates how to teleport a player always 5 units forward using only server side:
-- server/warp.lua
RegisterCommand("warp", function(source)
local ped = GetPlayerPed(source)
local coords = GetOffsetFromEntityInWorldCoords(ped, 0.0, 5.0, 0.0)
SetEntityCoords(ped, coords.x, coords.y, coords.z)
end, false)
References:
- GetElementMatrix - Multi Theft Auto: Wiki
11 Likes
Same code in C# for anyone who needs it, save rewriting it. Cheers @draobrehtom.
/// <summary>
/// Credit to draobrehtom.
/// https://forum.cfx.re/t/p/4502297.
/// https://forum.cfx.re/u/draobrehtom.
/// </summary>
internal Vector3 GetOffsetFromEntityInWorldCoords(Entity entity, Vector3 offset)
{
Vector3 position = entity.Position;
Vector3 rotation = entity.Rotation;
float rX = MathUtil.DegreesToRadians(rotation.X);
float rY = MathUtil.DegreesToRadians(rotation.Y);
float rZ = MathUtil.DegreesToRadians(rotation.Z);
double cosRx = Math.Cos(rX);
double cosRy = Math.Cos(rY);
double cosRz = Math.Cos(rZ);
double sinRx = Math.Sin(rX);
double sinRy = Math.Sin(rY);
double sinRz = Math.Sin(rZ);
Matrix matrix = new()
{
M11 = (float)((cosRz * cosRy) - (sinRz * sinRx * sinRy)),
M12 = (float)((cosRy * sinRz) + (cosRz * sinRx * sinRy)),
M13 = (float)(-cosRx * sinRy),
M14 = 1,
M21 = (float)(-cosRx * sinRz),
M22 = (float)(cosRz * cosRx),
M23 = (float)sinRx,
M24 = 1,
M31 = (float)((cosRz * sinRy) + (cosRy * sinRz * sinRx)),
M32 = (float)((sinRz * sinRy) - (cosRz * cosRy * sinRx)),
M33 = (float)(cosRx * cosRy),
M34 = 1,
Row4 = new(position.X, position.Y, position.Z - 1f, 1f)
};
return new()
{
X = (offset.X * matrix.M11) + (offset.Y * matrix.M21) + (offset.Z * matrix.M31) + matrix.M41,
Y = (offset.X * matrix.M12) + (offset.Y * matrix.M22) + (offset.Z * matrix.M32) + matrix.M42,
Z = (offset.X * matrix.M13) + (offset.Y * matrix.M23) + (offset.Z * matrix.M33) + matrix.M43
};
}
Same code in JS
function getEntityMatrix(entity) {
let dtr = Math.PI/180
let [x, y, z] = GetEntityCoords(entity)
let [rx, ry, rz] = GetEntityRotation(entity);
rx = rx * dtr
ry = ry * dtr
rz = rz * dtr
let matrix = [
[
Math.cos(rz)*Math.cos(ry) - Math.sin(rz)*Math.sin(rx)*Math.sin(ry),
Math.cos(ry)*Math.sin(rz) + Math.cos(rz)*Math.sin(rx)*Math.sin(ry),
-Math.cos(rx)*Math.sin(ry),
1
],
[
-Math.cos(rx)*Math.sin(rz),
Math.cos(rz)*Math.cos(rx),
Math.sin(rx),
1
],
[
Math.cos(rz)*Math.sin(ry) + Math.cos(ry)*Math.sin(rz)*Math.sin(rx),
Math.sin(rz)*Math.sin(ry) - Math.cos(rz)*Math.cos(ry)*Math.sin(rx),
Math.cos(rx)*Math.cos(ry),
1
],
[
x,
y,
z - 1.0,
1
]
]
return matrix
}
function GetOffsetFromEntityInWorldCoords (entity, offX, offY, offZ) {
let m = getEntityMatrix(entity);
let v = {
x: offX * m[0][0] + offY * m[1][0] + offZ * m[2][0] + m[3][0],
y: offX * m[0][1] + offY * m[1][1] + offZ * m[2][1] + m[3][1],
z: offX * m[0][2] + offY * m[1][2] + offZ * m[2][2] + m[3][2]
}
return v;
}
Here it is in Lua if anyone needs it
function GetOffsetFromEntityInWorldCoords(entity, offset)
local position = GetEntityCoords(entity)
local rotation = GetEntityRotation(entity)
local rX = math.rad(rotation.x)
local rY = math.rad(rotation.y)
local rZ = math.rad(rotation.z)
local cosRx = math.cos(rX)
local cosRy = math.cos(rY)
local cosRz = math.cos(rZ)
local sinRx = math.sin(rX)
local sinRy = math.sin(rY)
local sinRz = math.sin(rZ)
local matrix = {
M11 = (cosRz * cosRy) - (sinRz * sinRx * sinRy),
M12 = (cosRy * sinRz) + (cosRz * sinRx * sinRy),
M13 = -cosRx * sinRy,
M14 = 1,
M21 = -cosRx * sinRz,
M22 = cosRz * cosRx,
M23 = sinRx,
M24 = 1,
M31 = (cosRz * sinRy) + (cosRy * sinRz * sinRx),
M32 = (sinRz * sinRy) - (cosRz * cosRy * sinRx),
M33 = cosRx * cosRy,
M34 = 1,
Row4 = {position.x, position.y, position.z}
}
return vector3(
offset.x * matrix.M11 + offset.y * matrix.M21 + offset.z* matrix.M31 + matrix.Row4[1],
offset.x * matrix.M12 + offset.y * matrix.M22 + offset.z* matrix.M32 + matrix.Row4[2],
offset.x * matrix.M13 + offset.y * matrix.M23 + offset.z * matrix.M33 + matrix.Row4[3]
)
end
1 Like