How would I find out certain things a player said?

Im trying to make an admin system, I already have the base part of it, but the issue is, I don’t know how to figure out if the player said something like “smite playerName”

So how would I separate the command name and playerName while also figuring out what the player’s name was?

https://developer.roblox.com/en-us/api-reference/event/Player/Chatted

Plenty of code examples here.

1 Like

String manipulation and the .Chatted event

https://developer.roblox.com/en-us/api-reference/lua-docs/string

https://developer.roblox.com/en-us/api-reference/event/Player/Chatted

Also similar posts to this have been made before.

Im confused about string.sub, what’s the point of all of the numbers, and why do we put the message at the beggining?

You probably want to use string.split:

local message = "smite builderman"
-- Process Message
local splitString = string.split(message, " ")
local cmdName = splitString[1] -- "smite"
local playerName = splitString[2] -- "builderman"

string.split can be used to break a sentence string into a table of word strings based on the spaces.

string.sub gets a “sub string” of a string. It basically gets a part of a string, based on the position of the characters.

For example, if your string was “=abc” and you wanted to get the “abc” part you would get the letters from index 2 to index 4, since a is the second letter and c is the fourth letter.

string.sub("=abc", 2, 4) -- equates to "abc"

The number -1 is used to represent if you want to go all the way to the end of the string. So in the abc example, -1 could be used in place of 4 since we want the last index in the string.

string.sub("=abc", 2, -2) -- still equates to "abc"
1 Like

I want to find the player though, not have a specific player already listed.

Also, for the string.split function, why did you do message, " "? What is the white space supposed to represent?

And isn’t builder man apart of the message? so wouldn’t message, " " translate to ( smite builder man, " ")?

And also, why should I use string.split over string.sub? Is their a difference between the two that makes one less reliable?

In your code, you would set message to the value you get either from process cmd or from chatted.

The white space is the character used to break up the string. You probably want cmds to be broken up by white spaces, instead of something like , or |.

Ex:
If this was split by spaces (" ")

"hello world. This is a message"

It would turn into:

{"hello", "world.", "This", "is", "a", "message"}

If it was split by "." it would turn into:

{"hello world", "This is a message"}

To add two strings, the .. operator is used. If the code said message.." " then yes, that would be "smite builderman ". The comma is used to separate parameters/values into a tuple (ex: math.min(1,2) doesn’t add one and two, it finds the min of one and two).

The two functions do different things. split splits the string where ever there is a chosen character/string (in this case, " "). sub splits the string at an index/position number. Names of players and cmds have different lengths, so you don’t know the position numbers to split the string with for sub, so split is a good idea.

You could program your own split function using sub, though split is already made.

Try Doing This;

Put This In A Local Script:

local User = game.Players.LocalPlayer -- gets the local player
local CommandPrefix = "+"

User.Chatted:Connect(function(message) -- this will fire when the plr chats something
      local StringSplit = string.split(message, " ") -- splits string into 2 from space
      if StringSplit[1] == CommandPrefix.."smite" then -- checks if the first thing in the split is "(Command Prefix) smite"
         local plrToSmite = StringSplit[2] -- sets the plr they are going to smite to the second thing in split
         for i,plr in pairs(game.Players:GetChildren()) do -- goes through all of the players and checks if their name is equal to the plr we are going to smite
              if plr.Name == plrToSmite then -- if the plr we are going to smite is equal to the plr in the server, then we will smite them, but we use a RemoteEvent
                   YourRemoteEventLocation:FireServer(plr,plrToSmite) -- fires event passing the plr and plrToSmite
              else
                   print("Invalid Player: "..plrToSmite) -- if not, then we print that the plr is an invalid plr
              end
       end
end)

Server Script For The Remote:

YourRemoteLocation.OnServerEvent:Connect(function(user,plr,plrToSmite)
       --put what you want to do to the player who is going to get smite
       --plr.Character:WaitForChild("Humanoid").Health -= 100 (this is optional)
end)

I just wanna say, for the future of you trying to help people on the devforum, try to add more notes on the scripts.

I don’t understand most of this script, and it isn’t helping me on what I am supposed to do, especially cause In the future, I may do this same exact thing again but in a different game I am making.

sorry, i just now put in notes

1 Like

Would this be the first correct approach?

local CommandMessage = string.split(message, " ")
			
local command = CommandMessage[1] -- With the command being +smite
local playerName = CommandMessage[2] -- Being the players name

and also, what if someone says + smite playerName? what would happen then because wouldn’t it mess up the scripts?

because the command is supposed to be +smite, then the playerName but what would happen if someone does + smite playerName?

It wouldn’t mess up the script because you are checking if what the Plr said is equal to “smite (Player)”, so nothing will happen if the Plr says “+smite (Player)”

I do however suggest using a Command Prefix such as ! or /

You’d probably need to check if the command is valid. I’d recommend doing a mix of things:

local Players = game:GetService("Players")

-- List of valid cmds
local commandsList = {
     "smite"
}

local commandMessage -- Set to the message

