Jump to content

Spectate on a vehicle/ped/object


orel56000

Recommended Posts

1 hour ago, koragg said:

lol I needed the exact same thing just a few hours ago :D Have a look at my topic: 

 

The functions which did it for me were:

GetCamera()

setElementPosition()

atachElements()

The code example at the first function's wiki is what we're looking for.

Thank you for reply.

I need that free camera movement too.. so it does not helped me too much but thanks anyway

Edited by orel56000
Link to comment

I found a way for all who looking for that too

 

that the calculations:

local specdis, specon = 0, nil

function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() then
		local sx, sy = guiGetScreenSize()
		AngX = (AngX + (x - (sx/2))/10) % 360
		AngZ = (AngZ + (y - (sy/2))/10) % 360
		if AngZ > 180 then
			if AngZ < 315 then AngZ = 315 end
		else
			if AngZ > 45 then AngZ = 45 end
		end
	end
end
function RenderVeiw()
	local ox, oy, oz
	local x, y, z = getElementPosition(specon)
	ox = x - math.sin(math.rad(AngX)) * specdis
	oy = y - math.cos(math.rad(AngX)) * specdis
	oz = z + math.tan(math.rad(AngZ)) * specdis
	setCameraMatrix(ox, oy, oz, x, y, z)
end

function PlayerSpecOnElement(spec, distance)
	if spec == nil or distance == nil or spec == "None" then
		specon = nil
		specdis = 0
		return 1
	end
	if specon then
		removeEventHandler("onClientRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
	end
	specon = spec
	specdis = distance
	addEventHandler("onClientRender", getRootElement(), RenderVeiw)
	addEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
end

addEvent("setPlayerSpecOnElement", true)
addEventHandler("setPlayerSpecOnElement", getRootElement(), PlayerSpecOnElement)
Link to comment
13 minutes ago, koragg said:

@orel56000 AngX and AngZ are not defined anywhere and give error. Can you give example on how to use these functions to set the camera on an object and make it move freely to look around that object via mouse move (just like it is in normal spectating).

oh sorry, that a fix:

that the calculations:

local AngX, AngZ, specdis, specon = 0, 0, 0, nil

function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() then
		local sx, sy = guiGetScreenSize()
		AngX = (AngX + (x - (sx/2))/10) % 360
		AngZ = (AngZ + (y - (sy/2))/10) % 360
		if AngZ > 180 then
			if AngZ < 315 then AngZ = 315 end
		else
			if AngZ > 45 then AngZ = 45 end
		end
	end
end
function RenderVeiw()
	local ox, oy, oz
	local x, y, z = getElementPosition(specon)
	ox = x - math.sin(math.rad(AngX)) * specdis
	oy = y - math.cos(math.rad(AngX)) * specdis
	oz = z + math.tan(math.rad(AngZ)) * specdis
	setCameraMatrix(ox, oy, oz, x, y, z)
end

function PlayerSpecOnElement(spec, distance)
	if spec == nil or distance == nil or spec == "None" then
		specon = nil
		specdis = 0
		return 1
	end
	if specon then
		removeEventHandler("onClientRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
	end
	specon = spec
	specdis = distance
	addEventHandler("onClientRender", getRootElement(), RenderVeiw)
	addEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
end

addEvent("setPlayerSpecOnElement", true)
addEventHandler("setPlayerSpecOnElement", getRootElement(), PlayerSpecOnElement)

put that on client side

 

If you wanna use it on clientside:

PlayerSpecOnElement(element, lookDistance)

if you wanna use it on serverside:

triggerClientEvent(player, "setPlayerSpecOnElement", getRootElement(), element, lookDistance)

sorry for posting again i coulden't edit my reply

Edited by orel56000
  • Thanks 1
Link to comment

Nice, works like a charm. But is there a way to keep the focus of the camera behind the object when I'm not moving my mouse? I mean, when the object I'm spectating (a ghost car) makes a turn the camera stays at the same spot at which I left it via my mouse. I need it to go behind the object (ghost car) after a few seconds of not moving my mouse. Hope you can help!

Link to comment

@koragg i found how to do this

that the calculations:

local AngX, AngZ, specdis, ticks, speed, specon = 0, 0, 0, 0, 0.8, nil

function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() then
		local sx, sy = guiGetScreenSize()
		ticks = getTickCount()
		AngX = (AngX + (x - (sx/2))/10) % 360
		AngZ = (AngZ + (y - (sy/2))/10) % 360
		if AngZ > 180 then
			if AngZ < 315 then AngZ = 315 end
		else
			if AngZ > 45 then AngZ = 45 end
		end
	end
end
function RenderVeiw()
	if not specon then
		removeEventHandler("onClientRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
		return 1
	end
	local ox, oy, oz
	local x, y, z = getElementPosition(specon)
	if ticks+10000 < getTickCount() then
		local rx, ry, rz = getElementRotation(specon)
		local dis = AngX-(360-rz)
		local dis1 = math.abs(dis)
		if dis1 > 30 then
			if speed < 4 then speed = speed + 0.8 end
		end
		if dis1 < 30 then
			if speed > 0.8 then speed = speed - 0.8 end
		end
		if dis1 > speed then
			dis = dis/(dis1/(speed))
		end
		AngX = AngX - dis
	end
	ox = x - math.sin(math.rad(AngX)) * specdis
	oy = y - math.cos(math.rad(AngX)) * specdis
	oz = z + math.tan(math.rad(AngZ)) * specdis
	setCameraMatrix(ox, oy, oz, x, y, z)
end

function PlayerSpecOnElement(spec, distance)
	if spec == nil or distance == nil or spec == "None" then
		specon = nil
		specdis = 0
		return 1
	end
	if specon then
		removeEventHandler("onClientRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
	end
	specon = spec
	specdis = distance
	addEventHandler("onClientRender", getRootElement(), RenderVeiw)
	addEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
end

addEvent("setPlayerSpecOnElement", true)
addEventHandler("setPlayerSpecOnElement", getRootElement(), PlayerSpecOnElement)

 

Edited by idan1432
  • Like 2
Link to comment

OK, it works almost perfect. But do any of you know if there is a way to know when the camera has stopped moving itself and it's at the back of the target? What I mean is this:

 

After not moving my mouse for some seconds the camera goes behind the object automatically. Can I somehow know when the animation of it going to the back has ended? I hope you understood me :S I need to know when the animation of the camera going to the object's rear has ended because I want to force it to stay behind the object then (if mouse is not moved). @orel56000 @idan1432

Edited by koragg
Link to comment
local AngX, AngZ, specdis, ticks, ticks2, speed, specon = 0, 0, 0, 0, 0, 0.8, nil

function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() then
		local sx, sy = guiGetScreenSize()
		ticks = getTickCount()
		ticks2 = 1
		AngX = (AngX + (x - (sx/2))/10) % 360
		AngZ = (AngZ + (y - (sy/2))/10) % 360
		if AngZ > 180 then
			if AngZ < 315 then AngZ = 315 end
		else
			if AngZ > 45 then AngZ = 45 end
		end
	end
end
function RenderVeiw()
	if not specon then
		removeEventHandler("onClientRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
		return 1
	end
	local ox, oy, oz
	local x, y, z = getElementPosition(specon)
	if ticks+10000 < getTickCount() then
		local rx, ry, rz = getElementRotation(specon)
		local dis = AngX-(360-rz)
		local dis1 = math.abs(dis)
		if dis1 > 30 then
			if speed < 4 then speed = speed + 0.8 end
		end
		if dis1 < 30 then
			if speed > 0.8 then speed = speed - 0.8 end
		end
		if dis1 > speed then
			dis = dis/(dis1/(speed))
		end
		if dis1 < speed and ticks2 == 1 then
			ticks2 = 0
			triggerEvent("mouseAnimationEndCamera", getRootElement())
		end
		AngX = AngX - dis
	end
	ox = x - math.sin(math.rad(AngX)) * specdis
	oy = y - math.cos(math.rad(AngX)) * specdis
	oz = z + math.tan(math.rad(AngZ)) * specdis
	setCameraMatrix(ox, oy, oz, x, y, z)
end

function mouseAnimationEndCamera()
-- animation end
end

function PlayerSpecOnElement(spec, distance)
	if spec == nil or distance == nil or spec == "None" then
		specon = nil
		specdis = 0
		return 1
	end
	if specon then
		removeEventHandler("onClientRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
	end
	specon = spec
	specdis = distance
	addEventHandler("onClientRender", getRootElement(), RenderVeiw)
	addEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
end

addEvent("setPlayerSpecOnElement", true)
addEventHandler("setPlayerSpecOnElement", getRootElement(), PlayerSpecOnElement)

triggerClientEvent(player, "setPlayerSpecOnElement", getRootElement(), element, lookDistance)
PlayerSpecOnElement(element, lookDistance)

Have fun ~NOT TESTED~

Link to comment
2 hours ago, orel56000 said:

Have fun ~NOT TESTED~

It didn't work at first but when I removed the 'ticks2' variable it worked fine. All I needed was "if dis1 < speed then". Now I'll try to set the camera's Z position according to the car's rear position. Currently it keeps the same Z position even if car goes down a hill for example (isn't pointing directly at it's back, but is below the gta textures sometimes). Hope I can do that alone :D, if not I'll reply here again. Thank you for everything!

Link to comment

Here's an updated code if anyone needs it. With it you can use Q and E (and both) just like in normal spectating. Q - look left of vehicle, E - look right of vehicle and Q+E - look infront of vehicle:

local AngX, AngZ, specDist, specTarget, ticks, speed, fixedCam = 0, 0, 0, nil, 0, 0.8, true
-------------------------------------------------------------------------------------------------------------------------
function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() and not isMTAWindowActive() and getKeyState("Q") == false and getKeyState("E") == false then
		fixedCam = false
		local sx, sy = guiGetScreenSize()
		ticks = getTickCount()
		AngX = (AngX + (x - (sx / 2)) / 10) % 360
		AngZ = (AngZ + (y - (sy / 2)) / 10) % 360
		if AngZ > 180 then
			if AngZ < 315 then
				AngZ = 315
			end
		else
			if AngZ > 45 then
				AngZ = 45
			end
		end
	end
end
-------------------------------------------------------------------------------------------------------------------------
function RenderVeiw()
	local ox, oy, oz
	local x, y, z
	local savedDis1
	local savedSpeed
	if specTarget then
		x, y, z = getElementPosition(specTarget)
	end
	if x and y and z and AngX and AngZ and specDist then
		if getKeyState("Q") == true and getKeyState("E") == false and not isCursorShowing() and not isMTAWindowActive() then
			local rx, ry, rz = getElementRotation(specTarget)
			local dis = AngX - (270 - rz)
			local dis1 = math.abs(dis)
			if dis1 > 30 then
				if speed < 4 then
					speed = speed + 0.4
				end
			elseif dis1 < 30 then
				if speed > 0.8 then
					speed = speed - 0.4
				end
			elseif dis1 > speed then
				dis = dis / (dis1 / speed)
			end
			savedDis1 = dis1
			savedSpeed = speed
			fixedCam = true
			AngX = AngX - dis
		elseif getKeyState("Q") == false  and getKeyState("E") == true and not isCursorShowing() and not isMTAWindowActive() then
			local rx, ry, rz = getElementRotation(specTarget)
			local dis = AngX - (90 - rz)
			local dis1 = math.abs(dis)
			if dis1 > 30 then
				if speed < 4 then
					speed = speed + 0.4
				end
			elseif dis1 < 30 then
				if speed > 0.8 then
					speed = speed - 0.4
				end
			elseif dis1 > speed then
				dis = dis / (dis1 / speed)
			end
			savedDis1 = dis1
			savedSpeed = speed
			fixedCam = true
			AngX = AngX - dis
		elseif getKeyState("Q") == true and getKeyState("E") == true and not isCursorShowing() and not isMTAWindowActive() then
			local rx, ry, rz = getElementRotation(specTarget)
			local dis = AngX - (180 - rz)
			local dis1 = math.abs(dis)
			if dis1 > 30 then
				if speed < 4 then
					speed = speed + 0.4
				end
			elseif dis1 < 30 then
				if speed > 0.8 then
					speed = speed - 0.4
				end
			elseif dis1 > speed then
				dis = dis / (dis1 / speed)
			end
			savedDis1 = dis1
			savedSpeed = speed
			fixedCam = true
			AngX = AngX - dis
		elseif getKeyState("Q") == false and getKeyState("E") == false then
			if ticks + 1500 < getTickCount() then
				local rx, ry, rz = getElementRotation(specTarget)
				local dis = AngX - (360 - rz)
				local dis1 = math.abs(dis)
				if fixedCam == false then
					if dis1 > 30 then
						if speed < 4 then
							speed = speed + 0.4
						end
					end
					if dis1 < 30 then
						if speed > 0.8 then
							speed = speed - 0.4
						end
					end
					if dis1 > speed then
						dis = dis / (dis1 / speed)
					end
					if dis1 < speed then
						fixedCam = true
					end
				end
				if fixedCam == true then
					if dis1 > 30 then
						if speed < 4 then
							speed = speed + 0.4
						end
					elseif dis1 < 30 then
						if speed > 0.8 then
							speed = speed - 0.4
						end
					elseif dis1 > speed then
						dis = dis / (dis1 / speed)
					end
				end
				savedDis1 = dis1
				savedSpeed = speed
				AngX = AngX - dis
			end
		end
		if isCursorShowing() or isMTAWindowActive() then
			if ticks + 1500 < getTickCount() then
				if savedDis1 < savedSpeed then
					fixedCam = true
				end
			end
		end
		ox = x - math.sin(math.rad(AngX)) * specDist
		oy = y - math.cos(math.rad(AngX)) * specDist
		oz = z + math.tan(math.rad(AngZ)) * specDist + 2
		setCameraMatrix(ox, oy, oz, x, y, z)
	end
end
-------------------------------------------------------------------------------------------------------------------------
addEvent("setPlayerSpecOnElement", true)
function PlayerSpecOnElement(target, distance)
	if target == nil or distance == nil or target == "None" then
		if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then
			removeEventHandler("onClientCursorMove", root, MoveMouse)
			movedMouse = false
		end
		if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then 
			removeEventHandler("onClientRender", root, RenderVeiw)
		end
		specTarget = nil
		specDist = 0
		return 1
	end
	if specTarget then
		if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then
			removeEventHandler("onClientCursorMove", root, MoveMouse)
			movedMouse = false
		end
		if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then 
			removeEventHandler("onClientRender", root, RenderVeiw)
		end
	end
	specTarget = target
	specDist = distance
	if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then
		removeEventHandler("onClientCursorMove", root, MoveMouse)
		movedMouse = false
	end
	if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == false then
		addEventHandler("onClientCursorMove", root, MoveMouse)
		movedMouse = true
	end
	if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then 
		removeEventHandler("onClientRender", root, RenderVeiw)
	end
	if isEventHandlerAdded("onClientRender", root, RenderVeiw) == false then 
		addEventHandler("onClientRender", root, RenderVeiw)
	end
end
addEventHandler("setPlayerSpecOnElement", root, PlayerSpecOnElement)
-------------------------------------------------------------------------------------------------------------------------
function isEventHandlerAdded(sEventName, pElementAttachedTo, func)
	if type(sEventName) == "string" and isElement(pElementAttachedTo) and type(func) == "function" then
		local aAttachedFunctions = getEventHandlers(sEventName, pElementAttachedTo)
		if type(aAttachedFunctions) == "table" and #aAttachedFunctions > 0 then
			for i, v in ipairs(aAttachedFunctions) do
				if v == func then
					return true
				end
			end
		end
	end
	return false
end
------------------------------------------------------------------------------------------------------------------------
function getAll(name)
	local result = {}
	for i,element in ipairs(getElementsByType(name)) do
		result[i] = {}
		result[i].id = getElementID(element) or i
		local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) }
		local rotation = 0
		if getElementData(element,"rotation") then
		    rotation = tonumber(getElementData(element,"rotation"))
		elseif getElementData(element,"rotZ") then
		    rotation = tonumber(getElementData(element,"rotZ"))
		end
		local vehicle = tonumber(getElementData(element,"vehicle"))
		result[i].position = position;
		result[i].rotation = rotation;
		result[i].vehicle = vehicle;
	end
	return result
end

But I still can't figure out how to automatically fix the Z position of the camera :( If you know the maths behind it (you knew how to fix the X position to always be at the car's back) I'd be grateful if you tell me how to achieve this as well :) The camera just stays at one Z position, even if the vehicle is going up or down a hill and it looks bad. Need it to always stay behind the car just like it does on a normal straight road.

Link to comment

Here's a video explaining the problem better:

As you see in the first 50 seconds of the video the camera is behind the car. But from around 0:55 when the car goes up the hill the camera does not stay behind it but goes ontop of it.Also on 1:05 you can clearly see how the camera goes under the GTA textures because it does not stay behind the car, but this time is under it as it's going downhill. Could somebody please help me out with a code or formula so that the camera will stay always behind the car, thus avoiding those under-texture peaks and ontop-of-car weird look. It should always be focused at the back of the car as it is on a straight road from the start of the video until around 0:50. This is the full code for the camera function:

local AngX, AngZ, specDist, specTarget, ticks, speed, fixedCam, isMinimized = 0, 0, 0, nil, 0, 0.8, true, false
-------------------------------------------------------------------------------------------------------------------------
function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() and not isMTAWindowActive() and getKeyState("Q") == false and getKeyState("E") == false and getKeyState("mouse3") == false and isMinimized == false then
		fixedCam = false
		local sx, sy = guiGetScreenSize()
		ticks = getTickCount()
		AngX = (AngX + (x - (sx / 2)) / 10) % 360
		AngZ = (AngZ + (y - (sy / 2)) / 10) % 360
		if AngZ > 180 then
			if AngZ < 315 then
				AngZ = 315
			end
		else
			if AngZ > 45 then
				AngZ = 45
			end
		end
	end
end
-------------------------------------------------------------------------------------------------------------------------
function RenderVeiw()
	local ox, oy, oz
	local x, y, z
	local savedDis1
	local savedSpeed
	if specTarget then
		x, y, z = getElementPosition(specTarget)
	end
	if x and y and z and AngX and AngZ and specDist then
		if getKeyState("Q") == true and getKeyState("E") == false and getKeyState("mouse3") == false and not isCursorShowing() and not isMTAWindowActive() then
			local rx, ry, rz = getElementRotation(specTarget)
			local dis = AngX - (270 - rz)
			local dis1 = math.abs(dis)
			if dis1 > 30 then
				if speed < 4 then
					speed = speed + 0.4
				end
			elseif dis1 < 30 then
				if speed > 0.8 then
					speed = speed - 0.4
				end
			elseif dis1 > speed then
				dis = dis / (dis1 / speed)
			end
			savedDis1 = dis1
			savedSpeed = speed
			fixedCam = true
			AngX = AngX - dis
		elseif getKeyState("Q") == false  and getKeyState("E") == true and getKeyState("mouse3") == false and not isCursorShowing() and not isMTAWindowActive() then
			local rx, ry, rz = getElementRotation(specTarget)
			local dis = AngX - (90 - rz)
			local dis1 = math.abs(dis)
			if dis1 > 30 then
				if speed < 4 then
					speed = speed + 0.4
				end
			elseif dis1 < 30 then
				if speed > 0.8 then
					speed = speed - 0.4
				end
			elseif dis1 > speed then
				dis = dis / (dis1 / speed)
			end
			savedDis1 = dis1
			savedSpeed = speed
			fixedCam = true
			AngX = AngX - dis
		elseif ((getKeyState("Q") == true and getKeyState("E") == true) or getKeyState("mouse3") == true) and not isCursorShowing() and not isMTAWindowActive() then
			local rx, ry, rz = getElementRotation(specTarget)
			local dis = AngX - (180 - rz)
			local dis1 = math.abs(dis)
			if dis1 > 30 then
				if speed < 4 then
					speed = speed + 0.4
				end
			elseif dis1 < 30 then
				if speed > 0.8 then
					speed = speed - 0.4
				end
			elseif dis1 > speed then
				dis = dis / (dis1 / speed)
			end
			savedDis1 = dis1
			savedSpeed = speed
			fixedCam = true
			AngX = AngX - dis
		elseif ((getKeyState("Q") == false and getKeyState("E") == false) or getKeyState("mouse3") == false) then
			if ticks + 1500 < getTickCount() then
				local rx, ry, rz = getElementRotation(specTarget)
				local dis = AngX - (360 - rz)
				local zDis = AngZ - (360 - rz)
				local dis1 = math.abs(dis)
				if fixedCam == false then
					if dis1 > 30 then
						if speed < 4 then
							speed = speed + 0.4
						end
					end
					if dis1 < 30 then
						if speed > 0.8 then
							speed = speed - 0.4
						end
					end
					if dis1 > speed then
						dis = dis / (dis1 / speed)
					end
					if dis1 < speed then
						fixedCam = true
					end
				end
				if fixedCam == true then
					if dis1 > 30 then
						if speed < 4 then
							speed = speed + 0.4
						end
					elseif dis1 < 30 then
						if speed > 0.8 then
							speed = speed - 0.4
						end
					elseif dis1 > speed then
						dis = dis / (dis1 / speed)
					end
				end
				savedDis1 = dis1
				savedSpeed = speed
				AngX = AngX - dis
			end
		end
		if isCursorShowing() or isMTAWindowActive() then
			if ticks + 1500 < getTickCount() then
				if savedDis1 and savedSpeed and savedDis1 < savedSpeed then
					fixedCam = true
				end
			end
		end
		ox = x - math.sin(math.rad(AngX)) * specDist
		oy = y - math.cos(math.rad(AngX)) * specDist
		oz = z + math.tan(math.rad(AngZ)) * specDist + 2
		setCameraMatrix(ox, oy, oz, x, y, z)
	end
end
-------------------------------------------------------------------------------------------------------------------------
addEvent("setPlayerSpecOnElement", true)
function PlayerSpecOnElement(target, distance)
	if target == nil or distance == nil or target == "None" then
		if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then
			removeEventHandler("onClientCursorMove", root, MoveMouse)
			movedMouse = false
		end
		if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then 
			removeEventHandler("onClientRender", root, RenderVeiw)
		end
		specTarget = nil
		specDist = 0
		return 1
	end
	if specTarget then
		if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then
			removeEventHandler("onClientCursorMove", root, MoveMouse)
			movedMouse = false
		end
		if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then 
			removeEventHandler("onClientRender", root, RenderVeiw)
		end
	end
	specTarget = target
	specDist = distance
	if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == true then
		removeEventHandler("onClientCursorMove", root, MoveMouse)
		movedMouse = false
	end
	if isEventHandlerAdded("onClientCursorMove", root, MoveMouse) == false then
		addEventHandler("onClientCursorMove", root, MoveMouse)
		movedMouse = true
	end
	if isEventHandlerAdded("onClientRender", root, RenderVeiw) == true then 
		removeEventHandler("onClientRender", root, RenderVeiw)
	end
	if isEventHandlerAdded("onClientRender", root, RenderVeiw) == false then 
		addEventHandler("onClientRender", root, RenderVeiw)
	end
end
addEventHandler("setPlayerSpecOnElement", root, PlayerSpecOnElement)

 

Link to comment

As for your problem:

- use attachElements instead of setMatrix (it won't shake)

- to sovle camera rotation, usssh.... it requires quite harsh 3D Vector manipulations. You have to use Vector to keep camera position relative to vehicle, then rotate it on mouse movement and transform from global coordinates to vehicle local coordinates, meanwhile moving it back to target position (which has to be updated with vehicle x rotation) when no mouse movement happens. I made custom camera this way for my project, but it uses modified vectors, so I don't really know any easy way to help you.

Link to comment

At first I did it with attachElements but the camera couldn't be moved by mouse then. Anyway, the shake is from the race_ghost resource, it lags even when not spectating it :D. Can you have a look at the code I posted and see how the X position is fixed? I think @orel56000 fixed it.(OK, it was @idan1432) Maybe something similar for the Z one (though I tried and meh)? Problem's that I'm not that good at maths stuff (like Vectors, etc) otherwise I'd do it myself but can't do anything with such calculations :( And if not, thanks for trying atleast :) 

Edited by koragg
Link to comment

@koragg try this:

local AngX, AngZ, specdis, ticks, ticks2, speed, specon = 0, 0, 0, 0, 1, 0.8, nil

function MoveMouse(rx, ry, x, y)
	if not isCursorShowing() then
		local sx, sy = guiGetScreenSize()
		ticks = getTickCount()
		ticks2 = 1
		AngX = (AngX + (x - (sx/2))/10) % 360
		AngZ = (AngZ + (y - (sy/2))/10) % 360
		if AngZ > 180 then
			if AngZ < 315 then AngZ = 315 end
		else
			if AngZ > 45 then AngZ = 45 end
		end
	end
end
function RenderVeiw()
	if not specon then
		removeEventHandler("onClientPreRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
		return 1
	end
	local ox, oy, oz
	local x, y, z = getElementPosition(specon)
	if ticks+10000 < getTickCount() then
		local fixAngle = 360
		if getKeyState("Q") == true then fixAngle = 270 end
		if getKeyState("E") == true then fixAngle = 90 end
		if getKeyState("Q") == true and getKeyState("E") == true or getKeyState("mouse3") == true then fixAngle = 180 end
		local rx, ry, rz = getElementRotation(specon)
		local dis = AngX-(fixAngle-rz)
		local dis1 = math.abs(dis)
		local zdis = (35-AngZ)
		if AngZ < 360 and AngZ > 270 then zdis = 35+(360-AngZ) end
		if math.abs(zdis) > speed then zdis = zdis*(speed/math.abs(zdis)) end
		if dis1 > 30 then
			if speed < 4 then speed = speed + 0.8 end
		end
		if dis1 < 30 then
			if speed > 0.8 then speed = speed - 0.8 end
		end
		if dis1 > speed then dis = dis*(speed/dis1) end
		if dis1 < speed and math.abs(zdis) < speed and ticks2 == 1 then
			ticks2 = 0
			triggerEvent("mouseAnimationEndCamera", getRootElement())
		end
		AngX = AngX - dis
		AngZ = AngZ + zdis
	end
	ox = x - math.sin(math.rad(AngX)) * specdis
	oy = y - math.cos(math.rad(AngX)) * specdis
	oz = z + math.tan(math.rad(AngZ)) * specdis
	setCameraMatrix(ox, oy, oz, x, y, z)
end

function mouseAnimationEndCamera()
-- animation end
end

function PlayerSpecOnElement(spec, distance)
	if spec == nil or distance == nil or spec == "None" then
		specon = nil
		specdis = 0
		return 1
	end
	if specon then
		removeEventHandler("onClientPreRender", getRootElement(), RenderVeiw)
		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
	end
	specon = spec
	specdis = distance
	addEventHandler("onClientPreRender", getRootElement(), RenderVeiw)
	addEventHandler("onClientCursorMove", getRootElement(), MoveMouse)
end

addEvent("setPlayerSpecOnElement", true)
addEventHandler("setPlayerSpecOnElement", getRootElement(), PlayerSpecOnElement)

and tell me if it work

Edited by idan1432
Link to comment
1 hour ago, idan1432 said:

@koragg try this:


local AngX, AngZ, specdis, ticks, ticks2, speed, specon = 0, 0, 0, 0, 1, 0.8, nilfunction MoveMouse(rx, ry, x, y)	if not isCursorShowing() then		local sx, sy = guiGetScreenSize()		ticks = getTickCount()		ticks2 = 1		AngX = (AngX + (x - (sx/2))/10) % 360		AngZ = (AngZ + (y - (sy/2))/10) % 360		if AngZ > 180 then			if AngZ < 315 then AngZ = 315 end		else			if AngZ > 45 then AngZ = 45 end		end	endendfunction RenderVeiw()	if not specon then		removeEventHandler("onClientPreRender", getRootElement(), RenderVeiw)		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)		return 1	end	local ox, oy, oz	local x, y, z = getElementPosition(specon)	if ticks+10000 < getTickCount() then		local fixAngle = 360		if getKeyState("Q") == true then fixAngle = 270 end		if getKeyState("E") == true then fixAngle = 90 end		if getKeyState("Q") == true and getKeyState("E") == true or getKeyState("mouse3") == true then fixAngle = 180 end		local rx, ry, rz = getElementRotation(specon)		local dis = AngX-(fixAngle-rz)		local dis1 = math.abs(dis)		local zdis = (35-AngZ)		if AngZ < 360 and AngZ > 270 then zdis = 35+(360-AngZ) end		if math.abs(zdis) > speed then zdis = zdis*(speed/math.abs(zdis)) end		if dis1 > 30 then			if speed < 4 then speed = speed + 0.8 end		end		if dis1 < 30 then			if speed > 0.8 then speed = speed - 0.8 end		end		if dis1 > speed then dis = dis*(speed/dis1) end		if dis1 < speed and math.abs(zdis) < speed and ticks2 == 1 then			ticks2 = 0			triggerEvent("mouseAnimationEndCamera", getRootElement())		end		AngX = AngX - dis		AngZ = AngZ + zdis	end	ox = x - math.sin(math.rad(AngX)) * specdis	oy = y - math.cos(math.rad(AngX)) * specdis	oz = z + math.tan(math.rad(AngZ)) * specdis	setCameraMatrix(ox, oy, oz, x, y, z)endfunction mouseAnimationEndCamera()-- animation endendfunction PlayerSpecOnElement(spec, distance)	if spec == nil or distance == nil or spec == "None" then		specon = nil		specdis = 0		return 1	end	if specon then		removeEventHandler("onClientPreRender", getRootElement(), RenderVeiw)		removeEventHandler("onClientCursorMove", getRootElement(), MoveMouse)	end	specon = spec	specdis = distance	addEventHandler("onClientPreRender", getRootElement(), RenderVeiw)	addEventHandler("onClientCursorMove", getRootElement(), MoveMouse)endaddEvent("setPlayerSpecOnElement", true)addEventHandler("setPlayerSpecOnElement", getRootElement(), PlayerSpecOnElement)

and tell me if it work

Sadly it didn't. But I noticed that you tried to fix it only by using 'AngZ'. Isn't the 'AngZ' variable used while moving mouse? The problem in video is that without moving mouse, the camera does not go up/down a bit so that those glitches can be avoided.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...