Proximity chat?

I have a set of commands but the proximity doesn’t seem to be working, if anyone could help me that would be great.

Here is my server.lua:

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/dis" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^4Dispatch ^7|^4 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
	end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/do" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^1Do ^7|^1 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
	end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/run" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^3 Runs Name On ID And Runs Plate On Vehicle ^7|^3 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
    end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/sp" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^5 Searches Ped (What Do I find?) ^7|^5 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
    end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/sv" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^2 Searches Vehicle (What Comes Back?) ^7|^2 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
    end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/id" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^8Shows ID ^7|^8 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
    end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/ad" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^7[^2Advert^7] |^2 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,5), source)
    end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/uber" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^7[^2Uber^7] |^2 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,7), source)
    end
end)

AddEventHandler('chatMessage', function(source, name, msg)
	sm = stringsplit(msg, " ");
	if sm[1] == "/dark" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^7[^8Dark Web^7]", { 255, 0, 0 }, string.sub(msg,7), source)
    end
end)

function stringsplit(inputstr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={} ; i=1
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
        t[i] = str
        i = i + 1
    end
    return t
end

Here is my client.lua:

AddEventHandler('chatMessage', function(author, color, text, serverID)
    local myCoords = GetEntityCoords(GetPlayerPed(-1))
    local pedCoords = GetEntityCoords(GetPlayerPed(GetPlayerFromServerId(serverID))
    local dist = #(myCoords - pedCoords)
    if dist > 1.5 then
      return
    end
    local args = { text }
    if author ~= "" then
      table.insert(args, 1, author)
    end
    SendNUIMessage({
      type = 'ON_MESSAGE',
      message = {
        color = color,
        multiline = true,
        args = args
      }
    })
  end)

I want to be able to make certain commands proximity based whereas still keep some that are global.

Hey :slightly_smiling_face:

I know this doesn’t answer your question but I was wondering why aren’t you adding only one event listener on the server for all the commands and using one conditionnal structure to test them all. Like that :

AddEventHandler('chatMessage', function(source, name, msg)

	sm = stringsplit(msg, " ");
	
	if sm[1] == "/uber" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^7[^2Uber^7] |^2 " .. name .. '^7(' .. source .. ')', { 255, 0, 0 }, string.sub(msg,7), source)
	elseif sm[1] == "/dark" then
		CancelEvent()
		TriggerClientEvent('chatMessage', -1, "^7[^8Dark Web^7]", { 255, 0, 0 }, string.sub(msg,7), source)
    else
		--xxx
	end
	
end)

Another thing I was thinking while reading the code, if I were you I wouldn’t call my client event 'chatMessage' just to avoid any conflict.

Regargind your initial question, are you using any framework ? Because if so you can use the following methods ESX.GetPlayers() and xPlayer.getCoords(useVector) (for ESX) :
On the server side :

  • Your event get triggered when a message is written in the chat (you already did this part)
  • It checks if it’s one of your commands, if so it call a function you can write under (checkNearPlayers()) (pretty much done too)
  • In the checkNearPlayers() function you do a ‘ESX.GetPlayers()’ where you check the coords of the connected player that you compare with the coords of the player that typed the command
  • For each player that is in the radius you trigger a targetted client event that will do the SendNUIMessage

I didn’t see any errors in your code at first glance, but thought I would offer an alternative in case :wink: .There is a lot of possibilities mine is only one of them (probably not the best).
Did you do some print testing here and there in your code ? It might give you a specific answer for why it didn’t work.

Thank you for letting me know that was possible to do, I am still new to lua and figuring out the basics. Also my server is just a standalone server but I do have ND_Framework and pe-core but I do not know much about their code.

The script works perfectly fine I don’t get any errors but what is print testing?

ok :smile:
When I was mentioning the testing it was for the proximity not working (I thought it was messing up your all script :wink: ).
I call that print testing, but I don’t really know if it’s the proper naming (I’m french) lmao; when I say print testing it means using a display function (like print() ) to display the values of different variables/arrays on a script in order to see more clearly what is going on at a given point.

For example :

local myCoords = GetEntityCoords(GetPlayerPed(-1))
    local pedCoords = GetEntityCoords(GetPlayerPed(GetPlayerFromServerId(serverID))
    local dist = #(myCoords - pedCoords)
    print(dist, author, serverID) --Here
    print(myCoords, pedCoords) --Here and so on :) 
    if dist > 1.5 then
      return
    end

I was testing it and came across an issue and realised why it was not printing which could solve my issue however I don’t have anyone to test it with right now.

The error was:

Error parsing script @miscscripts/client/cl_commands.lua:4: ')' expected (to close '(' at line 3) near 'local'

Once I test it I will let you know but if the issue consists I am not sure what to do then.

Also I forgot to mention that the print you suggested displays this:

event chatMessage was not safe for net

The error you got is a synthax error, as I can’t see the all code I cannot tell you what to do in order to fix it (but it’s just synthax so easy fix).

Regarding the event chatMessage was not safe for net, it’s not the print you added that display the message. This message is due to the fact that you triggered an event that is not flagged as ‘safe for net use’, in order to allow an event to be triggered over the network you need to declare it as such using RegisterNetEvent("eventName") before the EventHandller.

I have added this:

RegisterNetEvent('chatMessage')

At the top of my client file so now it looks like this:

RegisterNetEvent('chatMessage')
AddEventHandler('chatMessage', function(author, color, text, serverID)
    local myCoords = GetEntityCoords(GetPlayerPed(-1))
    local pedCoords = GetEntityCoords(GetPlayerPed(GetPlayerFromServerId(serverID)))
    local dist = #(myCoords - pedCoords)
	print(dist, author, serverID) --Here
    print(myCoords, pedCoords) --Here and so on :)
    if dist > 1.5 then
      return
    end
    local args = { text }
    if author ~= "" then
      table.insert(args, 1, author)
    end
    SendNUIMessage({
      type = 'ON_MESSAGE',
      message = {
        color = color,
        multiline = true,
        args = args
      }
    })
  end)

Which I then tried a command and has a result of:

0.0        Do | Shrooms(1)        1
vector3(1441.867, -1488.115, 70.66713)      vector3(1441.867, -1488.115, 70.66713)

So should this be right and would this mean that it now works?

I have manged to test to see if the proximity works and it doesn’t but I can’t seem to figure why, I even tried changing the distance but still nothing. Do you have any suggestions to why this is not working?

I saw the result of your test :

0.0        Do | Shrooms(1)        1
vector3(1441.867, -1488.115, 70.66713)      vector3(1441.867, -1488.115, 70.66713)

This give us a more informations which is good, but i’m wondering what is displayed in the other player’s console ? (the player you are testing the script with)

@thibaultD
With the other player in close proximity the print was:

88.747840881348      Do | Shrooms(1)      1
vector3(336.9796, 2718.158, 55.89928)            vector3(328.6165, 2630.542, 44.51529)

And then when we was not in close proximity the print was:

0.0    Do  | Shrooms(1)      1
vector3(416.8404, 5739.882, 1078.786)            vector3(416.8404, 5739.882, 1078.786)

bump.

That chatMessage event usage is an outdated nightmare. You should use RegisterCommand() instead.

For “proximity chat”, using commands, you have to:

  • Get talker’s coords
  • Run a loop of GetPlayers(), server-side, and check the distance between their ped and talker’s ped.
  • If it’s close enough, send a message to that player using chat:addMessage - Cfx.re Docs

Additionally, you might want to looking into “chat modes”. Those are better for what you want to use (like, dark-web stuff)

Use this resource as a guide to create your own chat modes: bubblyRestrictedChat (ACL-restricted chat)

The ‘GetPlayers()’ doesn’t exists outside of ESX (or QBcore) if I’m not mistaking. That’s why I was offering the same approach but with ESX, but apparently he doesn’t use either of the frameworks, he’s going for a more standalone approach.

You are mistaking.
GetPlayers() is a server-side fivem function, not custom to ESX, or any framework.
You also have GetActivePlayers() client-side, but this only contains sources at the client is aware of.

for i,k in ipairs(GetPlayers()) do
  print(k) --prints all active player ids (sources) in the server console
end

My bad, I looked left and right in the doc but couldn’t find it. I noticed multiple times that some natives aren’t in the official Native Reference doc, that pretty annoing :frowning: .
Now thanks to you I know that she exists :wink:

1 Like

This has really confused me. I should probably mention I am new to lua but would like to learn. I don’t know how to use RegisterCommand(), I have tried looking at other scripts but I can’t seem to get the commands to work. Could you possible give me a template for a RegisterCommand one with no proximity and one with proximity? It would really help or even a resource that has what I need that I can easily configure.