ID:2230523
 
(See the best response by Lummox JR.)
Code:
mob
Player
verb
say(var/text as text)
var/msg
var/regex/search = new("@(\\w+)\\b (.+)","i")
var/found = search.Find(text)
if(found)
var/receiver = search.group[1]
if(receiver!="all")
chatTarget = receiver
// chatTarget = Players[receiver] //@TODO - change Players[] to be [Players[name]]==player mob"
else
chatTarget = null
msg = search.group[2]
if(chatTarget)
world<<"[usr]->[receiver]: [msg]"
else
world<<"[usr]: [msg]"
else
search = new("(.+)","i")
found = search.Find(text)
if(found)
msg = search.group[1]
world<<"[usr]: [msg]"


Problem description:
If the player types "@playername message" then this code picks out the 'playername' and the 'message', unless the 'playername' includes a space (i.e., "Lummox Jr" - in which case it picks out the first word as the name and includes the surname in the 'message'.

I've got a list of all players in an associative list in the format: "Players[player.name] = player mob", so I can use this to check if the first x words are someone's name, but I'm not good enough with regex to work out how.

As an aside: it seems weird to me that the 'group' var of a regex datum doesn't have a .len variable.
Best response
The group var not having a len variable was an oversight; the datum doesn't define it as var/list/group but as var/group. This is an easy fix and will be included in 511.1379.

For the problem at hand, you need something that can recursively look for more words as long as it thinks there's a possibility of a match. Frankly the job of doing that is annoying enough that I'd advise just not allowing spaces in an @ identifier and having an associative list by ckey(name) to look up players by name. Besides, you need case-insensitivity anyway.

So the way I'd do this, I'd use your regex and then run receiver through ckey(). Then I'd have a list of players by ckey (one by player name and maybe one by account name too, if they differ), so they could be looked up easily.

If you really wanted to allow spaces, it would get tricky. You'd need to create your own custom routine like ckey() but different, so that you could keep track of spaces. Then, you'd want your associative list to be able to associate multiple things by a word. E.g., if you have two players whose names start with "The", then "the" (lowercase) should associate with another associative list with the next word in their names. Likewise you'd also want a totally spaceless version of each name in the main list.

Don't forget you also want to sanitize msg. It's typical to strip out all HTML and you probably also want to strip \n and have some kind of anti-spam thing like a character limit. (600 or so works decently as a limit.)
Holy moly, that's a thorough response. Cheers Lummox, can't believe someone with as much on their plate as you will spend the time helping an ignorant idiot like me that in-depth.

Secondly, boo yah, that's the first Feature I've ever had an input into ^_^ I'm happier than a kitten chasing a leaky cow.
I don't mind helping users at all, especially Members. :)