Help with string.sub

I’m trying to make a pm addon and I ran into a small issue.


hook.Add("PlayerSay","PMPlayer",function(ply,text,team)
	if(string.sub(text,1,3)=="!pm")then
	
	end
end)


I’m not sure what to put in line 3 because I need to set two different things as variables when you use the command !pm. The target (the player you want to send the message to), and the message. Because the targets name is always going to be different lengths (same with the message) I’m not sure how I can set those exact two things as variables so that I can reference them later. Sorry if you don’t get what I fuck I’m on about :ohno: but please ask for any clarification.

Use string.Explode. Ex.


hook.Add("PlayerSay","PMPlayer",function(ply, text)
	if (string.sub(text,1,3) == "!pm")then
		local args = string.Explode(" ", text)
		local plyname = args[2]
		local message = args[3]
		
		if (not (plyname and message)) then
			ply:ChatPrint("Invalid PM! Missing args")
		end
		
		-- etc code
		
		return ""
	end
end)

You could also explode before you check for !pm, but I see no reason to do that for every time a player chats.

With that you can only pm one word at a time :frowning:


hook.Add("PlayerSay","PMPlayer",function(ply, text)
	if (string.sub(text,1,3) == "!pm")then
		local args = string.Explode(" ", text)
		local plyname = args[2]
		local messagetbl = {}
                for i = 3, #args do
                        messagetbl[i-3] = args*
                end
                local message = table.concat(messagetbl, " ")
		
		if (not (plyname and message)) then
			ply:ChatPrint("Invalid PM! Missing args")
		end
		
		-- etc code
		
		return ""
	end
end)

I would go even further though, because you want to pm players with spaces in their names.



hook.Add("PlayerSay", "PMPlayer", function(ply,text)
    local _,_,name,message = string.find(text,"!pm \"(.*)\" (.*)") --Matches text like "!pm "The Real Garry!" What do you want to do for lunch?"
    if not (name and message) then
        _,_,name,message = string.find(text,"!pm (%a+) (.*)")  --Matches text like "!pm NameWithNoSpaces How was your day today?"
        if not (name and message) then
            ply:ChatPrint("Invalid PM!")
            return nil --Returning nil is kinda the same as not returning anything, but it breaks us out of the function without useing goto
        end
    end
    --At this point, name and message are set
    for _,v in pairs(players.GetAll()) do
        if string.find(v:Nick(),name) then
            v:ChatPrint(message)
            --break --You might want to uncomment this line if you want pms to be delivered to exactly one person, currently this will deliver the pm to anyone who shares a part of the name typed in the pm command
            --For example, if players ["Red Rover","Red Barron","Lazy Dog"] are on the server, typing "!pm Red Hey, how's it going?" will deliver the pm to "Red Rover and Red Barron".
        end
    end
end)


For more on the wacky stuff in string.find, see the lua documntation on captures and pattern matching.
*Code is untested

For your first example you could just do



local name = args[2]
local message = table.concat(args, ' ', 3)


As for the overall idea of this kind of stuff, you’d probably just want to write a function that separates based on quotes.