There are a couple of improvements you could make in terms of the structuring of your code as well as how you’re applying tags. I do encourage checking out the Lua Chat System API documentation for some tips and tricks you can use in your code.
In terms of how you’re assigning tags, you can use a dictionary to determine what kind of tag a player should have and keep a separate table of constants determining the data of a chat tag. This way you can essentially enumerate your chat tags and assign them nicely.
local CHAT_TAG_STYLES = {
["Owner"] = {TagText = "OWNER", TagColor = Color3.fromRGB(36, 66, 39)},
-- etc
}
local SPECIAL_USERS = {
[61905980] = CHAT_TAG_STYLES.Owner,
-- etc
}
For SpeakerAdded, it’s imperative that you’re prepared for Deferred SignalBehavior becoming the default for when signals are fired as well as any potential race conditions arising out of your code wherein a speaker is added before the event connects. For this, take your lambda out of Connect and make a function variable for it. Connect it at the bottom then run it for every existing player.
local function speakerAdded(speakerName)
-- Code goes here
end
chatService.SpeakerAdded:Connect(speakerAdded)
for _, speaker in ipairs(chatService:GetSpeakerList()) do
task.spawn(speakerAdded, speaker)
end
A lot of developers working with the ChatService seem to not actually know that ChatSpeakers possess a GetPlayer method. Every player ChatSpeaker has their Player object attached which can be retrieved from the GetPlayer method. You should be using this over trying to find their player object in the Players service because it can also differentiate NPC speakers.
local speaker = chatService:GetSpeaker(speakerName)
local player = speaker:GetPlayer()
-- We do not want to add any tags to NPC speakers
if not player then return end
For the rest of your code, all you need to do is check if the player is in the special users dictionary using their UserId as a lookup key. If they exist, then you simply create a new table containing the tag that their UserId is assigned to. Since the special users table contains table references, you can directly pass in the value of the for loop as their chat tag. The dictionary’s great because you can avoid doing any unnecessary looping and instead directly check what tag a player should get.
Altogether:
local players = game:GetService("Players")
local marketplaceService = game:GetService("MarketplaceService")
-- EDIT: Please stay consistent. Changed this to use GetService.
local chatService = require(game:GetService("ServerScriptService"):WaitForChild('ChatServiceRunner'):WaitForChild('ChatService'))
local CHAT_TAG_STYLES = {
["Owner"] = {TagText = "OWNER", TagColor = Color3.fromRGB(36, 66, 39)},
-- etc
}
local SPECIAL_USERS = {
[61905980] = CHAT_TAG_STYLES.Owner,
-- etc
}
local function speakerAdded(speakerName)
local speaker = chatService:GetSpeaker(speakerName)
local player = speaker:GetPlayer()
-- We do not want to add any tags to NPC speakers
if not player then return end
-- Perform a lookup by their UserId; will return the table reference
-- if it exists, or nil if it doesn't.
local tagData = SPECIAL_USERS[player.UserId]
if tagData then
speaker:SetExtraData("Tags", {tagData})
end
end
chatService.SpeakerAdded:Connect(speakerAdded)
for _, speaker in ipairs(chatService:GetSpeakerList()) do
task.spawn(speakerAdded, speaker)
end
Fun fact: you can also add this as a ChatModule so that the ChatService initialises your module for you rather than having it as a separate script. It does require a couple of instances to be present so you can place your module there though. Ultimately there’s no difference between having it as a module ran by the ChatService or as a separate script beyond how ChatService gets defined in your code.
Just as an example, I substituted my UserId in the owner table to show you the result: