I need a code review (new coder)

Hello, I’m new in scripting, this is my first script, can someone experienced make me a code review?

area = 30
playerCheckToggle = false

Citizen.CreateThread(function ()
    while true do
        if IsControlJustPressed(0, 303) then
            if(playerCheckToggle == false) then
                playerCheckToggle = true
            elseif(playerCheckToggle == true) then
                playerCheckToggle = false
            end
        end
        Wait(1)
    end
end)

Citizen.CreateThread(function ()
    while true do
        while playerCheckToggle do
            local playerPed = PlayerPedId(-1)
            local playerId = PlayerId(-1)
            local playerName = GetPlayerName(playerId)
            local playerCoords = GetEntityCoords(playerPed)

            local activePlayers = GetActivePlayers()

            for i, player in ipairs(activePlayers) do
                local otherPed = GetPlayerPed(player)
                local x2, y2, z2 = table.unpack(GetEntityCoords(otherPed))
                local distance = math.floor(GetDistanceBetweenCoords(playerCoords.x,  playerCoords.y,  playerCoords.z,  x2,  y2,  z2,  true))
                
                if distance <= area then
                    DrawText3D(x2, y2, z2+1, "ID: " .. GetPlayerServerId(player) .. " | " .. GetPlayerName(player) .. "")
                end
            end
            Wait(1)
        end
        Wait(1)
    end
end)

function DrawText3D(x,y,z, text)
    local onScreen,_x,_y= World3dToScreen2d(x,y,z)

    if onScreen then
        BeginTextCommandDisplayText("STRING")
            
        SetTextScale(0.0, 0.40)
        SetTextFont(0)
        SetTextColour(255, 255, 255, 255)
        SetTextCentre(1)
        AddTextComponentString(text)
        EndTextCommandDisplayText(_x,_y)
    end
end
2 Likes

The following code is untested but sum up everything I could think of :

local area = 30 -- Use local variables
local playerCheckToggle = false

-- Use local functions if you use them only in that file
local function DrawText3D(coords, text) -- coords is a vector3, usually easier to use with natives
	SetTextScale(0.0, 0.40)
	SetTextFont(0)
	SetTextColour(255, 255, 255, 255)
	SetTextCentre(1)

	BeginTextCommandDisplayText("STRING")
	AddTextComponentSubstringPlayerName(text) -- New native name
	SetDrawOrigin(coords, 0) -- The proper way to draw 3d text
    EndTextCommandDisplayText(0.0, 0.0)
    ClearDrawOrigin()
end

CreateThread(function() -- Removed the Citizen. but thats not mandatory
    while true do
        if IsControlJustPressed(0, 303) then
			playerCheckToggle = not playerCheckToggle -- Correct way to toggle a boolean
        end

		if playerCheckToggle then -- Merged the two thread together as they have the same wait time
			local playerPed = PlayerPedId() -- This native takes no parameters
            local playerId = PlayerId() -- This native takes no parameters
            local playerName = GetPlayerName(playerId)
            local playerCoords = GetEntityCoords(playerPed)

            local activePlayers = GetActivePlayers()

			for i = 1, #activePlayers do -- Avoid the use of ipairs and pairs as much as possible
				local player = activePlayers[i]
				local otherPed = GetPlayerPed(player)
                local pos = GetEntityCoords(otherPed) -- Don't unpack the data and use the vector3
                local distance = #(playerCoords - pos) -- Use the distance operator between vector3, no need to floor the value

				if distance <= area then
					DrawText3D(vector3(pos.xy, pos.z + 1), "ID: " .. GetPlayerServerId(player) .. " | " .. GetPlayerName(player) .. "")
					-- A bit strange vector3 manipulation, see the doc : https://docs.fivem.net/docs/scripting-reference/runtimes/lua/functions/vector3/
				end
			end
		end

        Wait(0) -- Wait(1) is the same as Wait(0)
    end
end)

It is still not perfect however, you could use key bindings to avoid creating a thread for instance.

2 Likes

