AFK Protection

AFK Protection 3.1.2

Нет прав для скачивания
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
Есть причина использования в create_cvar 0 вместо FCVAR_NONE?
Мне визуально больше так нравится.

Может лучше создать переменную куда будет сохраняться значение квара g_Icon чтобы каждый раз не использовать get_pcvar_num? Он может измениться только при старте карты, поэтому логичнее будет 1 раз получить при старте карты.
Может и лучше. плагин-то маленький, не думаю что здесь это играет большую роль.
2 Дек 2018
Есть причина использования в create_cvar 0 вместо FCVAR_NONE?
а есть какая-либо разница?
 
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
Может лучше создать переменную куда будет сохраняться значение квара g_Icon чтобы каждый раз не использовать get_pcvar_num? Он может измениться только при старте карты, поэтому логичнее будет 1 раз получить при старте карты.
а нельзя ее в себя же записать?
like:
Код:
public plugin_precache()
{
    g_Icon = create_cvar("afk_icon", "1", FCVAR_NONE, "Иконка (спрайт) над игроком. 0 - выкл. 1 - вкл.", true, 0.0, true, 1.0)
    g_Icon = get_pcvar_num(g_Icon)
    if(g_Icon) g_Sprite = precache_model("sprites/afk/afk.spr")
}
 
Сообщения
1,277
Реакции
2,262
Помог
57 раз(а)
sbelov020,
Код:
Мне визуально больше так нравится.
Представьте что плагин это связка ключей. Вы вынимаете её и видите на ключах бирки '1' '2' '3' '4'. А теперь вынимаете другую связку, и там 'дом', 'гараж', 'работа'. Что удобнее и легче с ходу усвоить? ;) Всегда используйте поясняющее(когда из имени можно понять суть) именование, когда это возможно, потому как это повышает читабельность. Вы я думаю видели множество плагинов, где упоминаются коды возврата PLUGIN_CONTINUE, PLUGIN_HANDLED. Это те же самые константы, что и FCVAR_NONE, т.е. за ними "под капотом" закреплены обычные числа (см. amxmodx_const.inc и cvars.inc). Почему все нормальные скриптеры используют именно константы, а не числа? Читабельность. Всегда думайте об этом, изучайте по примерам других скриптеров этикет кода, и старайтесь его соблюдать. Больше всего раздражает, когда люди, просящие помощи, сбрасывают код, наполненный магическими числами, и приходиться разбираться, что какое число в той или иной конструкции обозначает.
 
Последнее редактирование:
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
BlackSignature, да, я уже понял. Ночью почитал в интернете немного и исправил на FCVAR_NONE.
 
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
w0w,
Код:
#include <amxmodx>
#include <fun>
#include <engine>
#include <fakemeta_util>

#define PLUGIN  "AFK Protection"
#define VERSION "2.2.1"
#define AUTHOR  "rapara13/Nordic Warrior"

#define TAG "AFK Менеджер"    // Задаем тег

new isAfk[MAX_PLAYERS+1], Float:gPlayerPosition[MAX_PLAYERS+1][3], gMoveTimer[MAX_PLAYERS+1], Float:ViewAngle[MAX_PLAYERS+1][3]
new g_Effects, g_Message, g_Icon, g_CvarIcon, g_Block, g_TimeAfk, g_Sprite, g_forwardId

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    
    new pCvar = create_cvar("afk_effects", "3", FCVAR_NONE, "Эффекты: 0 - выкл. 1 - прозрачность игрока, 2 - затемнение экрана игроку, 3 - всё вместе", true, 0.0, true, 3.0)
    bind_pcvar_num(pCvar, g_Effects)
    
    pCvar = create_cvar("afk_type_message", "2", FCVAR_NONE, "Тип сообщений клиенту о переходе в режим АФК: 0 - выкл. 1 - hud, 2 - DHUD, 3 - чат", true, 0.0, true, 3.0)
    bind_pcvar_num(pCvar, g_Message)
    
    pCvar = create_cvar("afk_time", "15", FCVAR_NONE, "Время простоя игрока до входа в режим АФК. (в секундах)", true, 1.0)
    bind_pcvar_num(pCvar, g_TimeAfk)
    
    g_Block = create_cvar("afk_block", "1", FCVAR_NONE, "Блокировать ли атаку афк-шнику: 0 - выкл. 1 - вкл.", true, 0.0, true, 1.0)
    hook_cvar_change(g_Block, "CallBack_CvarChange")

    g_forwardId = register_forward(FM_CmdStart, "fw_CmdStart")

    AutoExecConfig(true, "afk_protection")

    set_task(0.5, "afkcheck", 0, .flags="b")
}
public plugin_natives() register_native("is_afk", "native_is_afk")

