You've got the right idea at the start of the script. Tokenize the string with string.split, but then use that table instead of trying to modify the original message.
Here's a hacked out example:
function stutter(stChan, stTar, stMsg)
local stChannels = {"say","shout","tell","whisper","yell"}
local stStutters = {"th","ch","st","tr","bl","br","bl","sp","sc","t","h",
"g","i","c","l","j","y","d","n","w","f","a","s"}
if not table.contains(stChannels,stChan) then return false end
if stChan == "tell" then stMsg = string.format("%s %s",stTar,stMsg) end
local tokens = string.split(stMsg, " ")
for index,word in pairs(tokens) do
for _,st in pairs(stStutters) do
if string.starts(word,st) then
tokens[index] = string.format("%s-%s-%s",st,st,word)
break
end
end
end
display(table.concat(tokens, " "))
end
This way you're just working one word a time, like you should be.
You can test the function with:
stutter("say","dude","this is a test")
-- output: 'th-th-this i-i-is a-a-a t-t-test'
edit: I feel compelled to point out that I have always hated when people use speech impediments as a character mechanic. Yes, it offers a sense of realistic non-perfection... but it also offers a sense of hyper-realistic irritation to many players. I've found myself griefing several of them in the past and I'm honestly
not a griefer.