Jump to content

[Solved] Ped lighting


Kayl

Recommended Posts

Hey there,

I'm fighting with ped lighting.

After doing some tests, it seems that peds are created with no light-set.

If you warp them to a vehicle or freeze them, they will stay black.

They seem to only gain normal colors when having physically touched the ground at least once.

Test code:

local g_Peds = nil
function pedTest()
 
if g_Peds then
for ped,pedData in pairs(g_Peds) do
destroyElement(ped)
destroyElement(pedData.marker)
end
removeEventHandler("onClientPreRender", g_Root, onPedTestPreRender)
	g_Peds = nil
else
	g_Peds = {}
setTime(12, 0)
setWeather(0)
local x, y, z = -1287.0609130859, -84.415733337402
local tHeight = {14.14, 17}
local tFreeze = {"none", "mta", "manual"}
for _,freeze in ipairs(tFreeze) do
for _,height in ipairs(tHeight) do
local pedData = {}
			pedData.x = x
			pedData.y = y
			pedData.z = height
			pedData.freeze = freeze
local r, g, b = 0, 0, 0
if freeze == "none" then
				r, g, b = 255, 0, 0
elseif freeze == "mta" then
				r, g, b = 0, 255, 0
elseif freeze == "manual" then
				r, g, b = 0, 0, 255
end
			pedData.marker = createMarker(x, y, height+2, "arrow", 1, r, g, b, 255)
local ped = createPed(70, x, y, height)
if pedData.freeze == "mta" then
				setPedFrozen(ped, true)
end
			g_Peds[ped] = pedData
			y = y + 2
end
end
 
addEventHandler("onClientPreRender", g_Root, onPedTestPreRender)
end
end
addCommandHandler("pedtest", pedTest)
 
function onPedTestPreRender()
setTime(12, 0)
setWeather(0)
 
for ped, pedData in pairs(g_Peds) do
if pedData.freeze == "manual" then
setElementPosition(ped, pedData.x, pedData.y, pedData.z)
end
end
end

Screenshots:

Colors: blue = manually frozen (onClientPreRender), green = setPedFrozen, red = not frozen at all

Starting conditions: all peds created at ground level are lit correctly, others aren't.

9pnb55.png

The second ped from the right finally touched the ground and is now correctly lit

10gwp46.png

The setPedFrozen isn't perfect and the green dude shakes like hell (not seen on still image) and slowly but utterly approaches the ground

28hie04.png

The shaking dude, in his shaking nightmare, has touched the ground a tiny bit and therefore gained a tiny bit of correct light

2q22xiu.png

So, is there a way to fix that and make all the peds have correct lighting?

Edited by Guest
Link to comment

No, this is a bug. Not 100% sure if GTA's bug though. It also happens when player walks on custom models (can't remember if it's due to wrong collision data or vertex colour).

All you can do is spawn the ped on the ground and move him where you want him to be. As you mentioned, it makes ped lit properly since he/she first touches the ground.

Link to comment

I'm not really sure that's a GTA bug, as I always see no shakes to some things like GTA SA's interior markers.

Maybe it can be a bug only if you put the marker on something which is above the ground and before falling onto the ground.

I also agree to some of 50p's point though. Best way is to put the marker after the ped is on the ground instead.

PS: hmm, you must be kayl, the great scripter of the DKR Clan? Wow! I also really liked the server! Damn awesome scripts! :P

Link to comment

@xxx3

Sorry I don't really understand your answer.

The markers here are just to highlight where each ped was original created and what freeze method is used for each. The shaking mentioned is affecting the "ped under the green marker" only because of its freeze method.

Thank you for your comment on DKR Clan's scripts. :lol:

@50p

I feared you might answer that. It makes the ped creation "asynchronous" but I guess it's the price you have to pay to get this ped lighting working. I have modified the previous code in order to create the pink peds at ground level and then after 1sec only freeze them where expected:

local g_Peds = nil
function pedTest()
 
if g_Peds then
for ped,pedData in pairs(g_Peds) do
destroyElement(ped)
destroyElement(pedData.marker)
end
removeEventHandler("onClientPreRender", g_Root, onPedTestPreRender)
	g_Peds = nil
else
	g_Peds = {}
setTime(12, 0)
setWeather(0)
local x, y, z = -1287.0609130859, -84.415733337402
local tHeight = {14.14, 17}
local tFreeze = {"none", "mta", "manual", "ground_created"}
for _,freeze in ipairs(tFreeze) do
for _,height in ipairs(tHeight) do
local pedData = {}
			pedData.x = x
			pedData.y = y
			pedData.z = height
			pedData.freeze = freeze
local r, g, b = 0, 0, 0
if freeze == "none" then
				r, g, b = 255, 0, 0
elseif freeze == "mta" then
				r, g, b = 0, 255, 0
elseif freeze == "manual" then
				r, g, b = 0, 0, 255
elseif freeze == "ground_created" then
				r, g, b = 255, 0, 255
				pedData.realZ = pedData.z
				pedData.z = 14.14
end
			pedData.marker = createMarker(x, y, height+2, "arrow", 1, r, g, b, 255)
local ped = createPed(70, pedData.x, pedData.y, pedData.z)
if pedData.freeze == "mta" then
				setPedFrozen(ped, true)
elseif pedData.freeze == "ground_created" then
setElementPosition(ped, pedData.x, pedData.y, pedData.z)
				setPedFrozen(ped, true)
				pedData.ticks = getTickCount()
end
			g_Peds[ped] = pedData
			y = y + 2
end
end
 
addEventHandler("onClientPreRender", g_Root, onPedTestPreRender)
end
end
addCommandHandler("pedtest", pedTest)
 
 
function onPedTestPreRender()
setTime(12, 0)
setWeather(0)
 
local now = getTickCount()
 
for ped, pedData in pairs(g_Peds) do
if pedData.freeze == "manual" then
setElementPosition(ped, pedData.x, pedData.y, pedData.z)
elseif pedData.freeze == "ground_created" then
if (now - pedData.ticks) > 1000 then
			pedData.z =  pedData.realZ
			pedData.freeze = "manual"
setElementPosition(ped, pedData.x, pedData.y, pedData.z)
end
end
end
end

And indeed it works:

2mmckkz.png

I then modified the code again to be able to create those peds in front of the camera instead of in predefined positions.

The temporary position of the ped is the ground position found under the camera.

This works when the ground is near:

21es02b.png

But when the camera is up in the sky it doesn't:

It might be because no ground data is actually found or the ped put temporarily at ground level is not even streamed-in so the trick doesn't work:

i6dyyp.png

I guess I will therefore try the following to have something that works all the time:

- fade camera to black

- put it at a predefined position looking at the ground

- wait for collision data to be loaded (watching processLineOfSight on the known expected ground position)

- create the ped

- wait 1 sec

- move the camera & ped where they ought to be placed in the first place

- unfade the camera

This is not a solution that would work for everyone but for what I want to do I can tolerate a "loading" time.

I'll edit my post or post a new one to comment on the success/failure of the aforementioned procedure.

Edit

Ok since there was no reply I can edit my post to avoid double post.

I have implemented the procedure I mentioned and this allows the creation of a correctly lit ped very high up in the sky.

I have also added a ped next to it, created there to show that this one remains, as expected, black.

local g_PedTest = nil
function pedTest3()
if g_PedTest then
if g_PedTest.ped then
destroyElement(g_PedTest.ped)
end
if g_PedTest.ped2 then
destroyElement(g_PedTest.ped2)
end
if g_PedTest.cameraTarget then
setCameraTarget(g_PedTest.cameraTarget)
elseif g_PedTest.initialcameraMatrix then
setCameraMatrix(unpack(g_PedTest.initialcameraMatrix))
end
if g_PedTest.cameraFaded then
fadeCamera(true)
end
removeEventHandler("onClientPreRender", g_Root, onRealPedTestPreRender)
	g_PedTest = nil
else
	g_PedTest = {}
setTime(12, 0)
setWeather(0)
	g_PedTest.cameraTarget = getCameraTarget()
if not g_PedTest.cameraTarget then
		g_PedTest.initialcameraMatrix = {getCameraMatrix()}
end
fadeCamera(false, 0)
	g_PedTest.cameraFaded = true
	g_PedTest.cameraMatrix = {4, 4, 4, 0, 0, 2, 0, 70}
setCameraMatrix(unpack(g_PedTest.cameraMatrix))
	g_PedTest.state = "waiting_ground"
 
	g_PedTest.ped2Data = {1002, -45, 2000}
	g_PedTest.ped2 = createPed(70, unpack(g_PedTest.ped2Data))
 
addEventHandler("onClientPreRender", g_Root, onRealPedTestPreRender)
end
end
addCommandHandler("pedtest3", pedTest3)
 
function onRealPedTestPreRender()
setTime(12, 0)
setWeather(0)
 
setCameraMatrix(unpack(g_PedTest.cameraMatrix))
 
if g_PedTest.state and g_PedTest.state == "waiting_ground" then
local hit, hitx, hity, hitz = processLineOfSight(0, 0, 10, 0, 0, -10, true, false, false, false)
if hit then
		g_PedTest.ped = createPed(70, 0, 0, 3.11)
		setPedFrozen(g_PedTest.ped, true)
		g_PedTest.state = "waiting_ped"
		g_PedTest.ticks = getTickCount()
end
elseif g_PedTest.state == "waiting_ped" then
local now = getTickCount()
if (now - g_PedTest.ticks) > 1000 then
		g_PedTest.pedData = {1000, -45, 2000}
		g_PedTest.cameraMatrix = {1000, -40, 2002, 1000, -45, 2000, 0, 70}
setCameraMatrix(unpack(g_PedTest.cameraMatrix))
setElementPosition(g_PedTest.ped, unpack(g_PedTest.pedData))
if g_PedTest.cameraFaded then
fadeCamera(true, 1.0)
			g_PedTest.cameraFaded = false
end
end
else
setElementPosition(g_PedTest.ped, unpack(g_PedTest.pedData))
end
 
setElementPosition(g_PedTest.ped2, unpack(g_PedTest.ped2Data))
end

fnv8z7.png

The whole process only takes 1 second (safety time for the ped to light up correctly) and it's suitable for my needs.

So thanks for the input, I consider my problem solved.

Edit2: Tips for someone willing to reproduce the above code, it's important for the local player to also be placed in interior 0 or else the collision data won't be streamed-in and the processLineOfSight will always fail (at least in 1.0.3)

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...