Attempt to perform arithmatic on a nil value

Hi there everyone!

I’m trying to work on a resource that uses coords in a bunch of places and I thought I’d be clever and use the variables instead, so At the top, the the blip coords are set:

local blips = {
    {
		title=	"Chiliad Mountain Race",
		colour=	5,
		id=		315,
		x= 		-799.41,
		y=		5401.71,
		z=		34.21
	}
}

And further down, I tried to use blips.x, y and z :

DrawMarker(1, blips.x, blips.y, blips.z - 1, 0, 0, 0, 0, 0, 0, 3.0001, 3.0001, 1.5001, 255, 165, 0,165, 0, 0, 0,0)

But I got the error that z was a nil value. It didn’t say anything about x or y, which was odd.

Can someone tell me what I’ve done wrong that the script isn’t recognizing blips.z?

Thanks for your time!

Does it work if you don’t do the minus 1? Try doing minus 1.0. I’ve run into some issues with Lua between integers and floats/doubles.

Hmmm might have to try -1.0 or (blips.z - 1.0),

Hi there guys, thanks for your help!

I tried 1.0 but it’s still telling me that field z is a nil value. New line:

DrawMarker(1, blips.x, blips.y, blips.z - 1.0, 0, 0, 0, 0, 0, 0, 3.0001, 3.0001, 1.5001, 255, 165, 0,165, 0, 0, 0,0)

Any thoughts on what else I should try?

Dump the X value right in the line, make sure it’s not something else that’s throwing it off.

What displays if you do print(tonumber(blips.z)) above that line? Is it seeing blips.z and having issues with arithmetic? Like @hallux said, you could try in parentheses or with tonumber(blips.z - 1.0) to force the result to return a number.

I did as instructed and it moved the error to the next line using blips.z:

Draw3DText( blips.x, blips.y, blips.z  +.500, "Chiliad",7,0.3,0.2)

So it seems blips.z is not being recognized as a variable. What am I doing wrong to make that occur?

Stop trying to add shit to the Z… instead, just put it in with a direct number and see if you can at least get it to work properly.

DrawMarker(1, blips.x, blips.y, 34.21, 0, 0, 0, 0, 0, 0, 3.0001, 3.0001, 1.5001, 255, 165, 0,165, 0, 0, 0,0)

That’s what I did, hallux. When I did that, it moved the error to the next line with blips.z in it.

Also, are you iterating this with a loop? What’s that loop look like?
Lua can be strange at times, but most of the time it’s something minor you missed.

Give us the whole code.

This is the entire client.lua which is all the script consists of. All of blips.z has been replaced with the actual value, which got rid of the errors in the log but the script still doesn’t work. I’m not sure what else is causing problems.

--Pringus race script (probably more accurately a time trial script)
--todo: add laps?

function LocalPed()
	return GetPlayerPed(-1)
end
 
--Edit the xyz coords of this blip to change the starting line for the race

local blips = {
    {
		title=	"Chiliad Mountain Race",
		colour=	5,
		id=		315,
		x= 		-799.41,
		y=		5401.71,
		z=		34.21
	}
}


local IsRacing = false 
local cP = 1
local cP2 = 2
local checkpoint
local blip
local startTime