-- Get the first character of the message
local commandCharacter = string.sub(commandMessage, 1, 1)

-- Is cmd character valid?
if commandCharacter == "+" then
    -- Gets the list of words in commandMessage. sub is used to ignore cmd character
    local commandDetails = string.split(string.sub(commandMessage, 2, -1))

    -- Name of command
    local commandName = commandDetails[1]

    -- Name of player
    local playerName = commandDetails[2]

    -- Is name of player and name of command valid?
    if table.find(commandsList, commandName) and Players:FindFirstChild(playerName) then
        -- Run command here
    end
end

Note that you’ll probably want to program your own function to get the players based on their names, since find first child is case sensitive, and players also like to use the first few letters.

1 Like

The script didn’t seem to work and did not do anything, nor did it error…

Did I do anything wrong?

local Prefix = "+"

local RS = game:GetService("ReplicatedStorage")

game.Players.PlayerAdded:Connect(function(player)
	player.Chatted:Connect(function(message)
		if player.Name == "NubblyFry" then
			local Players = game:GetService("Players")

			-- List of valid cmds
			local commandsList = {
				"smite"
			}

			local commandMessage = message

			-- Get the first character of the message
			local commandCharacter = string.sub(commandMessage, 1, 1)

			-- Is cmd character valid?
			if commandCharacter == "+" then
				-- Gets the list of words in commandMessage. sub is used to ignore cmd character
				local commandDetails = string.split(string.sub(commandMessage, 2, -1))

				-- Name of command
				local commandName = commandDetails[1]

				-- Name of player
				local playerName = commandDetails[2]

				-- Is name of player and name of command valid?
				if table.find(commandsList, commandName) and Players:FindFirstChild(playerName) then
					local SmiteBlock = RS:WaitForChild("commandObjects"):WaitForChild("Smite")
					
					local PlayerObject = Players:FindFirstChild(playerName)
					
					local character = player.Character
					
					local ThunderSound = Instance.new("Sound", game.Workspace)
					ThunderSound.SoundId = "rbxassetid://357559831"
					
					ThunderSound:Play()
					
					SmiteBlock.Position = character:WaitForChild("HumanoidRootPart").Position
					
					task.wait(0.2)
					
					SmiteBlock:Destroy()
				end
			end
		end
	end)
end)

Note that player names and command names are case sensitive. It also might have to do with the test players, since I believe their names have spaces? I’d use print statements or break points to debug it.

1 Like

I debugged and learned that the playerName was returning as nil,

  07:19:55.527  Command Prefix '+' has been entered   -  Server - Commands:20
  07:19:55.527  smite NubblyFry  -  Server - Commands:30
  07:19:55.527  nil  -  Server - Commands:32
print("Command Prefix '+' has been entered ")
-- Gets the list of words in commandMessage. sub is used to ignore cmd character
local commandDetails = string.split(string.sub(commandMessage, 2, -1))

-- Name of command
local commandName = commandDetails[1]

-- Name of player
local playerName = commandDetails[2]
				
print(commandName)
print(playerName)

Whoops! I forgot to add the character to split the string by.

This line

local commandDetails = string.split(string.sub(commandMessage, 2, -1))

should have been

local commandDetails = string.split(string.sub(commandMessage, 2, -1), " ")

This code is fixed:

local Prefix = "+"

local RS = game:GetService("ReplicatedStorage")

game.Players.PlayerAdded:Connect(function(player)
	player.Chatted:Connect(function(message)
		if player.Name == "NubblyFry" then
			local Players = game:GetService("Players")

			-- List of valid cmds
			local commandsList = {
				"smite"
			}

			local commandMessage = message

			-- Get the first character of the message
			local commandCharacter = string.sub(commandMessage, 1, 1)

			-- Is cmd character valid?
			if commandCharacter == "+" then
				-- Gets the list of words in commandMessage. sub is used to ignore cmd character
				local commandDetails = string.split(string.sub(commandMessage, 2, -1), " ")

				-- Name of command
				local commandName = commandDetails[1]

				-- Name of player
				local playerName = commandDetails[2]

				-- Is name of player and name of command valid?
				if table.find(commandsList, commandName) and Players:FindFirstChild(playerName) then
					local SmiteBlock = RS:WaitForChild("commandObjects"):WaitForChild("Smite")
					
					local PlayerObject = Players:FindFirstChild(playerName)
					
					local character = player.Character
					
					local ThunderSound = Instance.new("Sound", game.Workspace)
					ThunderSound.SoundId = "rbxassetid://357559831"
					
					ThunderSound:Play()
					
					SmiteBlock.Position = character:WaitForChild("HumanoidRootPart").Position
					
					task.wait(0.2)
					
					SmiteBlock:Destroy()
				end
			end
		end
	end)
end)
1 Like

It worked, thanks!

smiting myself lots of time is entertainment.

1 Like

I do have a question though, Is this easily exploitable?

And why can I only smite myself?

If you’re running this on the server it isn’t exploitable.

You should be able to smite other players, what testing did you do? It probably doesn’t work on test characters and the names are case sensitive.