How to use % as a character in string.gsub() without getting an error?

So basically, I’m making a custom chat system. Everything seems to work fine, from scaling each individual message to scaling the actual canvas size of the scrolling frame—but whenever I try to use string.gsub() to add the message to a sample TextLabel, if the message has a “%” in it, it assumes I’m trying to do something else and gives an error.

- Players.Knineteen19.PlayerGui.ChatGui.ChatScript:80: invalid use of '%' in replacement string

Here’s the local script, since the server script works just fine and fires all clients:

-- Disabling Default Chat
game.StarterGui:SetCoreGuiEnabled("Chat",false)

-- Player Stuff
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:wait()

-- Gui
local gui = script.Parent
local chat = gui.Chat
local scroll = chat.ScrollingFrame
local text = chat.TextBox

-- Replicated Storage
local rs = game.ReplicatedStorage
local event = rs.ChatEvent

local sample = rs.ChatSample

-- Services
local uis = game:GetService("UserInputService")

-- Other
local inChat = false
local messageCount = 1
local last = nil

-- Functions
local function scrollAdjust()
	
	-- messageCounting
	local count = 0
	
	for i,v in pairs(scroll:GetChildren()) do
		if v.ClassName == "TextLabel" then
			count = count + v.Size.Y.Offset
		end
	end
	
	-- Adjusting Frame
	scroll.CanvasSize = UDim2.new(0,0,0,count)
	
end

scrollAdjust()

-- Textbox Events
text.Focused:Connect(function()
	inChat = true
end)
text.FocusLost:Connect(function()
	wait(0.1)
	inChat = false
end)

-- Keyboard Input
uis.InputBegan:Connect(function(key)
	
	if not inChat or text.Text == "" then return end
	
	if key.KeyCode == Enum.KeyCode.Return then
		
		-- Sending Message
		event:FireServer(text.Text)
		text.Text = ""
		
	end
	
end)

-- Loading Messages
event.OnClientEvent:Connect(function(player,message)
	
	-- Creating Clone
	local clone = sample:Clone()
	clone.Name = clone.Name..tostring(messageCount)
	clone.Parent = scroll
	
	clone.Text = string.gsub(clone.Text,"Sample",player.Name)
	clone.Text = string.gsub(clone.Text,"Message",message)
	
	clone.Size = UDim2.new(clone.Size.X.Scale,clone.Size.X.Offset,clone.Size.Y.Scale,math.floor((string.len(clone.Text)-97)/38)*100 + 100)
	
	-- Positioning
	if not last then
		clone.Position = UDim2.new(0,0,0,0)
	else
		clone.Position = last.Position + UDim2.new(0,0,last.Size.Y.Scale,0)
	end
	
	last = clone
	
	-- Adjusting Scrolling Frame
	scrollAdjust()
	
end)

Here’s the part that actually adds the message text so players can see the messages:

-- Loading Messages
event.OnClientEvent:Connect(function(player,message)
	
	-- Creating Clone
	local clone = sample:Clone()
	clone.Name = clone.Name..tostring(messageCount)
	clone.Parent = scroll
	
	clone.Text = string.gsub(clone.Text,"Sample",player.Name)
	clone.Text = string.gsub(clone.Text,"Message",message)
	
	clone.Size = UDim2.new(clone.Size.X.Scale,clone.Size.X.Offset,clone.Size.Y.Scale,math.floor((string.len(clone.Text)-97)/38)*100 + 100)
	
	-- Positioning
	if not last then
		clone.Position = UDim2.new(0,0,0,0)
	else
		clone.Position = last.Position + UDim2.new(0,0,last.Size.Y.Scale,0)
	end
	
	last = clone
	
	-- Adjusting Scrolling Frame
	scrollAdjust()
	
end)

Normally I wouldn’t need to use string.gsub() to change the message text, but since I’m using the new “rich text” feature in roblox text to have multiple colors, it just makes more sense to use string.gsub() and just replace the inner parts.

Without using string.gsub(), it would look like this:

clone.Text = '<font color="rgb(150,150,150)" size="35">'..player.Name..':</font><font color="rgb(255,255,255)" size="35"> '..message..'</font>'

and I feel like that would be unnecessarily tedious, especially if I ever decide I want to change the formatting.

I looked around online and couldn’t find anything on bypassing the “%” character with string.gsub(). Would there be a way to do so, or do I just need to fall back onto the other method I mentioned?

The % can also act as an escape character for magic characters. So put another % before it so you end up with "%%" and it will match a signle percent sign cancelling out its characteristic.

2 Likes

Hm, okay, that makes sense, but how would I change any potential % signs to cancel them out? Whenever the player sends a message, I just have a string that could contain the sign, but also might not, and also might have multiple. How would I tell the script to cancel the magic character out if it ever sees it?

As far as I can tell, I can’t just go like:

local msg = string.gsub(message,"%","%%")

because then I just get the same issue.

Just double the amount of % in each string, so message, "%%", "%%%%"

1 Like