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.
01 | local chatGui = script:FindFirstChild( "ChatGui" ) or script:WaitForChild( "ChatGui" ) |
02 | local filter = { "hello" ; "lua" ; "noob" ; "subjective" } |
03 |
04 | local replacement_words = { "apple" , "ambiguous" , "banana" , "bit" , "byte" , "car" , "clock" , "cold" , "front" , "game" , "gold" , "world" , "pizza" , "door" } |
05 |
06 | game.Players.PlayerAdded:connect( function (player) |
07 | local cloneit = chatGui:Clone() |
08 | cloneit.Parent = player.PlayerGui |
09 | player.Chatted:connect( function (msg) |
10 | print (player.Name .. " has said: \"" ..msg .. "\"" ) |
11 | for word in msg:gmatch( "%S+" ) do --This first loop splits every word the user has said |
12 | for _, v in pairs (filter) do |
13 | 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 |
14 | filtered_word = v |
15 | print ( "Filtered word got: \"" .. filtered_word .. "\"" ) |
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:
1 | local new = msg:gsub(v, replacement) |
2 | -- OR |
3 | 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.
1 | if string.lower(word) = = string.lower(v) and string.len(word) = = string.len(v) then |
becomes
1 | 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.