я немного не доделал перенос этого кода с C# на луа

--DIREKTIVY
script_name		('never-topple')
script_author	("pururin")
script_version	("03sep24")

--ZAVISIMOSTI
local maf = require 'maf'

--GLOBALʹNYE PEREMENNYE I KONSTANTY
local isActive			= false
--Components
local aircraft			-- Transform of the aircraft the rig follows and references
local mouseAim			-- Transform of the object the mouse rotates to generate MouseAim position
local cameraRig			-- Transform of the object on the rig which the camera is attached to
local cam				-- Transform of the camera itself
--Space
local showDebugInfo		= false;	-- How far the boresight and mouse flight are from the aircraft
local frozenDirection	= Vector3.forward;
local isMouseAimFrozen	= false;


--NASTROJKI
local useFixed			= true		-- Follow aircraft using fixed update loop
local camSmoothSpeed	= 5.0		-- How quickly the camera tracks the mouse aim point.
local mouseSensitivity	= 3.0		-- Mouse sensitivity for the mouse flight target
local aimDistance		= 500.0		-- How far the boresight and mouse flight are from the aircraft
local freezeKey			= 0x43


--OSNOVNAÂ FUNKCIÂ
function main()
	while not isPlayerPlaying(PLAYER_HANDLE) do wait(100) end
	wait(1000)

	while true do wait(0)
		if isCharInAnyCar(playerPed) then
			local car = storeCarCharIsInNoSave(playerPed)
			if doesVehicleExist(car) then
			
				if not isActive then
					local x, y, z, w = getVehicleQuaternion(car)
					aircraft	= maf.quat(x, y, z, w)
					mouseAim	= maf.quat(x, y, z, w)
					cameraRig	= maf.quat(x, y, z, w)
					cam		    = maf.quat(x, y, z, w)
					
					isActive	= true
					RotateRig()
				else
					RotateRig()
				end
								
			end
			
		else
			isActive = false
		end
	end
end



function getBoresightPos
	aimPosition = (aircraft.transform.forward * aimDistance) + aircraft.transform.position
end

function getMouseAimPos()
	return isMouseAimFrozen	and getFrozenMouseAimPos() or (mouseAim.position + (mouseAim.forward * aimDistance))
end

function getFrozenMouseAimPos()
	return mouseAim.position + (frozenDirection * aimDistance);
end


function RotateRig()
	-- Freeze the mouse aim direction when the free look key is pressed.
	if (isKeyDown(freezeKey)) then
		isMouseAimFrozen = true;
		frozenDirection = mouseAim.forward;
	else
		isMouseAimFrozen = false;
		mouseAim.forward = frozenDirection;
	end

	-- Mouse input.
	local mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
	local mouseY = -Input.GetAxis("Mouse Y") * mouseSensitivity;

	-- Rotate the aim target that the plane is meant to fly towards.
	-- Use the camera's axes in world space so that mouse motion is intuitive.
	mouseAim.Rotate(cam.right, mouseY, Space.World);
	mouseAim.Rotate(cam.up, mouseX, Space.World);

	-- The up vector of the camera normally is aligned to the horizon. However, when
	-- looking straight up/down this can feel a bit weird. At those extremes, the camera
	-- stops aligning to the horizon and instead aligns to itself.
	local upVec
	
	if math.abs(mouseAim.forward.y) > 0.9 then
		upVec = cameraRig.up
	else
		upVec = Vector3.up
	end

	-- Smoothly rotate the camera to face the mouse aim.
	cameraRig.rotation = Damp(cameraRig.rotation,
							  Quaternion.LookRotation(mouseAim.forward, upVec),
							  camSmoothSpeed,
							  Time.deltaTime);
end



function Damp(a, b, lambda, dt)
    return Quaternion.Slerp(a, b, 1 - math.exp(-lambda * dt))
end





function onD3DPresent() 
	if (showDebugInfo == true) then
		
		-- Draw the boresight position.
		--Gizmos.color = Color.white;
		--Gizmos.DrawWireSphere(getBoresightPos, 10f);
	
		-- Draw the position of the mouse aim position.
		--Gizmos.color = Color.red;
		--Gizmos.DrawWireSphere(getMouseAimPos, 10f);
	
		-- Draw axes for the mouse aim transform.
		--Gizmos.color = Color.blue;
		--Gizmos.DrawRay(mouseAim.position, mouseAim.forward * 50f);
		--Gizmos.color = Color.green;
		--Gizmos.DrawRay(mouseAim.position, mouseAim.up * 50f);
		--Gizmos.color = Color.red;
		--Gizmos.DrawRay(mouseAim.position, mouseAim.right * 50f);

	end
end