public client_disconnected(id) isAfk[id] = false

public plugin_precache()
{
    g_Icon = create_cvar("afk_icon", "1", FCVAR_NONE, "Иконка (спрайт) над игроком. 0 - выкл. 1 - вкл.", true, 0.0, true, 1.0)
    g_CvarIcon = get_pcvar_num(g_Icon)
    if(g_CvarIcon) g_Sprite = precache_model("sprites/afk/afk.spr")
}
public afkcheck()
{
    static Float:current_v_angle[3], Float:origin[3], Float:distance

    for(new i = 1; i <= MAX_PLAYERS; i++)
    {
        if (!is_user_alive(i)) continue
        if (pev(i, pev_flags) & FL_INWATER) continue
        
        entity_get_vector(i, EV_VEC_origin, origin)
        entity_get_vector(i, EV_VEC_v_angle, current_v_angle)

        distance = vector_distance(gPlayerPosition[i], origin)

        if ((distance <= 1) & (ViewAngle[i][0] == current_v_angle[0] || ViewAngle[i][1] == current_v_angle[1]))
        {
            gMoveTimer[i]++
            if(gMoveTimer[i] > g_TimeAfk * 2)
            {
                gMoveTimer[i] = 0
                afk(i)
            }
        }
        else
        {
            gMoveTimer[i] = 0
            ViewAngle[i][0] = current_v_angle[0]
            ViewAngle[i][1] = current_v_angle[1]
            back(i)
        }
        gPlayerPosition[i][0] = origin[0]
        gPlayerPosition[i][1] = origin[1]
        gPlayerPosition[i][2] = origin[2]
    }
}
public afk(id)
{
    if(isAfk[id])
    return
 
    if(is_user_alive(id))
    {
        set_user_godmode(id, 1)
        if(g_Effects == 1 || g_Effects == 3)
        {
            set_user_rendering(id, kRenderFxNone,255,255,255,kRenderTransAlpha,120)
        }
        if(g_Effects == 2 || g_Effects == 3)
        {
            message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, id)
            write_short(~0)
            write_short(~0)
            write_short(0x0004)
            write_byte(0)
            write_byte(0)
            write_byte(0)
            write_byte(130)
            message_end()
        }
        if(g_CvarIcon) add_icon(id)
        set_pev(id, pev_solid, SOLID_NOT)

        switch(g_Message)
        {
            case 1:
            {
                set_hudmessage(0, 206, 209, -1.0, 0.1, 0, 1.0, 3.0, 0.1, 0.2, -1)
                show_hudmessage(id, "[%s]^nТы перешел в режим АФК.", TAG)
            }
            case 2:
            {
                set_dhudmessage(0, 206, 209, -1.0, 0.1, 0, 1.0, 3.0, 0.1, 0.2)
                show_dhudmessage(id, "[%s]^nТы перешел в режим АФК.", TAG)
            }
            case 3:
            {
                client_print_color(id, print_team_default, "^4[%s] ^1Ты перешел в ^3режим ^4AFK.", TAG)
            }
        }
    }
    isAfk[id] = true
}
public back(id)
{
    if(!isAfk[id])
    return

    set_user_godmode(id, 0)
    if(g_Effects == 1 || g_Effects == 3)
    {
        set_user_rendering(id,0,0,0,kRenderTransAlpha,0)
    }
    if(g_Effects == 2 || g_Effects == 3)
    {
        message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, id)
        write_short(1<<10)
        write_short(1<<10)
        write_short(0x0000)
        write_byte(0)
        write_byte(0)
        write_byte(0)
        write_byte(100)
        message_end()
    }
    if(g_CvarIcon) remove_icon(id)
    set_pev(id, pev_solid, SOLID_SLIDEBOX)

    switch(g_Message)
    {
        case 1:
        {
            set_hudmessage(148, 0, 211, -1.0, 0.2, 0, 1.0, 3.0, 0.1, 0.2, -1)
            show_hudmessage(id, "[%s]^nТы вышел из режима АФК.", TAG)
        }
        case 2:
        {
            set_dhudmessage(148, 0, 211, -1.0, 0.2, 0, 1.0, 3.0, 0.1, 0.2)
            show_dhudmessage(id, "[%s]^nТы вышел из режима АФК.", TAG)
        }
        case 3:
        {
            client_print_color(id, print_team_default, "^4[%s] ^1Ты вышел из ^3режима ^4AFK.", TAG)
        }
    }
    isAfk[id] = false
}
public fw_CmdStart(id, UC_Handle, Seed) // блокируем атаку афк-шнику
{
    if(isAfk[id])
    {
        new buttons = get_uc(UC_Handle, UC_Buttons)
        if((buttons & IN_ATTACK))
        {
            buttons &= ~IN_ATTACK
            set_uc(UC_Handle, UC_Buttons, buttons)
        }
        if((buttons & IN_ATTACK2))
        {
            buttons &= ~IN_ATTACK2
            set_uc(UC_Handle, UC_Buttons, buttons)
        }
    }
}
public add_icon(index)
{
    if(!is_user_connected(index))
    return;
    new origin[3]

    get_user_origin(index, origin)
 
    message_begin(MSG_ALL, SVC_TEMPENTITY);
    write_byte(TE_SPRITE);
    write_coord(origin[0] + 6)
    write_coord(origin[1])
    write_coord(origin[2] += 53)
    write_short(g_Sprite);
    write_byte(5);
    write_byte(120);
    message_end();
    set_task(2.0, "add_icon", index);
}
public remove_icon(index)
{
    if(!is_user_connected(index))
    return;
 
    message_begin(MSG_ALL, SVC_TEMPENTITY)
    write_byte(TE_KILLPLAYERATTACHMENTS);
    write_byte(index);
    message_end();
    remove_task(index);
}
public CallBack_CvarChange(pcvar, szOldValue[], szNewValue[])
{
    if(pcvar == g_Block)
    {
        new iOldValue = str_to_num(szOldValue);
        new iCvarEnabled = str_to_num(szNewValue);
        if(iCvarEnabled && iOldValue == 0)
        {
            g_forwardId = register_forward(FM_CmdStart, "fw_CmdStart")
        }
        else if(!iCvarEnabled && iOldValue == 1)
        {
            unregister_forward(FM_CmdStart, g_forwardId)
        }
    }
}
public native_is_afk(amxx, params)
{
    enum { player = 1 }

    new iPlayer = get_param(player)
    return isAfk[iPlayer]
}
тогда так. правильно?
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
sbelov020, установка кваров и хук смены - да.
 
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
w0w, а остальное? Ведь на данный момент это конечный код. Только позже, сделаю еще мультиязычность.
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
sbelov020,
1. get_user_msgid("ScreenFade") нужно вынести глобально, так как оно не меняется.

