VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
Messages and chat colors

Table of Contents

#include <VoltMod/Api.hpp>
auto& msg = runtime.Messages;
msg.Send(slot, "Done."); // chat, to one player
msg.Send(slot, "Watch out!", VoltMod::MessageKind::Center); // plain center print
msg.Broadcast("Server restarting in 5 minutes."); // chat, to every human player
msg.Broadcast("Round of the day!", VoltMod::MessageKind::Alert);
// Translate into each player's language and substitute tokens, in one call:
msg.SendKey(slot, "cmd.banSuccess", {{"name", targetName}});
msg.BroadcastKey("round.mvp", {{"name", mvp}}, VoltMod::MessageKind::Center);
@ Center
Plain center-screen print.
@ Alert
Top-center alert bar.

VoltMod::MessageKind picks the destination: Chat, Center, CenterHtml or Alert. Send and Broadcast send finished text; SendKey and BroadcastKey translate a key for each recipient, so a broadcast reaches every player in their own language. runtime.Policy.Reply usually forwards to Send. Shake(slot, durationSec, frequency, amplitude) shakes one player's view.

Chat output keeps an existing leading color escape or prepends the default, so a line cannot inherit color from the one before it.

For a sticky center panel that survives the client's HUD clearing use VoltMod::CenterHtml; see Messaging and chat input. This service is main-thread only: call it from hooks, timers, command handlers or database and HTTP completions, which already run on the game thread.

Color constants

CS2 treats bytes 0x01 through 0x10 as inline color changes, active until the next escape. The constants in <VoltMod/Messaging/ChatColors.hpp> are inline constexpr std::string_view, so they drop straight into std::format.

Constant(s) Byte Color
Default / White \x01 White
DarkRed \x02 Dark red
LightPurple \x03 Light purple
Green \x04 Green
Olive \x05 Olive
Lime \x06 Lime
Red \x07 Red
Gray / Grey \x08 Gray
Yellow / LightYellow \x09 Yellow
Silver / BlueGrey \x0A Silver
LightBlue / Blue \x0B Light blue
DarkBlue \x0C Dark blue
Purple / Magenta \x0E Purple
LightRed \x0F Light red
Gold / Orange \x10 Gold

Names sharing a byte are aliases. ChatColors::Palette is the same set deduplicated to one canonical lowercase name per byte.

namespace ChatColors = VoltMod::ChatColors;
auto line = std::format("{}[ADMIN]{} {}{}{} kicked {} for {}{}",
ChatColors::Red, ChatColors::Default,
ChatColors::LightBlue, adminName, ChatColors::Default,
targetName,
ChatColors::Olive, reason);
runtime.Messages.Broadcast(line);

For a color that comes from config, look the escape up by name. ParseNamed is case-insensitive, resolves aliases ("orange" gives Gold), and returns Default for anything it does not know:

std::string_view color = ChatColors::ParseNamed(group.PrefixColor);

PaletteChoices(labelFor) returns Labeled canonical names for a color picker, shaped for a ChoiceRow<std::string>; labelFor supplies each localized label and may return "" to use the name itself.

The escape bytes are garbage in a console or a log file, so strip them there:

Log::Info("{}", ChatColors::Strip(coloredLine));

A repeated broadcast layout ("[PREFIX] actor did-thing target") belongs in the plugin's own chat service. The framework supplies transport and colors.