Главная | Комментарии | О проекте
Чтение RSS
Суперсайт
Главная Контакты Карта сайта Добавить в избранное
  • Кто OnLine

    Всего на сайте: 14
    Гостей: 1
    Пользователи: - отсутствуют
    Роботы: Yandex Bot, Yandex Bot, Google Bot, crawl Bot, Google Bot, Yandex Bot, Yandex Bot, Yandex Bot, Yandex Bot, Yandex Bot

    Опрос пользователей

    Для какого мода Вы пишите плагины?

    • Популярное

    Рекомендуем

    • AMX Mod X
    • up.org.ua

    Наши друзья


  • Автор: Admin Дата: 19-02-2012, 15:34 Просмотров: 8503

    Урок 13. Включение и выключение функции игроком.

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

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

    Какая же логика у данного процесса?
    Для начала нужно определиться будет ли нужная функция при подключении к серверу включена или выключена. Для примера представим, что функция для игрока будет по умолчанию выключена:
    new bool:g_bFuncUse [33] = false

    В данном коде создается массив из булевых переменных присваивается значение ложь всем массиву. Этот массив и является «переключателем» выключена/выключена функция для каждого из игроков по отдельности. Но как вы уже догадались, сам по себе выключатель ни чего не сделает, его нужно включить в какую то схему, этой схемой будет «Условие» в котором будет проверяться положение «переключателя»:
    if(g_bFuncUse[id]){
        //Выключатель включен
    }else{
        //Выключатель выключен
    }

    Вроде бы как все работает, но чего то не хватает не так ли? Вижу, правильно думаете! Не хватает команды которая будет включать и выключать переключатель. С этим еще проще, регистрируем команду say и создаем для нее функцию:
    register_clcmd("say","fOnOff")
    ...
    public fOnOff(id){
        //Получение что написал игрок
        new args[10]
        read_args(args,9)
        remove_quotes(args)
        
        //Если было написано /off
        if(equal(args, "/off", 4)){
            g_bFuncUse[id] = false
            client_print(id,print_chat,"[scripts] Cmd disable")        
        }
        //Если было написано /on    
        if(equal(args, "/on", 4)){
            g_bFuncUse[id] = true
            client_print(id,print_chat,"[scripts] Cmd is activated")
        }
    }

    Как вы уже догадались, команды у нас будут say /on и say /off.

    А так же нельзя забывать, что игрок может выйти и на его место войдет другой, по этому переменную нужно приводить в исходное состояние, например так:
    public client_connect(id){
        g_bFuncUse[id] = false
    }

    Можно и при выходе игрока, в теории разницы ни какой нету, все зависит от структуры вашего плагина.

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

    /* Plugin generated by AMXX-Studio */

    #include <amxmodx>
    #include <amxmisc>
    #include <fun>
    #include <fakemeta>
    #include <hamsandwich>

    new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
    30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }

    new const MAXCLIP[] = { -1, 13, -1, 10, -1, 7, -1, 30, 30, -1, 30, 20, 25, 30, 35, 25, 12, 20,
    10, 30, 100, 8, 30, 30, 20, -1, 7, 30, 30, -1, 50 }


    #define PLUGIN "[scripts] on/off function"
    #define VERSION "1.0"
    #define AUTHOR "Admin"

    new bool:g_bFuncUse[33] = false

    public plugin_init()
    {
        register_plugin(PLUGIN, VERSION, AUTHOR)
        
        register_clcmd("say","fOnOff")
        register_message(get_user_msgid("CurWeapon"), "messageCurWeapon")
        
        
    }
    public fOnOff(id){
        new args[10]
        read_args(args,9)
        remove_quotes(args)
        
        if(equal(args, "/off", 4)){
            g_bFuncUse[id] = false
            client_print(id,print_chat,"[scripts] Cmd disable")    
            
            set_user_gravity(id,1.0)
        }
        
        if(equal(args, "/on", 4)){
            g_bFuncUse[id] = true
            client_print(id,print_chat,"[scripts] Cmd is activated")
            
            set_user_gravity(id,0.5)
        }
    }
    public client_connect(id){
        g_bFuncUse[id] = false
    }
    public messageCurWeapon(msg_id, msg_dest, msg_entity){
        
        if(!g_bFuncUse[msg_entity])
            return PLUGIN_CONTINUE
        
        if(get_msg_arg_int(1) != 1)
            return PLUGIN_CONTINUE
        
        static weapon
        weapon = get_msg_arg_int(2)
        
        if(MAXBPAMMO[weapon] > 2){
            set_pdata_int(get_pdata_cbase(msg_entity, 373), 51, MAXCLIP[weapon], 4)
            set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
        }
        return PLUGIN_CONTINUE
    }    


    Но в функции messageCurWeapon, использован немного другой способ контроля положения переключателя выл/выкл.
    Раньше у нас была логика такая:
    Если переключатель включен то:
    ...
    Если нет то
    ...

    А в данном варианте:
        if(!g_bFuncUse[msg_entity])
            return PLUGIN_CONTINUE

    Если переключатель не включен, то возвращаем return PLUGIN_CONTINUE, что прервет дальнейшее выполнение функции.

    Как вы понимаете можно было использовать и другой способ, и выглядело бы это так:
    public messageCurWeapon(msg_id, msg_dest, msg_entity){
        
        if(g_bFuncUse[msg_entity]){
            
            
            if(get_msg_arg_int(1) != 1)
                return
            
            static weapon
            weapon = get_msg_arg_int(2)
            
            if(MAXBPAMMO[weapon] > 2){
                set_pdata_int(get_pdata_cbase(msg_entity, 373), 51, MAXCLIP[weapon], 4)
                set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
            }
        }
    }

    Как видно, сразу же код "уплывает" в право, при том что нет необходимости в этом, необходимость была бы, если дальше был бы еще какой то код, который было бы необходимо выполнить.

    Теперь пару слов о том, как можно еще проще использовать команды включения выключения, например если для этого хочется использовать одну команду,а не две разные.
    Для этого регистрируется команда:
    register_clcmd("say /megakomanda","fOnOff")

    А в функции делается проверка на состояние переключателя и переводится в другое положение:
    public fOnOff(id){
        if(g_bFuncUse[id]){
            g_bFuncUse[id] = false
            client_print(id,print_chat,"[scripts] Cmd disable")  
        }else{
            g_bFuncUse[id] = true
            client_print(id,print_chat,"[scripts] Cmd is activated")
        }
    }


    На самом деле вариантов реализации включения/выключения очень много, все зависит от вашей фантазии.
    Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
    Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
    Урок 13. Включение и выключение функции игроком.
    lenarsaitov

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Спасибо lol
    defa

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    new bool:g_bFuncUse [32] = false -> new bool:g_bFuncUse[33] = false smile
    Admin

    30.07.2011
    ICQ: 980500
    Публикаций: 507
    Комментариев: 333
    Репутация: -  58  +

    Зачем? что бы был пустой закрывающий символ?
    вот простой тупой пример, что в массиве с размерностью 32 все ок.

    /* Plugin generated by AMXX-Studio */

    #include <amxmodx>
    #include <amxmisc>

    #define PLUGIN "New Plug-In"
    #define VERSION "1.0"
    #define AUTHOR "Admin"


    public plugin_init() {
        register_plugin(PLUGIN, VERSION, AUTHOR)

        register_clcmd("say /t","test")
        
    }
    public test(id){
        

        new mas[32]
        
        for(new i = 0; i < 32; i++){
            
            mas[i] = i+100
        
            console_print(0,"id:
    %d",i)
            
        }
        
        console_print(0,"----------------------------
    4;)
        
        for(new i = 0; i < 32; i++){
            
            console_print(0,"id:
    %d",mas[i])
            
        }
        
    }


    или чего то не догоняю ) поясни на примере!
    --------------------
    Legenda

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Спасибо, хороший урок. А как сделать, что бы переключатель сохранялся после смены карты, например в файл по стимид или по другой информации? Видел такое в плагине admin_esp_mini, параметры сохраняются в файл vault.ini виде AESPmini_STEAM_0:1:12345678 11. Если будет свободное время, можете сделать урок, как сохранять параметры, поставленные игроком в плагине, и как потом их применять.
    defa

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Так как размерность массива начинается с 0 до N, то в твоём случае будет g_bFuncUse[0-31], но количество игроков MAX = 32. В итоге запросто можно выйти за пределы границ массива, т.к. 32 ячейки нету. Это последует за собой ошибку в логах:
    error 032: array index out of bounds (variable X)
    Admin

    30.07.2011
    ICQ: 980500
    Публикаций: 507
    Комментариев: 333
    Репутация: -  58  +

    defa, почему в примере выше нет ошибки?
    32 ячейка как раз таки есть. так как 0 это первая ячейка по количеству( см пример)
    а 31я ячейка будет являться 32.
    Но не остается ячейки на пустой символ...
    Я не утверждаю ничего, просто хочу докопаться до истины с этим закрывающим последним пустым символом...
    --------------------
    defa

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Смотри, у игроков Id равным нулю быть не может, если Id = 32, => g_bFuncUse[id] = g_bFuncUse[32], а 32 нету.
    Admin

    30.07.2011
    ICQ: 980500
    Публикаций: 507
    Комментариев: 333
    Репутация: -  58  +

    Айди и не бывает равным нулю,а нумерация массива начинается с нуля.
    id 1 = mas[0]
    id 2 = mas[2]
    id 32 = mas[31]
    вот ут и вопрос, нужен ли последний пустой символ или нет.
    в прмире выше нет пустого символа и ошибки нет.
    --------------------
    defa

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Господи, причём здесь пустой символ, мы не со строками работаем)

    d 1 = mas[0]

    id 2 = mas[2]

    id 32 = mas[31]

    Это всё обычные присвоения, а если id взять в качестве индекса, то 32 вылезет за пределы.([32] => 0-31, 32 не влезет, [33] => 0-32, допустимо.
    Admin

    30.07.2011
    ICQ: 980500
    Публикаций: 507
    Комментариев: 333
    Репутация: -  58  +

    АА въехал )
    тогда везде надо исправить в примерах 32 на 33 :)

    У меня на серверах нигде нету 32 слотов, по этому ни когда не сталкивался с этим...

    Забавно, при этом во всех моих основных плагинах на серверах, правильно стоит 33 )
    старею :)
    --------------------

    Информация

    Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Наверх

Реклама