Код:
new g_iMsgScreenFade

public plugin_init()
{
    g_iMsgScreenFade = get_user_msgid("ScreenFade")
}
2. Недавно проверил hook_cvar_change, всё же не нужно проверять тот ли это квар или нет. Поэтому:

Код:
pCvar = create_cvar("afk_block", "1", FCVAR_NONE, "Блокировать ли атаку афк-шнику: 0 - выкл. 1 - вкл.", true, 0.0, true, 1.0)
hook_cvar_change(pCvar, "CallBack_CvarChange")
И убрать проверку в CallBack_CvarChange: if(pcvar == g_Block)

3. g_forwardId = register_forward(FM_CmdStart, "fw_CmdStart")
->
unregister_forward(g_forwardId = register_forward(FM_CmdStart, "fw_CmdStart"))
Код:
if(get_pcvar_num(pCvar))
    g_forwardId = register_forward(FM_CmdStart, "fw_CmdStart")
4. set_task -> set_task_ex. Меньше хардкода.
5. Делая код в одну строчку теряется удобство чтения, по моему мнению.

Код:
public plugin_natives()
{
    register_native("is_afk", "native_is_afk")
}

public client_disconnected(id)
{
    isAfk[id] = false
}
6. Форматирование кода, нужно поработать над этим.

Код:
if (!is_user_alive(i)) continue
if (pev(i, pev_flags) & FL_INWATER) continue
->
Код:
if (!is_user_alive(i) || pev(i, pev_flags) & FL_INWATER)
    continue
Подобные проверки этой:
Код:
if(!isAfk[id])
return
->
Код:
if(!isAfk[id])
    return
Некоторые глобальные переменные имеют префикс g в плагине (по сути надо g_ -Венгерская нотация-) а другие нет, что затрудняет чтение плагина.

7. MAX_PLAYERS нужно заменить на MaxClients, это не одно и то же. Первое это число игроков что поддерживает AMX Mod X а второе это число игроков что поддерживает сервер.

