Colored Chat Messages in CS 1.6 (client_print_color)

July 2, 2025 Daemon666 8 min read 20 views

Colored chat in Counter-Strike 1.6 is not a font feature — it is a set of control bytes the client interprets inside a SayText message. AMX Mod X 1.9 wrapped that in a clean native, client_print_color(), but the color rules underneath are the same on every version and they are what trips people up. This walks through the native, the color codes, and the fallback you need if you are still on 1.8.2.

1. The native (AMX Mod X 1.9 and newer)

client_print_color() does not exist in 1.8.2. If you use it, your plugin's minimum is 1.9 — compile against 1.9 or 1.10 headers or you will hit error 017 undefined symbol. The signature:

client_print_color(id, sender, const message[], any:...)

id is the receiver (0 = everyone). sender is whose team color ^x03 resolves to — use the constant print_team_default for the neutral case:

client_print_color(0, print_team_default, "^x04[SERVER]^x01 Round starts in ^x0330^x01 seconds")

2. The color codes

Colors are embedded as ^x escape sequences directly in the string:

CodeColor
^x01Default (yellow-white)
^x03Team color of the sender index
^x04Green

^x03 is the interesting one: it is not a fixed color. It renders as the team color (blue for CT, red/orange for T) of whatever player index you pass as sender. Pass a real player id to color their name in their team color; pass print_team_default when the message has no owner.

3. Printing a player's name in team color

new name[32]
get_user_name(id, name, charsmax(name))
client_print_color(0, id, "^x03%s^x01 planted the bomb", name)

Because sender is id, the ^x03 before the name resolves to that player's team color, and ^x01 returns the rest of the line to default. This is the idiom behind almost every kill-feed and announce plugin.

4. The 1.8.2 fallback: build the SayText yourself

On 1.8.2 you send the raw user message. Find the SayText message id once and write the control bytes manually:

new g_msgSayText
public plugin_init() {
    g_msgSayText = get_user_msgid("SayText")
}

print_color(id, const msg[]) {
    message_begin(id ? MSG_ONE_UNRELIABLE : MSG_ALL, g_msgSayText, _, id)
    write_byte(id ? id : 1)   // sender index for ^x03
    write_string(msg)
    message_end()
}

You then embed the same ^x01/^x03/^x04 codes in msg. This is exactly what client_print_color does internally — which is why upgrading to 1.9 is worth it just to delete this boilerplate. If you would rather not write any of it, our CSB Admin Chat plugin ships colored admin messages ready to go.

5. Watch the length and the newline

A single chat line is bounded — build the string into a fixed buffer and format into it rather than concatenating blindly:

new msg[191]
formatex(msg, charsmax(msg), "^x04[SERVER]^x01 %s connected from ^x03%s", name, country)
client_print_color(0, print_team_default, msg)

Two practical limits bite here. First, the client truncates very long chat lines, so anything past roughly 190 characters is dropped — count your color codes toward that budget, each ^xNN is real bytes on the wire. Second, a message with no trailing newline is fine for client_print_color, but the hand-built SayText path needs the string exactly as the client expects; do not append your own ^n unless you mean a line break. When in doubt, format into a sized buffer and let the native handle delivery.

Common errors

  • Colors show as literal ^x04 text — you sent the string through client_print(id, print_chat, ...), which does not parse color codes. Only client_print_color (or a hand-built SayText) does.
  • Everything after the name loses its color — you forgot to reset with ^x01 after a ^x03 segment. Codes persist until the next one.
  • ^x03 is always white — you passed print_team_default (or index 0) as sender. It needs a live player index to pick a team color.
  • 017 undefined symbol client_print_color — you are compiling on 1.8.2 headers. Move to AMX Mod X 1.9 or use the SayText fallback above.
  • Message only reaches one player when you wanted everyone — in the manual version, MSG_ONE with a specific id targets one client; use MSG_ALL and id 0 for a broadcast.

Verification

Load the plugin, join the server, and trigger the message. You should see the yellow default text with green and team-colored segments exactly where you placed the codes. Test it with a player on each team — the ^x03 segment must flip color between a CT and a T sender. If it renders as plain text, you are on the wrong print path; re-check step 1. The natives used here are documented in the amxmodx and engine includes if you want the full argument list.

Contributors: Daemon666 ✦
Share: