Русское сообщество по скриптингу

[INC] Tutor API

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

[INC] Tutor API

Сообщение Retro-kolt Lincoln » 27 апр 2012, 23:23

Автор: Вы должны зарегистрироваться, чтобы видеть ссылки.
Источник: Вы должны зарегистрироваться, чтобы видеть ссылки.
Версия: Alpha
Статью писал: Вы должны зарегистрироваться, чтобы видеть ссылки.

Предисловие:
В этой статье мы рассмотрим использование тутор сообщений из кондишен зеро с помощью API от Вы должны зарегистрироваться, чтобы видеть ссылки.

Основные функции:
* Создание тутор сообщений используя различные стили.
* Возможность выставлять длительность сообщения, так же можно сделать чтобы сообщение не пропадало, то есть перманентные сообщения.
* Возможность писать сообщения в любой кодировке на русском, хоть в Ansi хоть в UTF-8, русский текст не когда не исказится.
* Выставление надёжности сообщение, при обычной надёжности сообщение будет отправляется с аргументом MSG_ONE_UNRELIABLE, при максимальной надёжности с MSG_ONE.
* Сообщения поддерживают любые аргументы.
* Хорошая поддержка ML
* Установлен лимит символов для сообщения, при слишком большой длине сообщения сервер не будет вылетать.

Установка:
Распакуйте содержимое архива в ГЛАВНУЮ папку с сервером. Скомпилируйте исходник TutorAPI.sma и пропишите его в plugins.ini.

Natives:
Код: Выделить всё
native TutorShow(iEntity = 0, iType = TutorTypeDefault, Float:fTime = 0.0, iSound = TutorSoundNone, const iMessage[], any:...); 

Описание:
Показывает тутор сообщение игроку/игрокам.

Аргументы:
| Название | Тип | По умолчанию | Описание
----------------------------------------------------------------------------------------
| iEntity | Целочисленное | 0 | Индекс игрока которому показывать сообщение (0 - всем)
| iType | Целочисленное | TutorTypeDefault | Стиль сообщения (смотрите стили выше)
| fTime | Дробное | 0.0 | Время показа тутор сообщения (0.0 - бесконечно)
| iSound | Целочисленное | TutorSoundNone | Звук при сообщении (смотрите звуки выше)
| iMessage | Целочисленное | отсутствует | Сообщение
| ... | отсутствует | отсутствует | Аргументы к сообщению

Примеры:
Код: Выделить всё
TutorShow(0, TutorTypeScenario, 0.0, TutorSoundTaskComplete, "You are complete your %d task!", 5);
TutorShow(id, TutorTypeHint, 5.0, TutorSoundTutorMsg, "To buy weapon press ^"B^" key"); 


Код: Выделить всё
native TutorClose(iEntity = 0); 

Описание:
Закрывает тутор у игрока/игроков.

Аргументы:
| Название | Тип | По умолчанию | Описание
----------------------------------------------------------------------------------------
| iEntity | Целочисленное | 0 | Индекс игрока которому надо закрыть сообщение (0 - всем)

Примеры:
Код: Выделить всё
TutorClose(id);
TutorClose(0); 


Код: Выделить всё
native TutorReliable(bool:bReliable); 

Описание:
Изменяет надёжность сообщений тутора, а также звуков. Если не знаете зачем это, не используйте !!!

Аргументы:
| Название | Тип | По умолчанию | Описание
----------------------------------------------------------------------------------------
| bReliable | Булевая | false | Надёжность

Примеры:
Код: Выделить всё
TutorReliable(false);
TutorReliable(true); 


Использование:
Откройте ваш плагин который вы будете модифицировать и добавьтев него после ваших инклудов:
Код: Выделить всё
#include <TutorAPI>       

После используйте нужные нативы которые написаны выше.

Пример использования:
Код: Выделить всё
#include <amxmodx>
#include <TutorApi>
 
#define PLUGIN  ""
#define VERSION ""
#define AUTHOR  ""
 
public plugin_init
()
{
        register_plugin(PLUGIN, VERSION, AUTHOR)
        register_clcmd("say /rs", "rs")
}
 