8. Используем только нужные значения:
message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, id)
->
message_begin(MSG_ONE, g_iMsgScreenFade, .player = id) (тут так же используем уже глобальную переменную).

9. В native_is_afk(amxx, params) я бы добавил проверку на валидность игрока.
 
Последнее редактирование:
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
нужно вынести глобально, так как оно не меняется.
разве это хорошо, когда много переменных?
подключать лишний инклуд ради замены цифры на константу?
6. Форматирование кода, нужно поработать над этим.

C++:
if (!is_user_alive(i)) continue
if (pev(i, pev_flags) & FL_INWATER) continue
->
C++:
if (!is_user_alive(i) || pev(i, pev_flags) & FL_INWATER)
continue
Подобные проверки этой:
C++:
if(!isAfk[id])
return
->
C++:
if(!isAfk[id])
return
тут была
сохранена форматация кода автора.
Некоторые глобальные переменные имеют префикс g
и в этих тоже. вчера тоже была такая мысль, но не стал переделывать, т.к. они являются массивами и я подумал, что их так удобнее отличить. это ошибка?

В native_is_afk(amxx, params) я бы добавил проверку на валидность игрока.
ну так разве этот твой код не является проверкой?

Код:
{
    ..
    enum { player = 1 }

    new iPlayer = get_param(player)
    ...
}
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
разве это хорошо, когда много переменных?
То что сейчас хуже чем создать переменную и записать в неё число всего один раз чем постоянно его получать.

подключать лишний инклуд ради замены цифры на константу?
Какая связь? Можно тогда не подключать include и копировать все нативы прямо себе в плагин, если так удобнее, что конечно неправильно. Нет никакой разницы от подключения этого инклуда.

тут была
сохранена форматация кода автора.
Думаю читабельнее будет как написал выше и не плодить проверки когда можно сделать так.

и в этих тоже. вчера тоже была такая мысль, но не стал переделывать, т.к. они являются массивами и я подумал, что их так удобнее отличить. это ошибка?
Имеется введу что некоторые имеют префикс g а другие что тоже глобальные не имеют префикс, как например isAfk. Можно сделать так: g_bIsAfk[MAX_PLAYERS+1].

ну так разве этот твой код не является проверкой?
Тут нет проверки на валидность игрока, только получение первого аргумента. Я бы добавил проверку на валидность с сообщением об ошибке (см. например как реализованы нативы в Multi Jump.
 
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
(см. например как реализованы нативы в Multi Jump.
Код:
bool:is_user_valid_native(id)
{
    if(!is_user_valid(id))
    {
        log_error(AMX_ERR_NATIVE, "%s Player out of range (%i)", g_szLogTag, id);
        return false;
    }
    return true;
}
это?

Тут нет проверки на валидность игрока, только получение первого аргумента.
тогда я запутался.

и да, в каком случае игрок может быть "невалидным"?
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
sbelov020, да, оно самое. Мало ли где может использоваться натив, даже когда игрок уже вышел или в каком-то цикле, таким образом плагин выдаст ошибку что такой-то игрок не валидный и можно будет исправить плагин добавив проверку на валидность.
 
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
Мало ли где может использоваться натив, даже когда игрок уже вышел или в каком-то цикле, таким образом плагин выдаст ошибку что такой-то игрок не валидный и можно будет исправить плагин добавив проверку на валидность.
Но разве писать такой код, чтоб все игроки были валидны - не забота других кодеров, которые захотят использовать мой натив?
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
sbelov020, как раз про это я и говорю. Что может быть ошибка или упущена проверка но об этом в большом коде сложно будет узнать, а так будет ошибка натива что игрок не валидный.
 
Сообщения
3,561
Реакции
1,559
Помог
131 раз(а)
вот это интересно. спасибо за инфу. я-то думал, откуда берутся все эти i, sz и т.д.

Форматирование кода, нужно поработать над этим.
что касается этого, то тут если сделать:

Diff:
public native_is_afk(amxx, params)
{
    enum { player = 1 }

    new iPlayer = get_param(player)
-return g_IsAfk[iPlayer]
+        return g_IsAfk[iPlayer]
}
вылазит loose indentation.

в остальных местах норм.
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
что касается этого, то тут если сделать:
Там этого не нужно делать. В других местах это нужно потому что оно вызывается например внутри условия поэтому мы даём знать табуляцией что оно находится внутри условия для лучшего чтения плагина.
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
sbelov020, имел ввиду в цикле:
Код:
for(new i = 1; i <= MAX_PLAYERS; i++)
->
Код:
for(new i = 1; i <= MaxClients; i++)
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу