Шаблонизатор сообщений чата для AMX Mod X (Counter-Strike 1.6 / GoldSrc).
Каждое сообщение в чат (say, say_team и их dead/spectator-варианты)
перерисовывается через шаблон отправителя, собранный из плейсхолдеров
ParamsController.
Шаблоны поддерживают цвета чата (^1 / ^3 / ^4).
Состоит из двух компонентов — реестра шаблонов и селектора шаблонов — поставляемых одним плагином. Селектор можно подменить другим плагином через публичный форвард (например, селектором на VipModular-лимитах).
- Перехват всех сообщений
SayTextи подмена на шаблон отправителя. - Плейсхолдеры ParamsController (
{p:name},{map}, ...) + текст игрока{chat:text}. - Цвета чата
^1/^3/^4. - Шаблоны в нескольких JSON-файлах (папка
Templates/). - Встроенный селектор: базовые ключи
Say/SayTeamплюс уточнения по состоянию отправителя (SayDead,SaySpec,SayTeamT/SayTeamCT,SayTeamDead, ...);say_teamоткатывается наsay, если командные шаблоны не заданы. - Подменяемый селектор (свой API для расширенных реализаций).
- AMX Mod X 1.10+.
- ParamsController
1.5.0— как зависимость сборки и как отдельный плагин на сервере.
Готовый архив (см. релизы) распаковать в корень сервера (addons/amxmodx/...),
добавить ChatTemplater.amxx в addons/amxmodx/configs/plugins.ini.
На сервере также должен быть установлен ParamsController.amxx.
addons/amxmodx/configs/ChatTemplater/
├── Templates/
│ └── Example.json
└── Selector.json
Каждый файл — JSON-массив объектов:
[
{
"Key": "default_say",
"Template": "^3{p:name}^1: ^4{chat:text}",
"Description": "Публичный чат"
},
{
"Key": "default_sayteam",
"Template": "^3({p:team-name}) {p:name}^1: ^4{chat:text}",
"Description": "Командный чат"
}
]Key— уникальный ключ шаблона (на него ссылается селектор).Template— строка шаблона с плейсхолдерами и цветами.Description— необязательное описание.
Файлы читаются через PCJson и обрабатываются одинаково: шаблонов может быть
сколько угодно, важно лишь чтобы ключи не повторялись.
Объект «ключ селектора → Key шаблона». Базовые ключи — по одному на канал;
остальные уточняют состояние отправителя и необязательны:
{
"Say": "default_say",
"SayDead": "default_say_dead",
"SaySpec": "default_say_spec",
"SayTeam": "default_sayteam",
"SayTeamT": "default_sayteam_t",
"SayTeamCT": "default_sayteam_ct",
"SayTeamDead": "default_sayteam_dead",
"SayTeamTDead": "default_sayteam_t_dead",
"SayTeamCTDead": "default_sayteam_ct_dead",
"SayTeamSpec": "default_sayteam_spec"
}| Ключ | Когда применяется | Откат, если ключ не задан |
|---|---|---|
Say |
say, отправитель жив |
— (последний рубеж) |
SayDead |
say, мёртв |
Say |
SaySpec |
say, наблюдатель |
Say |
SayTeam |
say_team, жив |
Say |
SayTeamT |
say_team, жив, Terrorist |
SayTeam → Say |
SayTeamCT |
say_team, жив, Counter-Terrorist |
SayTeam → Say |
SayTeamDead |
say_team, мёртв (любая сторона) |
SayTeam → SayDead → Say |
SayTeamTDead |
say_team, мёртв, Terrorist |
SayTeamDead → SayTeam → SayDead → Say |
SayTeamCTDead |
say_team, мёртв, Counter-Terrorist |
SayTeamDead → SayTeam → SayDead → Say |
SayTeamSpec |
say_team, наблюдатель |
SayTeam → SaySpec → Say |
Незаданный уточняющий ключ откатывается на более общий, затем на базовый ключ
канала, а для say_team — дальше на цепочку say того же состояния
(SayDead / SaySpec / Say). То есть серверу достаточно задать только
шаблоны say, чтобы стилизовать и общий, и командный чат. Файл с одной парой
Say / SayTeam работает ровно как раньше.
Канал (say или say_team) — свойство команды, его определяет ядро.
Состояние (жив / мёртв / наблюдатель) и сторону (T / CT) встроенный селектор
определяет сам по отправителю (is_user_alive, get_user_team).
- Текст игрока:
{chat:text}. - Глобальная группа:
{map},{time},{date},{server-name},{players-count},{nextmap},{uptime}, ... - Группа игрока:
{p:name},{p:team-name},{p:health},{p:armor},{p:frags},{p:ping},{p:alive},{p:index}, ...
Полный список даёт группа плейсхолдеров ParamsController.
^1 — обычный (белый), ^3 — цвет команды, ^4 — зелёный. Сырые байты цвета
писать не нужно: тип параметра ChatTemplate сам превращает ^-коды в коды
движка и компилирует шаблон.
Селектор решает, какой шаблон использовать для пары (игрок, канал). Решение
захватывается публичным форвардом CT_OnRequestTemplate:
#include <amxmodx>
#include <ChatTemplater>
public plugin_init()
{
register_plugin("My CT Selector", "1.0", "author");
}
public CT_OnRequestTemplate(const playerIndex, const E_CTChannel:channel)
{
// Не VIP — пусть решает встроенный селектор.
if (!(get_user_flags(playerIndex) & ADMIN_LEVEL_H))
return PLUGIN_CONTINUE;
if (channel == CTChannel_Say)
CT_SetRequestedTemplate("vip_say");
else
CT_SetRequestedTemplate("vip_sayteam");
// Захватить решение и остановить цепочку селекторов.
return PLUGIN_HANDLED;
}CT_SetRequestedTemplate(key)+return PLUGIN_HANDLED— использовать свой шаблон.return PLUGIN_CONTINUE— отдать встроенному селектору.CT_GetBuiltinTemplate(playerIndex, channel)— явный откат к встроенному результату.- Форвард передаёт только канал (
say/say_team). Живость, спектаторство и сторону селектор достаёт изplayerIndexсам (is_user_alive,get_user_team) — если это нужно конкретно ему.
Полный пример (селектор по VipModular-лимитам) — в скилле
skills/selector-swap/references/example-vipmodular.md.
enum E_CTChannel
{
CTChannel_Say = 0,
CTChannel_SayTeam,
};
enum T_Template
{
Invalid_Template = 0,
};
// Реестр
native T_Template:CT_RegisterTemplate(const key[], const template[]);
native T_Template:CT_FindTemplate(const key[]);
native bool:CT_GetTemplateString(const T_Template:template, out[], const len);
// Подмена селектора
forward CT_OnRequestTemplate(const playerIndex, const E_CTChannel:channel);
native CT_SetRequestedTemplate(const key[]);
native T_Template:CT_GetBuiltinTemplate(const playerIndex, const E_CTChannel:channel);amxb buildЗависимости и параметры сборки заданы в amxbuild.yml. Компиляция — последним
доступным компилятором AMXX.
chat-templater-template-config— настройка шаблонов и встроенного селектора.chat-templater-selector-swap— подмена селектора (пример на VipModular-лимитах).