public rs
(id)
{
        new players[32]
        get_user_name(id, players, 31)
        
        if 
(is_user_connected(id))
        {
                set_user_frags(id, 0)
                cs_set_user_deaths(id, 0)
        
                TutorShow
(0, TutorTypeDefault, 5.0, TutorSoundTutorMsg, "%s обновил свой счёт!", players)
        }
        
        return PLUGIN_HANDLED
}
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Retro-kolt Lincoln 28 апр 2012, 13:54, всего редактировалось 8 раз(а).
Аватара пользователя
Retro-kolt Lincoln
 
Сообщения: 1283
Зарегистрирован: 28 авг 2010, 19:16
Благодарил (а): 321 раз.
Поблагодарили: 581 раз.
Опыт программирования: Больше трех лет
Языки программирования: ╚►Counter-Strike 1.6

Re: [INC] Tutor API

Сообщение HENRI(_)LLOYD » 11 мар 2013, 01:50

А я вроде нашел, в TutorTextWindow.res
Аватара пользователя
HENRI(_)LLOYD
 
Сообщения: 189
Зарегистрирован: 26 дек 2012, 03:07
Благодарил (а): 34 раз.
Поблагодарили: 7 раз.

Re: [INC] Tutor API

Сообщение Valer4 » 22 сен 2014, 14:31

подправь в rs
#include <cstrike>
#include <fun>
Аватара пользователя
Valer4
 
Сообщения: 52
Зарегистрирован: 07 окт 2010, 14:12
Откуда: Байконур
Благодарил (а): 5 раз.
Поблагодарили: 5 раз.

Re: [INC] Tutor API

Сообщение KPOCT » 20 сен 2016, 15:05

| iMessage | Целочисленное | отсутствует | Сообщение
--->
| sMessage | Массив символов | отсутствует | Сообщение

Не?
(2*b) || !(2*b)
Аватара пользователя
KPOCT
 
Сообщения: 65
Зарегистрирован: 21 фев 2016, 23:33
Благодарил (а): 21 раз.
Поблагодарили: 7 раз.
Опыт программирования: Больше трех лет
Языки программирования: C, C++, C#, Pawn, VBS, PHP, JS

Re: [INC] Tutor API

Сообщение sa1me » 20 сен 2016, 16:32

Обновил вложения.
Аватара пользователя
sa1me
 
Сообщения: 361
Зарегистрирован: 07 апр 2014, 20:51
Откуда: pfnAddToFullPack
Благодарил (а): 174 раз.
Поблагодарили: 177 раз.
Опыт программирования: Меньше недели

Re: [INC] Tutor API

Сообщение KPOCT » 20 сен 2016, 17:55

sa1me писал(а):Обновил вложения.

TutorAPI.sma бы ещё.
А то
Код: Выделить всё
( 53) Load fails: Plugin uses an unknown function (name "TutorShow") - check your modules.ini.

Натив не зарегистрирован, насколько я понял.
(2*b) || !(2*b)
Аватара пользователя
KPOCT
 
Сообщения: 65
Зарегистрирован: 21 фев 2016, 23:33
Благодарил (а): 21 раз.
Поблагодарили: 7 раз.
Опыт программирования: Больше трех лет
Языки программирования: C, C++, C#, Pawn, VBS, PHP, JS

Re: [INC] Tutor API

Сообщение KPOCT » 04 дек 2016, 01:14

Ребят, будьте добры, залейте TutorAPI.sma.
(2*b) || !(2*b)
Аватара пользователя
KPOCT
 
Сообщения: 65
Зарегистрирован: 21 фев 2016, 23:33
Благодарил (а): 21 раз.
Поблагодарили: 7 раз.
Опыт программирования: Больше трех лет
Языки программирования: C, C++, C#, Pawn, VBS, PHP, JS

Re: [INC] Tutor API

Сообщение flymic24 » 04 дек 2016, 10:32

KPOCT,
Код: Выделить всё
/*===================================================================================================================================================================================================================================
                                                                                                [Подгружаем API amxmodx]
===================================================================================================================================================================================================================================*/

#include <amxmodx>

/*===================================================================================================================================================================================================================================
                                                                                                [Макросы]
===================================================================================================================================================================================================================================*/

#define TutorSoundNone        -1

#define MAX_MSG_LEN            369
#define MAX_MSG_LEN2        185

#define PRECACHE_SOUND        precache_sound
#define PRECACHE_GENERIC    precache_generic
#define GET_USER_MSG_ID        get_user_msgid
#define MESSAGE_BEGIN        message_begin
#define WRITE_BYTE            write_byte
#define WRITE_SHORT            write_short
#define WRITE_STRING        write_string
#define MESSAGE_END()        message_end()

/*===================================================================================================================================================================================================================================
                                                                                                [Переменные]
===================================================================================================================================================================================================================================*/

// Целочисленные
new g_iMsgTutorClose;    // http://wiki.alliedmods.net/Half-Life_1_Game_Events#TutorClose    No arguments
new g_iMsgTutorText;    // http://wiki.alliedmods.net/Half-Life_1_Game_Events#TutorText        string byte string string short short short
new g_iMaxPlayers;
static const g_iSounds[][] =
{
    "events/enemy_died.wav",
    "events/friend_died.wav",
    "events/task_complete.wav",
    "events/tutor_msg.wav"
};

// Булевая
new bool:g_bReliable;    // Надёжность

// Динамический массив
new Array:g_aMultiLang;    // Для записи мест которые нужно менять (ML)

/*===================================================================================================================================================================================================================================
                                                                                                [Natives, Precache, Init, End]
===================================================================================================================================================================================================================================*/

// Natives
public plugin_natives()
{
    register_native("TutorReliable", "NativeTutorReliable", 1);    // Изменение надёжности
    register_native("TutorShow", "NativeTutorShow", 0);            // Показ
    register_native("TutorClose", "NativeTutorClose", 1);        // Закрытие
}

// Precache
public plugin_precache()
{
    // Graffic Effects
    PRECACHE_GENERIC("gfx/career/icon_i.tga");
    PRECACHE_GENERIC("gfx/career/icon_skulls.tga");
    PRECACHE_GENERIC("gfx/career/round_corner_ne.tga");
    PRECACHE_GENERIC("gfx/career/round_corner_nw.tga");
    PRECACHE_GENERIC("gfx/career/round_corner_se.tga");
    PRECACHE_GENERIC("gfx/career/round_corner_sw.tga");
    
    
// Resources
    PRECACHE_GENERIC("resource/TutorScheme.res");
    PRECACHE_GENERIC("resource/UI/TutorTextWindow.res");
    
    
// Sounds
    PRECACHE_SOUND("events/enemy_died.wav");
    PRECACHE_SOUND("events/friend_died.wav");
    PRECACHE_SOUND("events/task_complete.wav");
    PRECACHE_SOUND("events/tutor_msg.wav");
}

// Init
public plugin_init()
{
    // Регистрируем
    register_plugin("Tutor API", "Alpha", "[WPMG]PRoSToTeM@");
    
    
// Получаем идентификаторы сообщений
    g_iMsgTutorClose = GET_USER_MSG_ID("TutorClose");
    g_iMsgTutorText = GET_USER_MSG_ID("TutorText");
    
    
// Получаем максимальное количество игроков
    g_iMaxPlayers = get_maxplayers();
    
    
// Создаём динамический массив
    g_aMultiLang = ArrayCreate();
}

// End
public plugin_end() ArrayDestroy(g_aMultiLang); // Удаляем массив

/*===================================================================================================================================================================================================================================
                                                                                                [AMXX API функции]
===================================================================================================================================================================================================================================*/

// Событие выхода игрока с сервера
public client_disconnect(iEntity) remove_task(iEntity); // Убираем задачу

/*===================================================================================================================================================================================================================================
                                                                                                [Native handlers]
===================================================================================================================================================================================================================================*/

// TutorReliable(bool:bReliable = false)
// Изменяет надёжность сообщения тутора
public NativeTutorReliable(bool:bReliable) g_bReliable = bReliable;

// TutorShow(iEntity = 0, iType = TutorDefault, Float:fTime = 0.0, iSound = TutorSoundNone, const iMessage[], any:...)
// Показываем тутор
public NativeTutorShow(iPlugin, iParams)
{
    // Получаем значения аргументов
    new iEntity = get_param(1);            // 1-ый
    new iType = get_param(2);            // 2-ой
    new Float:fTime = get_param_f(3);    // 3-ий
    new iSound = get_param(4);            // 4-ый
    
    
// Сообщение
    new iBuffer[MAX_MSG_LEN];
    new iBuffer2[MAX_MSG_LEN2];
    
    
// Отсылаем одному игроку
    if (iEntity)
    {
        // Заменяем все LANG_PLAYER, на ID получателя
        for (new iArg = 6; iArg < iParams; iArg++)
        {
            // Если аргумент не равен LANG_PLAYER переходим к следующему аргументу
            if (get_param_byref(iArg) != LANG_PLAYER)
                continue;
            
            
// Получаем следующий аргумент
            get_string(iArg + 1, iBuffer, charsmax(iBuffer));
            
            
// Если это не ML ключ переходим к следующему аргументу
            if (GetLangTransKey(iBuffer) == TransKey_Bad)
                continue;
            
            
// Меняем численное значение аргумента
            set_param_byref(iArg++, iEntity);
        }
        
        
// Если аргументов больше 5 форматируем сообщение
        if (iParams > 5) vdformat(iBuffer, charsmax(iBuffer), 5, 6);
        // Иначе получаем 5 аргумент
        else get_string(5, iBuffer, charsmax(iBuffer));
        
        
// Преобразуем
        utf8Tocp1251(iBuffer, iBuffer2, charsmax(iBuffer2));
        
        
// Отсылаем
        MESSAGE_BEGIN(g_bReliable ? MSG_ONE : MSG_ONE_UNRELIABLE, g_iMsgTutorText, _, iEntity);
        WRITE_STRING(iBuffer2);
        WRITE_BYTE(0);
        WRITE_SHORT(0);
        WRITE_SHORT(0);
        WRITE_SHORT(iType);
        MESSAGE_END();
        
        
// Убираем task
        remove_task(iEntity);
        
        
// Если есть время, то задаём задачу
        if (fTime)
        {
            // Записываем в аргументы задачи надёжность
            new iTaskArgs[1];
            
            iTaskArgs
[0] = _:g_bReliable;
            
            set_task
(fTime, "TaskTutorClose", iEntity, iTaskArgs, 1);
        }
        
        
// Проигрываем звук
        if (iSound != TutorSoundNone) PlaySound(iEntity, _, g_iSounds[iSound], _, g_bReliable);
    }
    // Отсылаем всем
    else
    
{
        // Количество аргументов, текущий аргумент
        new iChangeArgsCount, iArg;
        
        
// Записываем все аргументы содержащие LANG_PLAYER
        for (iArg = 6; iArg < iParams; iArg++)
        {
            // Если аргумент не равен LANG_PLAYER переходим к следующему аргументу
            if (get_param_byref(iArg) != LANG_PLAYER)
                continue;
            
            
// Получаем следующий аргумент
            get_string(iArg + 1, iBuffer, charsmax(iBuffer));
            
            
// Если это не ML ключ переходим к следующему аргументу
            if (GetLangTransKey(iBuffer) == TransKey_Bad)
                continue;
            
            
// Записываем в массив
            ArrayPushCell(g_aMultiLang, iArg++);
            
            iChangeArgsCount
++;
        }
        
        if 
(iChangeArgsCount)
        {
            // Массив из игроков
            new iPlayers[32];
            // Всего игроков
            new iPlayersCount;
            // Последний игрок
            new iPlayer;
            
            
// Получаем игроков
            get_players(iPlayers, iPlayersCount);
            
            
// Делаем цикл из игроков
            for (new i = 0; i < iPlayersCount; i++)
            {
                // Сохраняем последнего игрока
                iPlayer = iPlayers[i];
                
                
// Меняем аргументы LANG_PLAYER на ID игрока
                for (iArg = 0; iArg < iChangeArgsCount; iArg++)
                    set_param_byref(ArrayGetCell(g_aMultiLang, iArg), iPlayer);
                
                
// Форматируем сообщение
                vdformat(iBuffer, charsmax(iBuffer), 5, 6);
                
                
// Преобразуем
                utf8Tocp1251(iBuffer, iBuffer2, charsmax(iBuffer2));
                
                
// Отсылаем
                MESSAGE_BEGIN(g_bReliable ? MSG_ONE : MSG_ONE_UNRELIABLE, g_iMsgTutorText, _, iPlayer);
                WRITE_STRING(iBuffer2);
                WRITE_BYTE(0);
                WRITE_SHORT(0);
                WRITE_SHORT(0);
                WRITE_SHORT(iType);
                MESSAGE_END();
                
                
// Убираем task
                remove_task(iPlayer);
                
                
// Если есть время, то задаём задачу
                if (fTime)
                {
                    // Записываем в аргументы задачи надёжность
                    new iTaskArgs[1];
                    
                    iTaskArgs
[0] = _:g_bReliable;
                    
                    set_task
(fTime, "TaskTutorClose", iPlayer, iTaskArgs, 1);
                }
                
                
// Проигрываем звук
                if (iSound != TutorSoundNone) PlaySound(iPlayer, _, g_iSounds[iSound], _, g_bReliable);
            }
            
            
// Очищаем массив
            ArrayClear(g_aMultiLang);
        }
        else
        
{
            // Если аргументов больше 5 форматируем сообщение
            if (iParams > 5) vdformat(iBuffer, charsmax(iBuffer), 5, 6);
            // Иначе получаем 5 аргумент
            else get_string(5, iBuffer, charsmax(iBuffer));
            
            
// Преобразуем
            utf8Tocp1251(iBuffer, iBuffer2, charsmax(iBuffer2));
            
            
// Отсылаем
            MESSAGE_BEGIN(g_bReliable ? MSG_ALL : MSG_BROADCAST, g_iMsgTutorText);
            WRITE_STRING(iBuffer2);
            WRITE_BYTE(0);
            WRITE_SHORT(0);
            WRITE_SHORT(0);
            WRITE_SHORT(iType);
            MESSAGE_END();
            
            
// Массив из игроков
            new iPlayers[32];
            // Всего игроков
            new iPlayersCount;
            // Последний игрок
            new iPlayer;
            
            
// Получаем игроков
            get_players(iPlayers, iPlayersCount);
            
            
// Делаем цикл из игроков
            for (new i = 0; i < iPlayersCount; i++)
            {
                // Сохраняем последнего игрока
                iPlayer = iPlayers[i];
                
                
// Убираем task
                remove_task(iPlayer);
                
                
// Если есть время, то задаём задачу
                if (fTime)
                {
                    // Записываем в аргументы задачи надёжность
                    new iTaskArgs[1];
                    
                    iTaskArgs
[0] = _:g_bReliable;
                    
                    set_task
(fTime, "TaskTutorClose", iPlayer, iTaskArgs, 1);
                }
            }
            
            
// Проигрываем звук
            if (iSound != TutorSoundNone) PlaySound(_, _, g_iSounds[iSound], _, g_bReliable);
        }
    }
}

