Skip to main content

BenzyChat

BenzyChat

A clean, standalone FiveM roleplay chat. It replaces the stock chat with color-coded local and global commands (/me, /do, /ooc, /leo, /med, …), draws each message as a dark glass bubble in the top-left corner — the sender's name, the command type in its own color, and the text — and gives players a polished top-center typing box with real command autocomplete and sent-line recall. Opening the box turns the bubbles into a scrollable recent-message view. Each player picks how chat shows (fade on new message, always on, or hidden), and every message can be mirrored to Discord. No framework, no database, no dependencies.

Made by Samuel Benzy of Benzy Development.


Features

  • Local + global commands/me, /do, /ooc, /leo, /med out of the box, each with an auto-generated global twin (/gme, /gooc, …). Local messages reach only players within range; global messages reach the whole server.
  • Color-coded types — the type label (me, ooc, …) is drawn in its own color so you can tell messages apart at a glance. Every command and color is set in config.lua.
  • On-screen bubbles — dark, slightly transparent bubbles that come down from the top-left corner: the sender's FiveM name, the colored command type, an optional GLOBAL tag, and the message in white. Up to three at a time.
  • A proper typing box — a top-center glass pill with Tab autocomplete (cycle-complete a command into the box) and ↑ / ↓ recall of your own sent lines. Opening it turns the top-left bubbles into a mouse-wheel-scrollable view of the recent messages.
  • Per-player visibility — a toggle key cycles active (show on a new message, then fade), always (keep the last three pinned), and hidden (never show). Each player's choice is remembered.
  • No-command behavior — decide what plain text with no /command does: nothing, a local message, or a global one.
  • Discord logging — paste a webhook URL and every message posts a tidy embed with the command and scope; @everyone can't ping.
  • A true drop-in — it provides chat, so other resources' chat:addMessage lines still show as bubbles and their chat:addSuggestion commands still autocomplete. Foreign commands (/pay, /engine, …) keep working.
  • Standalone — no framework (ESX/QBCore) and no database required.

How it works

  • The client shows the bubbles and the typing box. Press the open key to type; on Enter, one of BenzyChat's commands goes to the server with the exact text, a foreign command is handed off to whatever registered it, and plain text follows the no-command setting.
  • The server is the authority: it re-validates every command (clients are never trusted), trims and length-caps the text, and works out the recipients — everyone for a global command, only players in range for a local one. Then it renders on each recipient's client and logs to Discord.
  • Everything visual — the colors, positions, bubble timing, and theme — is read from config.lua and applied to the UI when it loads, so a config change is all it takes to restyle.

Requirements

  • A FiveM server. That's it — BenzyChat is standalone.

Installation

  1. Place the BenzyChat folder in your server's resources directory.
  2. Add BenzyChat to your server.cfg:
    ensure BenzyChat
    BenzyChat replaces the stock chat (it declares provide 'chat') and stops the built-in chat resource automatically whenever it starts, so you don't need to touch it in server.cfg.
  3. (Optional) Set a Discord webhook to log chat — paste a URL into Config.Webhooks in config.lua.
  4. Open config.lua and set the commands, colors, and theme to taste.
  5. Restart the server (or ensure/restart BenzyChat).

Press T in-game to open chat (rebindable in Settings → Key Bindings → FiveM). Run /debugbenzychat from the server console (or an admin) for a quick state report and sample bubbles.


Configuration

Everything is configured in config.lua, and every option has a comment above it explaining what it does. The highlights:

Commands

OptionWhat it does
Config.CommandsThe command list — each row's Command, Label, Color, and Description. Add Global = false or Range = 30.0 to any row. Prefix any command with g in-game for its global twin.
Config.NoCommandBehaviourWhat plain text with no /command does — 'none', 'local', or 'global'.

Bubbles

OptionWhat it does
Config.Bubbles.PositionWhere the bubble stack sits — see Positions.
Config.Bubbles.DurationMilliseconds a bubble stays before it fades (the active mode only).

Input & visibility

OptionWhat it does
Config.Input.PositionWhere the typing box sits (default top-center).
Config.Visibility.DefaultThe mode a player starts on — 'active', 'always', or 'hidden'.
Config.Visibility.ToggleKeyThe default key that cycles the modes (rebindable).

Theme, Discord & locale

OptionWhat it does
Config.ThemeThe surface color, text/name colors, accent, and corner radius.
Config.WebhooksA URL per scope (Local, Global, Plain) — leave blank to skip, use the same URL to log everything to one channel.
Config.LocaleActive language code (default 'en').

Commands

Every command below has a global twin — prefix it with g to send it server-wide: /me/gme, /ooc/gooc, and so on.

CommandTypeWhat it does
/me <action>LocalAn action you perform — John Doe waves.
/do <detail>LocalDescribe the scene or surroundings.
/ooc <message>LocalOut-of-character chatter to nearby players.
/leo <message>LocalLaw-enforcement chatter.
/med <message>LocalMedical / EMS chatter.
/g<command> …GlobalThe global twin of any command above — reaches the whole server.

Plain text typed without a leading /command follows Config.NoCommandBehaviour. Add, remove, or recolor any command in Config.Commands.

Keys: T opens the typing box; L cycles the visibility mode. Both are rebindable in Settings → Key Bindings → FiveM. In the box: Enter sends, Esc cancels, Tab / Shift+Tab complete a command, ↑ / ↓ recall your last lines, and the mouse wheel scrolls the history.


Visibility modes

Each player presses the toggle key (default L) to cycle how chat shows on their screen. No matter the mode, opening the typing box always shows the recent messages.

ModeWhat it does
activeA bubble appears when a new message arrives, then fades after Config.Bubbles.Duration. The default.
alwaysThe last few messages stay pinned on screen at all times.
hiddenBubbles never show — you only see messages by opening the box.

Set the starting mode with Config.Visibility.Default; each player's own choice is then remembered across sessions.


Positions

Set Config.Bubbles.Position and Config.Input.Position to one of:

top-left top-center top-right
center-left center-right
bottom-left bottom-center bottom-right

Bubbles default to top-left and the typing box to top-center, so the two never overlap.


Discord logging

Paste a webhook URL and every message posts an embed — the sender (name + id), the message, the command, and the scope. Leave a scope's URL blank to skip it, or use the same URL for all three to log everything in one channel.

  • Per scope: Config.Webhooks.Local, Config.Webhooks.Global, Config.Webhooks.Plain.
  • Safe by design: player text only ever goes inside the embed, which Discord never turns into a mention, so a message containing @everyone can't ping.

Integrating with other resources

BenzyChat is a drop-in chat, so most resources need no changes. The docs cover the rest:

  • docs/EVENTS.md — BenzyChat's own events and the stock chat:* events it keeps working.
  • docs/EXPORTS.md — raise a bubble on a client, or broadcast a message from the server.
  • docs/INTEGRATIONS.md — replacing the stock chat, how other resources' output still shows, and Discord logging.

Because it provides chat, any resource that calls TriggerEvent('chat:addMessage', …) or chat:addSuggestion keeps working with no changes.


Notes

  • Bubbles are purely visual and client-side. A message shows, fades, and is gone; opening the box shows the last few again as a scrollable recent view. Nothing is stored server-side.
  • Local chat never leaves range. The server sends a local message only to players who should see it, so out-of-range clients can't sniff it (no metagaming).
  • It replaces the stock chat. BenzyChat stops the built-in chat resource automatically whenever it starts, so the two never run side by side — no server.cfg change needed.

Troubleshooting

  • Turn on debug logging first — set Config.Debug = true, restart, and watch the server console + each client's F8. Every message logs its command, scope, and recipient count. /debugbenzychat prints a state report.
  • Two chat boxes — BenzyChat stops the built-in chat on its own (with Config.Debug on you'll see "stopped the built-in chat resource" in the console). If a box still shows, another resource is running its own chat — stop that one.
  • A local message reaches no one — local chat carries 20m and reaches nearby players (globals reach everyone). Give a command its own Range in Config.Commands to change how far it carries.
  • A command does nothing — check the command exists in Config.Commands (names are case-insensitive).
  • Another script's command isn't in the autocomplete — For a command and its help text to appear, BenzyChat needs to be running when that resource registers it — ensure BenzyChat near the top of your server.cfg for the fullest hints.
  • Discord isn't logging — confirm the URL is set in Config.Webhooks and that the resource can reach Discord. Debug logging shows each post's result.
  • The box won't open / I'm stuck — check the open key in Key Bindings. If a reload ever leaves you stuck, the resource releases focus on stop.

Support

Need help? Visit support.benzy.lol.


Credits

Made by Samuel Benzy of Benzy Development.

Website: https://benzy.lol