--[[

Add checkpoints using the formatting:
CheckPoints[1] =  	{ x = 0, y = 0, z = 0, type = 5}
Number in brackets is the number of the checkpoint (CheckPoints[1] would be the first 
checkpoint in the race)
Change the checkpoint type to determine whether or not it will be a checkpoint or
the finish line. type = 5 for regular checkpoints, type = 9 for the finish.

The example race is in North Yankton.

]]
local CheckPoints = {}
CheckPoints[1] =  	{ x = -704.72, y = 5401.20, z =  34.21, type = 5}
CheckPoints[2] =	{ x = -707.56, y = 5286.41, z =  72.79, type = 5}
CheckPoints[3] =	{ x = -637.18, y = 5209.41, z =  82.33, type = 5}
CheckPoints[4] =	{ x = -570.84, y = 5053.54, z = 132.13, type = 5}
CheckPoints[5] =	{ x = -381.00, y = 4908.91, z = 193.61, type = 5}
CheckPoints[6] =	{ x = -301.82, y = 4970.74, z = 243.78, type = 5}
CheckPoints[7] =	{ x = -219.58, y = 4902.72, z = 314.37, type = 5}
CheckPoints[8] =	{ x =  -94.44, y = 4938.72, z = 378.89, type = 5}
CheckPoints[9] =	{ x =   16.47, y = 5028.70, z = 451.93, type = 5}
CheckPoints[10] =  	{ x =   99.42, y = 5088.46, z = 502.69, type = 5}
CheckPoints[11] =  	{ x =  134.96, y = 5213.44, z = 546.21, type = 5}
CheckPoints[12] =  	{ x =  230.67, y = 5300.07, z = 619.84, type = 5}
CheckPoints[13] =	{ x =  402.28, y = 5504.77, z = 728.41, type = 5}
CheckPoints[14] =  	{ x =  523.91, y = 5615.44, z = 780.27, type = 9}
CheckPoints[15] =  	{ x =  523.91, y = 5615.44, z = 780.27, type = 9}

Citizen.CreateThread(function()
    preRace()
end)

function preRace()
    while not IsRacing do
        Citizen.Wait(0)
            --[[if (IsControlJustReleased(1, 47)) then
                SetPedCoordsKeepVehicle(LocalPed(), 3103.01, -4826.48, 111.81)
                TriggerServerEvent("printPlayers")
            end]]
            DrawMarker(1, blips.x, blips.y, 34.21 - 1.0, 0, 0, 0, 0, 0, 0, 3.0001, 3.0001, 1.5001, 255, 165, 0,165, 0, 0, 0,0)
        if GetDistanceBetweenCoords( blips.x, blips.y, 34.21, GetEntityCoords(LocalPed())) < 50.0 then
            	Draw3DText( blips.x, blips.y, 34.21  +.500, "Chiliad",7,0.3,0.2)
            	Draw3DText( blips.x, blips.y, 34.21  +.100, "Mountain",7,0.3,0.2)
        end
        if GetDistanceBetweenCoords( blips.x, blips.y, 34.21, GetEntityCoords(LocalPed())) < 2.0 then
            TriggerEvent("fs_freemode:displayHelp", "Press ~INPUT_CONTEXT~ to Race!")
            if (IsControlJustReleased(1, 38)) then
                if IsRacing == false then
                    IsRacing = true
                    TriggerEvent("cRace:TPAll")
                else
                    return
                end
            end
        end
    end
end

RegisterNetEvent("cRace:TPAll")
AddEventHandler("cRace:TPAll", function()
    SetPedCoordsKeepVehicle(PlayerPedId(), blips.x, blips.y, 34.21)
    SetEntityHeading(PlayerPedId(), 265.0)
    Citizen.CreateThread(function()
        local time = 0
        function setcountdown(x)
          time = GetGameTimer() + x*1000
        end
        function getcountdown()
          return math.floor((time-GetGameTimer())/1000)
        end
        setcountdown(6)
        while getcountdown() > 0 do
            Citizen.Wait(1)
            
            --how the hell do I disable controls?

            DrawHudText(getcountdown(), {255,191,0,255},0.5,0.4,4.0,4.0)
        end
            TriggerEvent("fs_race:BeginRace")
    end)
end)