// TutorClose(iEntity = 0)
// Закрытие тутора
public NativeTutorClose(iEntity)
{
    if (iEntity)
    {
        MESSAGE_BEGIN(g_bReliable ? MSG_ONE : MSG_ONE_UNRELIABLE, g_iMsgTutorClose, _, iEntity);
        MESSAGE_END();
        
        remove_task
(iEntity);
    }
    else
    
{
        MESSAGE_BEGIN(g_bReliable ? MSG_ALL : MSG_BROADCAST, g_iMsgTutorClose);
        MESSAGE_END();
        
        for 
(new i = 1; i <= g_iMaxPlayers; i++)
            remove_task(i);
    }
}

/*===================================================================================================================================================================================================================================
                                                                                                [Tasks handlers]
===================================================================================================================================================================================================================================*/

public TaskTutorClose(const iTaskArgs[], iEntity)
{
    MESSAGE_BEGIN(iTaskArgs[0] ? MSG_ONE : MSG_ONE_UNRELIABLE, g_iMsgTutorClose, _, iEntity);
    MESSAGE_END();
}

/*===================================================================================================================================================================================================================================
                                                                                                [Stocks]
===================================================================================================================================================================================================================================*/

// UTF8 to cp1251 stock by PomanoB, other code styling xD
stock utf8Tocp1251(const string[], output[], maxlen)
{
    new i, len, j, char1, char2
    len 
= strlen(string)
    while(string[i] && j <= maxlen)
    {
        if (+ 1 < len)
        {
            char1 = string[i]&0xFF
            char2 
= string[i+1]&0xFF
            if 
(char1 == 0xD0 && char2 == 0x81)
            {
                output[j] = 168
                i
++
            }
            else
            if 
(char1 == 0xD1 && char2 == 0x91)
            {
                output[j] = 184
                i
++
            }
            else
            if 
(char1 == 0xD0 && char2 >= 0x90 && char2 <= 0xBF)
            {
                output[j] = char2 + 48
                i
++
            }
            else
            if 
(char1 == 0xD1 && char2 >= 0x80 && char2 <= 0x8F)
            {
                output[j] = char2 + 112
                i
++
            }
            else
                output
[j] = string[i]
        }
        else
            output
[j] = string[i]
        i++
        j++
    }
    
    output
[maxlen] = 0;
}