--
-- Copyright (c) Brian Hernandez. All rights reserved.
-- Licensed under the MIT license. See LICENSE file in the project root for details.
--

перенеси окончательно этот код до работоспосбоного состояния в gta sa. используй функции moonloader и библиотеку maf - Example
local maf = require 'maf'

local a = maf.vector(1, 2, 3)
local b = maf.vector(4, 5, 6)

local c = a + b
local d = maf.rotation.between(a, b)

print(c:unpack())
print(d:getAngleAxis())
Documentation
In general, any function that returns a vector or a rotation will write its result into the last parameter, out. The function also returns out for convenience, to allow for method chaining. If out is unspecified, then the result will be written into the first parameter instead.

Vectors
maf.vector(x, y, z) or maf.vec3(x, y, z)
Create a new vector. Omitted elements will be set to zero.

The x, y, and z keys contain the individual components of the vector.

The following metamethods are defined for vectors:

v + v - Add two vectors.
v - v - Subtract two vectors.
v * v - Multiply two vectors.
v * n - Scale a vector by a number.
v / v - Divide two vectors.
-v - Negate a vector.
#v - Get the length of a vector.
vector:unpack()
Get the individual components of the vector.

vector:set(x, y, z)
Set the individual components of a vector. x can also be a vector.

vector:add(v2, [out])
Add two vectors.

vector:sub(v2, [out])
Subtract two vectors.

vector:mul(v2, [out])
Multiply two vectors.

vector:div(v2, [out])
Divide two vectors.

vector:scale(s, [out])
Multiply each component of the vector by a number s.

vector:length()
Return the length of the vector.

vector:normalize([out])
Set the length of a vector to 1.

vector:distance(v2)
Return the distance between two vectors.

vector:angle(v2)
Return the angle between two vectors, in radians.

vector:dot(v2)
Return the dot product of two vectors, defined as v1.x * v2.x + v1.y * v2.y + v1.z * v2.z.

vector:cross(v2, [out])
Return the cross product of two vectors. The cross product is a vector that is perpendicular to the two input vectors.

vector:lerp(v2, t, [out])
Mixes two vectors together using linear interpolation. The parameter t controls how they are mixed (0 will return vector, 1 will return v2, .5 will return a 50/50 blend of the two vectors, etc.).

vector:project(u, [out])
Projects vector onto u, storing the result in out.

vector:rotate(r, [out])
Applies a rotation r to the vector.

Rotations
maf.rotation(x, y, z, w) or maf.quat(x, y, z, w)
Creates a new rotation (quaternion) from x, y, z, w components. Unless you are some sort of wizard that understands quaternions, it's probably easier to use .fromAngleAxis, .fromDirection, or .between.

The following metamethods are defined for rotations:

q + q - Add two rotations.
q - q - Subtract two rotations.
q * q - Multiply two rotations, resulting in a rotation that is equivalent to applying the first rotation followed by the second.
q * v - Multiply a rotation by a vector, returning the rotated vector.
-q - Negate a rotation.
#q - Get the length of a rotation.
rotation:unpack()
Get the individual components of the rotation.

rotation:set(x, y, z, w)
Set the individual components of a rotation. x can also be a rotation.

rotation.fromAngleAxis(angle, x, y, z)
Creates a new rotation from an angle/axis pair. This is the same as creating a new rotation and calling :setAngleAxis on it. x can also be a vec3.

rotation:setAngleAxis(angle, x, y, z)
Set the rotation's values using angle/axis representation. x can also be a vec3.

angle, x, y, z = rotation:getAngleAxis()
Get the angle/axis representation of the rotation.

rotation.between(v1, v2)
Create a new rotation that represents the rotation between v1 and v2. Both vectors should be normalized.

rotation:setBetween(v1, v2)
Update an existing rotation to represent the rotation between v1 and v2. Both vectors should be normalized.

rotation.fromDirection(x, y, z)
Create a new rotation from a direction vector. The rotation will represent the rotation from the forward vector (0, 0, -1) to the direction vector. x can also be a vec3.

rotation:setDirection(x, y, z)
Set a rotation's value to those of the direction vector. x can also be a vec3.

rotation:add(r2, [out])
Add two rotations together. To combine two rotations together, multiply them instead.

rotation:sub(r2, [out])
Subtract two rotations.

rotation:mul(r2, [out])
Multiply two rotations together, returning a rotation that combines the two.

rotation:scale(s, [out])
Multiply each component of the rotation by a number s.

rotation:length()
Return the length of the rotation.

rotation:normalize([out])
Normalize a rotation, setting its length to 1.

rotation:lerp(r2, t, [out])
Mix two rotations together using linear interpolation. This is faster than :slerp but less accurate.

rotation:slerp(r2, t, [out])
Mix two rotations together using spherical linear interpolation.