Skip to content

Chat Categories

Chat Categories

Categories are the tabs in the chat input. Each one is a separate channel with its own colors, tags, permissions, delivery rules and identity badges. They are defined in shared/config/categories.lua as config.chatCategories.

The built-in Commands tab

A command category is always injected as the first tab at runtime (from shared/main.lua) — you do not define it yourself:

shared/main.lua
table.insert(config.chatCategories, 1, {
    label = "CATEGORY_COMMANDS_LABEL",
    type = "command",
    icon = "terminal",
    placeholder = "CATEGORY_COMMANDS_PLACEHOLDER",
})

Anything typed in this tab is executed as a command. With config.allowNoSlashCommands = true, a known command name works with or without a leading slash (typing me hi runs /me hi).

What ships enabled

Out of the box only the Admin category is active in config.chatCategories. Ready-to-use examples for OOC (Global), OOC (Local/closest), Police, EMS and Gang are included in the file but commented out — uncomment and tune them as needed.

Category type How access is gated
Commands command Always present (auto-injected)
Admin admin ACE permissions command / admin / adminchat
OOC (Global) ooc Open to everyone (example)
OOC (Local) oocclosest Proximity — distance in meters (example)
Police pdchat jobs = { police = {...grades} } (example)
EMS emschat jobs = { ambulance = true } (example)
Gang gang gangs = { ... } (example)

Default category

config.defaultChatCategory decides which tab is focused when chat opens:

shared/config/general.lua
config.defaultChatCategory = "command"

Slash vs. no-slash commands

shared/config/general.lua
--- true  = commands work WITH and WITHOUT a leading slash ("me hi" runs /me)
--- false = commands only trigger with a leading slash ("/me hi")
config.allowNoSlashCommands = true

Category parameters

Every category supports a rich set of fields. A trimmed example:

shared/config/categories.lua
{
    label = "CATEGORY_ADMIN_LABEL",  -- translation key for the tab name
    type = "admin",                  -- unique id for this category
    icon = "shield-alt",             -- FontAwesome icon
    webhookKey = "chatMessage",      -- Discord log webhook (see Discord Logging)
    placeholder = "CATEGORY_ADMIN_PLACEHOLDER",
    permissions = { "command", "admin", "adminchat" }, -- required ACE perms
    maxLength = 500,                 -- max message length
    tags = {                         -- fixed tag(s) shown before the message
        { tag = "Admin", textColor = { 51, 51, 51 }, bgColor = { 255, 105, 97 } },
    },
    color = { 255, 105, 97 },        -- default message text color
    showPlayerName = { active = true, censored = false, showWearingMask = true },
    showPlayerId   = { active = false, type = "serverId" },
    showPlayerJob  = { active = false, showLabel = true, showGrade = false },
    discordTag     = { active = false, maxShow = 1, roles = { ... } },
    showHour       = { active = true },
}

Full field reference (all optional unless noted):

Field Type Description
label string Translation key for the tab display name
type string Required. Unique identifier for the category
icon string FontAwesome icon name
webhookKey string Discord webhook key to log this category's messages
command string / string[] Chat command(s) that route into this category
placeholder string Translation key for the input placeholder
distance number Max delivery distance in meters; omit for global
maxLength number Maximum message character length
permissions string[] Required ACE permissions to see/use the category
jobs table Required jobs — true = all grades, number[] = specific grades
gangs table Required gangs — same shape as jobs
tags table[] Fixed tags shown before messages (tag, textColor, bgColor)
color RGB Default message text color { r, g, b }
showPlayerName table active, censored, bgColor, textColor, showWearingMask
showPlayerId table active, type = "serverId", colors
showPlayerJob table active, showLabel, showGrade, colors, per-job overrides
discordTag table active, maxShow, roles[] (Discord role → tag)
showHour table active, colors — appends the message time

Name censoring shows a masked name (e.g. J*** D**). If a player is wearing a mask, their name is hidden as Unknown unless showWearingMask = true — the mask check is driven by config.noneMask in general.lua.