Thanks for helping me :grinning:

1 Like

Thanks mate!

In the spirit of optimization, you could create a thread that checks every 250 or 500 ms for players within a slightly larger radius store them in an array. Then use a similar thread to what @Elio suggested and iterate the array of players within that radius. This would prevent you from calculating the distance between you and every player every frame, which could substantially cut down on CPU time if there are a large number of players in the server. Instead, you will be calculating the distance between you and every player within a reasonable distance from you that may need their names displayed.

Here is a quick untested mock up of what that may look like. Here, I am checking every 500ms for players within area * 2 of your player. Anyone further than that away will likely not be approaching you faster than 500ms.

local area = 30 -- Use local variables
local playerCheckToggle = false
local activePlayersNear = {}

-- Use local functions if you use them only in that file
local function DrawText3D(coords, text) -- coords is a vector3, usually easier to use with natives
	SetTextScale(0.0, 0.40)
	SetTextFont(0)
	SetTextColour(255, 255, 255, 255)
	SetTextCentre(1)

	BeginTextCommandDisplayText("STRING")
	AddTextComponentSubstringPlayerName(text) -- New native name
	SetDrawOrigin(coords, 0) -- The proper way to draw 3d text
    EndTextCommandDisplayText(0.0, 0.0)
    ClearDrawOrigin()
end

CreateThread(function() -- Removed the Citizen. but thats not mandatory
    while true do
        if IsControlJustPressed(0, 303) then
			playerCheckToggle = not playerCheckToggle -- Correct way to toggle a boolean
        end

		if playerCheckToggle then -- Merged the two thread together as they have the same wait time

			for i = 1, #activePlayersNear do -- Avoid the use of ipairs and pairs as much as possible
				local player = activePlayersNear[i]
				local otherPed = GetPlayerPed(player)
                local pos = GetEntityCoords(otherPed) -- Don't unpack the data and use the vector3
                local distance = #(playerCoords - pos) -- Use the distance operator between vector3, no need to floor the value

				if distance <= area then
					DrawText3D(vector3(pos.xy, pos.z + 1), "ID: " .. GetPlayerServerId(player) .. " | " .. GetPlayerName(player) .. "")
					-- A bit strange vector3 manipulation, see the doc : https://docs.fivem.net/docs/scripting-reference/runtimes/lua/functions/vector3/
				end
			end
		end

        Wait(0) -- Wait(1) is the same as Wait(0)
    end
end)

CreateThread(function()
    while true do
		if playerCheckToggle then
            activePlayersNear = {}
			local playerPed = PlayerPedId() -- This native takes no parameters
            local playerId = PlayerId() -- This native takes no parameters
            local playerName = GetPlayerName(playerId)
            local playerCoords = GetEntityCoords(playerPed)

            local activePlayers = GetActivePlayers()

			for i = 1, #activePlayers do -- Avoid the use of ipairs and pairs as much as possible
				local player = activePlayers[i]
				local otherPed = GetPlayerPed(player)
                local pos = GetEntityCoords(otherPed) -- Don't unpack the data and use the vector3
                local distance = #(playerCoords - pos) -- Use the distance operator between vector3, no need to floor the value

				if distance <= area * 2 then
                    table.insert(activePlayersNear, activePlayers[i])
				end
			end
		end

        Wait(500)
    end
end)

This could absolutely be further cleaned up, this is just a quick mock up of how you may reduce CPU time on a resource such as this.

3 Likes

Thanks for the reply :pray:

1 Like

I would suggest to remove the whole loop waiting for pressing a key, RegisterKeyMapping is better and you will save performance.

local playerCheckToggle  = false
RegisterKeyMapping('+showplayers', 'your key description', 'keyboard', YourKey)

RegisterCommand('+showplayers', function() -- when holding key

if playerCheckToggle  == true then
return 
end

playerCheckToggle = true

CreateThread(function()
	while playerCheckToggle do
       --rest of the code from above
	end
end)


end,false)

RegisterCommand('-showplayers', function() --when key is released
playerCheckToggle = false
end,false)

4 Likes

Best Solution :+1:

1 Like

Since I want to press the key once and display the names and press the key again to hide the names, I came up with this:

local area = 30
local playerCheckToggle = false

local function DrawText3D(coords, text)
    SetTextScale(0.0, 0.40)
    SetTextFont(0)
    SetTextColour(255, 255, 255, 255)
    SetTextCentre(1)

    BeginTextCommandDisplayText("STRING")
    AddTextComponentSubstringPlayerName(text)
    SetDrawOrigin(coords, 0)
    EndTextCommandDisplayText(0.0, 0.0)
    ClearDrawOrigin()
end

RegisterKeyMapping('showplayers', 'Toggle Near Players Names', 'keyboard', 'U')

RegisterCommand('showplayers', function()
    if playerCheckToggle then
        playerCheckToggle = not playerCheckToggle
        return
    end

    playerCheckToggle = true

    CreateThread(function()
        while playerCheckToggle do
            local playerPed = PlayerPedId()
            local playerId = PlayerId()
            local playerName = GetPlayerName(playerId)
            local playerCoords = GetEntityCoords(playerPed)

            local activePlayers = GetActivePlayers()

            for i = 1, #activePlayers do
                local player = activePlayers[i]
                local otherPed = GetPlayerPed(player)
                local pos = GetEntityCoords(otherPed)
                local distance = #(playerCoords - pos)

                if distance <= area then
                    DrawText3D(vector3(pos.xy, pos.z + 1), "ID: " .. GetPlayerServerId(player) .. " | " .. GetPlayerName(player) .. "")
                end
            end
            Wait(0)
        end
    end)

end, false)

It’s a good solution or it’s a mess? :flushed:

1 Like

Looks good, but:

Is not used anywhere as i see.

change wait to 5 instead of running it at 0

1 Like

Why should it be to 5?

1 Like
local area = 30
local playerCheckToggle = false

local function DrawText3D(coords, text)
    SetTextScale(0.0, 0.40)
    SetTextFont(0)
    SetTextColour(255, 255, 255, 255)
    SetTextCentre(1)

    BeginTextCommandDisplayText("STRING")
    AddTextComponentSubstringPlayerName(text)
    SetDrawOrigin(coords, 0)
    EndTextCommandDisplayText(0.0, 0.0)
    ClearDrawOrigin()
end

RegisterKeyMapping('showplayers', 'Toggle Near Players Names', 'keyboard', 'U')

RegisterCommand('showplayers', function()
    if playerCheckToggle then
        playerCheckToggle = not playerCheckToggle
        return
    end

    playerCheckToggle = true

    CreateThread(function()
        while playerCheckToggle do
            local sleep = 1000
            local playerPed = PlayerPedId()
            local playerId = PlayerId()
            local playerName = GetPlayerName(playerId)
            local playerCoords = GetEntityCoords(playerPed)

            local activePlayers = GetActivePlayers()

            for i = 1, #activePlayers do
                local player = activePlayers[i]
                local otherPed = GetPlayerPed(player)
                local pos = GetEntityCoords(otherPed)
                local distance = #(playerCoords - pos)

                if distance <= area then
                    sleep = 5
                    DrawText3D(vector3(pos.xy, pos.z + 1), "ID: " .. GetPlayerServerId(player) .. " | " .. GetPlayerName(player) .. "")
                end
            end
            Citizen.Wait(sleep)
        end
    end)

end, false)

If you face flickering draw text then keep reducing sleep under distance check unless it stops flickering

1 Like

Bad idea because it depends on player FPS and will flicker for players with higher FPS, and you probably want to make the script work properly for others players too, right?
Citizen.Wait(1) in loops is practical and changing between 5 and 1ms will not make any noticeable change.

1 Like

Thank you to all of you for helping. I know a lot of people often fear coming here and posting these sort of things as they are afraid of being bashed.

This is the type of community support we like to see, so thank you all.

9 Likes