RegisterNetEvent("fs_race:BeginRace") --main loop
AddEventHandler("fs_race:BeginRace", function()
    startTime = GetGameTimer()
    Citizen.CreateThread(function()
        checkpoint = CreateCheckpoint(CheckPoints[cP].type, CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z + 2, CheckPoints[cP2].x, CheckPoints[cP2].y, CheckPoints[cP2].z, 8.0, 204, 204, 1, 100, 0)
        blip = AddBlipForCoord(CheckPoints[cP].x, CheckPoints[cP].y, CheckPoints[cP].z)          
        while IsRacing do 
            Citizen.Wait(5)
            SetVehicleDensityMultiplierThisFrame(0.0)
            SetPedDensityMultiplierThisFrame(0.0)
            SetRandomVehicleDensityMultiplierThisFrame(0.0)
            SetParkedVehicleDensityMultiplierThisFrame(0.0)
            SetScenarioPedDensityMultiplierThisFrame(0.0, 0.0)

            --Comment these out if you don't want HUD text
            DrawHudText(math.floor(GetDistanceBetweenCoords(CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z, GetEntityCoords(GetPlayerPed(-1)))) .. " meters", {249, 249, 249,255},0.0,0.75,1.0,1.0)
            DrawHudText(string.format("%i / %i", cP, tablelength(CheckPoints)), {249, 249, 249, 255},0.7,0.0,1.5,1.5)
            DrawHudText(formatTimer(startTime, GetGameTimer()), {249, 249, 249,255},0.0,0.0,1.5,1.5)
                if GetDistanceBetweenCoords(CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z, GetEntityCoords(GetPlayerPed(-1))) < 10.0 then
                    if CheckPoints[cP].type == 5 then
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        PlaySoundFrontend(-1, "RACE_PLACED", "HUD_AWARDS")
                        cP = math.ceil(cP+1)
                        cP2 = math.ceil(cP2+1)
                        checkpoint = CreateCheckpoint(CheckPoints[cP].type, CheckPoints[cP].x,  CheckPoints[cP].y,  CheckPoints[cP].z + 2, CheckPoints[cP2].x, CheckPoints[cP2].y, CheckPoints[cP2].z, 8.0, 204, 204, 1, 100, 0)
                        blip = AddBlipForCoord(CheckPoints[cP].x, CheckPoints[cP].y, CheckPoints[cP].z)
                    else
                        PlaySoundFrontend(-1, "ScreenFlash", "WastedSounds")
                        DeleteCheckpoint(checkpoint)
                        RemoveBlip(blip)
                        IsRacing = false
                        cP = 1
                        cP2 = 2
                        TriggerEvent("chatMessage", "Server", {0,0,0}, string.format("Finished with a time of " .. formatTimer(startTime, GetGameTimer())))
                        preRace()
                    end
                    else
                end
            end
        end)
end)


--utility funcs

function tablelength(T)
    local count = 0
    for _ in pairs(T) do 
    count = count + 1 end
    return count
end

function formatTimer(startTime, currTime)
	local newString = currTime - startTime
	local ms = string.sub(newString, -3, -2)
	local sec = string.sub(newString, -5, -4)
	local min = string.sub(newString, -7, -6)
	--newString = string.sub(newString, -1)
	newString = string.format("%s%s.%s", min, sec, ms)
	return newString
end

function Draw3DText(x,y,z,textInput,fontId,scaleX,scaleY)
	local px,py,pz=table.unpack(GetGameplayCamCoords())
	local dist = GetDistanceBetweenCoords(px,py,pz, x,y,z, 1)

	local scale = (1/dist)*20
	local fov = (1/GetGameplayCamFov())*100
	local scale = scale*fov

	SetTextScale(scaleX*scale, scaleY*scale)
	SetTextFont(fontId)
	SetTextProportional(1)
	SetTextColour(255, 255, 255, 250)
	SetTextDropshadow(1, 1, 1, 1, 255)
	SetTextEdge(2, 0, 0, 0, 150)
	SetTextDropShadow()
	SetTextOutline()
	SetTextEntry("STRING")
	SetTextCentre(1)
	AddTextComponentString(textInput)
	SetDrawOrigin(x,y,z+2, 0)
	DrawText(0.0, 0.0)
	ClearDrawOrigin()
end

