First of all, I am not that great at manipulating strings. I recently started to make my own chat gui which was not that hard to make but with a filter feature. Recently, I have been in a bit of a trouble trying to replace chars/words. It seems that I am in the right path but this error calling 'gsub
' on bad self (string
expected, got table) is bugging me right now.
local chatGui = script:FindFirstChild("ChatGui") or script:WaitForChild("ChatGui") local filter = { "hello"; "lua"; "noob"; "subjective"} local replacement_words = {"apple", "ambiguous", "banana", "bit", "byte", "car", "clock", "cold", "front", "game", "gold", "world", "pizza", "door"} game.Players.PlayerAdded:connect(function(player) local cloneit = chatGui:Clone() cloneit.Parent = player.PlayerGui player.Chatted:connect(function(msg) print(player.Name .. " has said: \""..msg .. "\"") for word in msg:gmatch("%S+") do --This first loop splits every word the user has said for _, v in pairs(filter) do if string.lower(word) == string.lower(v) and string.len(word) == string.len(v) then --Checks every word and the correct length of that filtered word filtered_word = v print("Filtered word got: \"" .. filtered_word .. "\"") local replacement = tostring(replacement_words[math.random(1, #replacement_words)]) --Here is the main issue print("Replacement word is: \"" .. replacement .. "\"") print("Found filtered word in our filter system. Replacing that word") new_S = string:gsub(msg, v, replacement) --calling 'gsub' on bad self (string expected, got table) print(new_S) end end end end) end)
You're misusing :
.
:
makes a method call, which acts upon the thing just to the left of the :
; you're telling it to act upon string
but you should act upon msg
.
Use one of the following two options:
local new = msg:gsub(v, replacement) -- OR local new = string.gsub(msg, v, replacement)
When you write obj:foo(bar)
, Lua reads this as obj.foo(obj, bar)
-- it copies the thing to the left to be the first parameter.
Thus string:gsub(msg, v, replacement)
is really string.gsub(string, msg, v, replacement)
.
In general, I suggest using the method style for strings because it's so much more compact and readable.
if string.lower(word) == string.lower(v) and string.len(word) == string.len(v) then
becomes
if word:lower() == v:lower() and word:len() == v:len() then
Note that you can even use #word
instead of word:len()
.
In this case, there's no point in also comparing the lengths. If the words are the same (the first condition), they are the same length.