stock PlaySound(const pReceiver = 0, const pSender = 0, const szSound[], const iPitch = PITCH_NORM, const bool:bReliable = false)
{
    if (bReliable)
    {
        if (pReceiver)
        {
            message_begin(MSG_ONE, get_user_msgid("SendAudio"), _, pReceiver)
        }
        else
        
{
            message_begin(MSG_ALL, get_user_msgid("SendAudio"))
        }
    }
    else
    
{
        if (pReceiver)
        {
            message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SendAudio"), _, pReceiver)
        }
        else
        
{
            message_begin(MSG_BROADCAST, get_user_msgid("SendAudio"))
        }
    }
    
    write_byte
(pSender)
    write_string(szSound)
    write_short(iPitch)
    message_end()
}
Аватара пользователя
flymic24
 
Сообщения: 209
Зарегистрирован: 05 окт 2012, 17:29
Откуда: Bryansk
Благодарил (а): 4 раз.
Поблагодарили: 76 раз.
Опыт программирования: Около года
Языки программирования: Counter-Strike 1.6

Re: [INC] Tutor API

Сообщение L4D2 » 04 дек 2016, 15:20

Если б по координатам можно было бы его изменить, то и цены б ему не было.

==============================================
|| Пишу не большие плагины под заказ: Заказ онлайн (Кликабельно)
|| Ссылка на официальный топик: заказ плагинов.
|| Желаешь оставить отзыв: тебе сюда(кликни).
==============================================
Аватара пользователя
L4D2
 
Сообщения: 792
Зарегистрирован: 25 июн 2011, 19:26
Благодарил (а): 240 раз.
Поблагодарили: 100 раз.
Языки программирования: Counter-Strike 1.6

Re: [INC] Tutor API

Сообщение KPOCT » 04 дек 2016, 18:42

L4D2 писал(а):Если б по координатам можно было бы его изменить, то и цены б ему не было.

Это да, было бы очень здоровски.
(2*b) || !(2*b)
Аватара пользователя
KPOCT
 
Сообщения: 65
Зарегистрирован: 21 фев 2016, 23:33
Благодарил (а): 21 раз.
Поблагодарили: 7 раз.
Опыт программирования: Больше трех лет
Языки программирования: C, C++, C#, Pawn, VBS, PHP, JS

Re: [INC] Tutor API

Сообщение KPOCT » 05 дек 2016, 11:27

Ник: KP0CT
Скрин:
Снимок.PNG


Избежать этого никак нельзя?
Кроме замены unicode-символов на обычные.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
(2*b) || !(2*b)
Аватара пользователя
KPOCT
 
Сообщения: 65
Зарегистрирован: 21 фев 2016, 23:33
Благодарил (а): 21 раз.
Поблагодарили: 7 раз.
Опыт программирования: Больше трех лет
Языки программирования: C, C++, C#, Pawn, VBS, PHP, JS

Пред.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4