function DrawHudText(text,colour,coordsx,coordsy,scalex,scaley) --courtesy of driftcounter
	SetTextFont(7)
	SetTextProportional(7)
	SetTextScale(scalex, scaley)
	local colourr,colourg,colourb,coloura = table.unpack(colour)
	SetTextColour(colourr,colourg,colourb, coloura)
	SetTextDropshadow(0, 0, 0, 0, coloura)
	SetTextEdge(1, 0, 0, 0, coloura)
	SetTextDropShadow()
	SetTextOutline()
	SetTextEntry("STRING")
	AddTextComponentString(text)
	DrawText(coordsx,coordsy)
end

--create blip
Citizen.CreateThread(function()
	for _, info in pairs(blips) do
		info.blip = AddBlipForCoord(info.x, info.y, info.z)
		SetBlipSprite(info.blip, info.id)
		SetBlipDisplay(info.blip, 4)
		SetBlipScale(info.blip, 1.0)
		SetBlipColour(info.blip, info.colour)
		SetBlipAsShortRange(info.blip, true)
		BeginTextCommandSetBlipName("STRING")
		AddTextComponentString(info.title)
		EndTextCommandSetBlipName(info.blip)
	end
end)

Ahh. I think it’s because the blips table is multidimensional.

Instantiate it like so:

local blips = {
    -- { these brackets make this table a table of tables
		title=	"Chiliad Mountain Race",
		colour=	5,
		id=		315,
		x= 		-799.41,
		y=		5401.71,
		z=		34.21
	-- }
}

OR

Reference the variable like this blips[1].z. this tells it to reference the first table in the table of tables. Most programming language tables (arrays) start on 0 but Lua is 1.

Sorry if formatting is wonky, scripting through mobile has a lot to be desired.

Also, I was using the same tablelength function, but you can just do #tableName to get the count of a table.

Hi there Salty,

That fixed the primary issue but then caused another. While it got the markers working, it broke the map blip. Is there something I can do to the blip function so it will work as well with the same newly bracketless blips?

Citizen.CreateThread(function()
	for _, info in pairs(blips) do
		info.blip = AddBlipForCoord(info.x, info.y, info.z)
		SetBlipSprite(info.blip, info.id)
		SetBlipDisplay(info.blip, 4)
		SetBlipScale(info.blip, 1.0)
		SetBlipColour(info.blip, info.colour)
		SetBlipAsShortRange(info.blip, true)
		BeginTextCommandSetBlipName("STRING")
		AddTextComponentString(info.title)
		EndTextCommandSetBlipName(info.blip)
	end
end)

I’ll shoot you a “fixed” code tomorrow when I’m at a computer. Should be pretty easy.

Got a real keyboard now.

So, the problem with your script is that parts of it expect blips to be a single table, and parts of it expect blips to be a table of tables (multidimensional).

Your map blip portion is iterating through a multidimensional table and displaying each blip according to the data found. The portion of the script above that expects blips to be a single table, with the blip data in it. So, by removing the extra opening and closing brackets, it fixed the code that assumes blips is a single table, and broke the code that assumed blips is multidimensional.

So, to fix this:
A - Go back through and change any instance of blips to either iterate with a for loop similar to the map blips.
B - Go back through and add blips[1] to each instance where the blip variable is referenced
C - What I’d do, just re-write the map blips portion to assume it’s not multidimensional:

Citizen.CreateThread(function()
	local blip = AddBlipForCoord(blips.x, blips.y, blips.z)
	SetBlipSprite(blip, blips.id)
	SetBlipDisplay(blip, 4)
	SetBlipScale(blip, 1.0)
	SetBlipColour(blip, blips.colour)
	SetBlipAsShortRange(blip, true)
	BeginTextCommandSetBlipName("STRING")
	AddTextComponentString(blips.title)
	EndTextCommandSetBlipName(blip)
end)

Can we take a moment and appreciate how weird sounding the word blip is?

Hope this helps!

Thanks grandpa. As a completely unlearned lua muddler, I very much appreciate the explanation. I have some understanding of multidimensional arrays through PHP but was not savvy enough to apply it to the lua code.

I really appreciate all the help!

Blips.

1 Like

I think we can all agree PHP syntax is superior.
I may be biased, but PHP is bae.

1 Like