Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 7 1 2 3 ... ПоследняяПоследняя
Показано с 1 по 10 из 62
  1. #1
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±

    Слежка за игроком (/spectate)

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

    Поехали...
    Для начала, создадим необходимую нам переменную, которая будет отвечать за ID того игрока, за которым мы наблюдаем:
    PHP код:
    new spectating[MAX_PLAYERS]; 
    Использовать эту переменную мы будем следующим образом:
    PHP код:
    spectating[playerid] = - 1// данное значение переменной, означает что мы игрок не за кем не наблюдает
    spectating[playerid] = playerid// любое значение, отличающееся от -1, будет значить, что игрок за кем-то наблюдает 
    Создавать мы будем, следующие команды:
    Код:
    /spectate - для того чтобы начать слежку за определенным игроком.
    /offspec - для того чтобы закончить слежку за определенным игроком.
    Мы также введем новый колбэк в мод, это облегчит процесс обновления режима слежки за определенным игроком.

    Перейдем непосредственно к коду...

    PHP код:
    // Я приведу пример на целом колбэке OnPlayerCommandText
    // Для определения ID игрока после команды (как параметр к команде), я буду использовать sscanf.
    // Подробнее как использовать OnPlayerCommandText и sscanf, можно узнать перейдя по ссылке в конце мануала
    public OnPlayerCommandText(playeridcmdtext[])
    {
        new 
    cmd[32],params[128];
        
    sscanf(cmdtext"s[32]s[128]"cmdparams);
        
        if(
    strcmp(cmd"/spectate"))
        {
            new 
    player_id;
            if(
    sscanf(params"d"player_id)) return SendClientMessage(playerid0xFFFFFF"/spectate [ID]");
            if(
    IsPlayerConnected(player_id))
            {
                
    //Получаем виртуальный мир игрока за которым следим и устанавливаем такой-же игроку который следит, аналогично с интерьером
                
    SetPlayerVirtualWorld(playerid,GetPlayerVirtualWorld(player_id));
                
    SetPlayerInterior(playerid,GetPlayerInterior(player_id));
                
    //Сейчас мы установим значение нашей переменной следящему игроку.
                
    spectating[playerid] = player_id;
                
    //Теперь, переведем следящего в режим наблюдения за игроком
                
    TogglePlayerSpectating(playerid1);

                
    //Разберёмся, находидтся ли игрок за которым следим в машине или нет. Установим соответствующий тип слежки.
                
    if(IsPlayerInAnyVehicle(player_id)) PlayerSpectateVehicle(playeridGetPlayerVehicleID(player_id), SPECTATE_MODE_NORMAL);
                else 
    PlayerSpectatePlayer(playeridplayer_idSPECTATE_MODE_NORMAL);
            }
            else return 
    SendClientMessage(playerid, -1"Игрок не найден!");
            return 
    1;
        }
        if(
    strcmp(cmd"/offspec"true) == 0)
        {
            if(
    IsPlayerConnected(playerid))
            {
                
    //Устанавливаем следящему виртуальный мир, который используется при spawn, аналогично с интерьером
                
    SetPlayerVirtualWorld(playerid,0);
                
    SetPlayerInterior(playerid,0);
                
    //Очищаем переменную
                
    spectating[playerid] = -1;
                
    //Отключаем режим наблюдения у следящего
                
    TogglePlayerSpectating(playerid0);
            }
            return 
    1;
        }
        return 
    0;

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

    PHP код:
    public OnPlayerStreamOut(playeridforplayerid)
    {
         
    //Данный паблик вызовется когда игрок за которым следим, пропадет из вида следящего (смена интерьера, виртуального мира)
        
    if(IsPlayerConnected(forplayerid))
        {
            if(
    spectating[forplayerid] == playerid)//Проверяем действительно ли следит следящий игрок именно за этим игроком (см. примечание 1)
            
    {
                
    //Колбэк указанный ниже, поможет нам быстро обновить режим слежки
                
    UpdateSpectatingStatus(forplayeridplayerid);
            }
        }
        return 
    1;
    }

    public 
    OnPlayerStateChange(playeridnewstateoldstate)
    {
        
    //Если игрок за которым следим, меняет свой статус относительно нас (садится в машину)
        
    for(new 0!= MAX_PLAYERSi++)
        {
            if(
    IsPlayerConnected(i))
            {
                if(
    spectating[i] == playerid)//Проверяем действительно ли следит следящий игрок именно за этим игроком
                
    {
                    
    //Колбэк указанный ниже, поможет нам быстро обновить режим слежки
                    
    UpdateSpectatingStatus(iplayerid);
                }
            }
        }
        return 
    1;

    Ну и наконец, добавим в любую точку мода, нашу функцию обновления режима слежки:
    PHP код:
    stock UpdateSpectatingStatus(spectatoridspectedid)
    {
        
    //Еще раз проверяем, совпадает ли значение в переменной следящего игрока с ID игрока за которым следят
        
    if(spectating[spectatorid] == spectedid)
        {
            
    //Приведенные ниже строчки-оповещения, вы можете не использовать
            
    if(GetPlayerState(spectedid) == PLAYER_STATE_WASTED) return GameTextForPlayer(spectatorid"~r~Target wasted!"50003); // игрок убит
            
    if(GetPlayerState(spectedid) == PLAYER_STATE_SPECTATING) return GameTextForPlayer(spectatorid"~r~Target in spectating mode!"50003); // игрок перешел в режим слежки
            
    if(!IsPlayerConnected(spectedid)) return GameTextForPlayer(spectatorid"~r~Target disconnected!"50003); // игрок отключился
            
            //Снова устанавливаем виртуальный мир следящему, то же самое, проделываем с интерьером
            
    SetPlayerVirtualWorld(spectatorid,GetPlayerVirtualWorld(spectedid));
            
    SetPlayerInterior(spectatorid,GetPlayerInterior(spectedid));
            
    //Отправляем следящего снова в режим слежки
            
    TogglePlayerSpectating(spectatorid1);
            if(
    IsPlayerInAnyVehicle(spectedid)) PlayerSpectateVehicle(spectatoridGetPlayerVehicleID(spectedid), SPECTATE_MODE_NORMAL);
            else 
    PlayerSpectatePlayer(spectatoridspectedidSPECTATE_MODE_NORMAL);
        }
        return 
    1;

    Дополнение
    Мне предложили отличное дополнение к режиму наблюдение - это переключение между игрокам за которыми следим, при помощи клавиш. Я выбрал клавиши NUM 4, NUM6. Итак, для этого нам потребуется задействовать паблик OnPlayerKeyStateChange:
    PHP код:
    public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
    {
        if(
    newkeys KEY_ANALOG_LEFT// проверяем нажатие клавиши NUM 4
        
    {
            if(
    spectating[playerid] != -1// проверяем наблюдает ли за кем-либо игрок
            
    {
                if(
    spectating[playerid] <= 0spectating[playerid] = GetMaxPlayers(); // если игрок наблюдает за минимальным ID, то перекидываем его на максимальный
                
    else spectating[playerid]--; // или убавляем -1 от ID игрока за кем следящий наблюдал ранее
                
    UpdateSpectatingStatus(playeridspectating[playerid]); // обновляем режим слежки
            
    }
        }
        
        if(
    newkeys KEY_ANALOG_RIGHT// проверяем нажатие клавиши NUM 6
        
    {
            if(
    spectating[playerid] != -1// проверяем наблюдает ли за кем-либо игрок
            
    {
                if(
    spectating[playerid] >= GetMaxPlayers()) spectating[playerid] = 0// если игрок наблюдает за максимальным ID, перекидываем его на минимальный
                
    else spectating[playerid]++; // или добавляем +1 к ID игрока за кем следящий наблюдал ранее
                
    UpdateSpectatingStatus(playeridspectating[playerid]); // обновляем режим слежки
            
    }
        }
        return 
    1;
        
    // Не спорю, удобнее будет из цикла вытаскивать ID самого большого подключившегося игрока
        // Но, я не думаю что это будет мелочью в плане быстродействия кода.
        // Можно также завести переменную и записывать в нёё самый последний ID подключившегося игрока (см. примечание 2)

    Заключение

    Важно помнить и учитывать следующие факторы:
    - В коде не используются, как может оказаться по вашему мнению, наиболее быстрые функции (исключение sscanf).
    - Изменять код приведенный в примере, вы можете как душе угодно, я помогу вам разобраться с получившимися багами.

    На этом всё...
    Ах да!

     Примечание 1
    Примечание 1
    OnPlayerStreamOut - вызывается для каждого игрока, который теряет из виду любого игрока сервера, именно поэтому нам необходима проверка на совпадение ID.

     Примечание 2
    Примечание 2
    Как же нам определить самый большой ID среди игроков? Попробуем так:
    PHP код:
    new last_id// создаем переменную для записи самого большого ID игрока

    public OnPlayerConnect(playerid)
    {
        if(
    playerid last_id// проверяем, больше ли ID подключившегося игрока, чем предыдущее значении перменной
        
    {
            
    last_id playerid// если так, то обновляем значение
        
    }
        return 
    1;
    }

    // Теперь в дополнении, при переключении кнопок, вместо GetMaxPlayers, можно использовать значение данной переменной
    // Единственный минус, в том, что если игрок отключится от сервера, максимальный ID - не обновится
    // Но я думаю мне предложат варианты как исправить данный минус 


    Использование OnPlayerCommandText + sscanf



    Автор мануала: wAx


    Последний раз редактировалось wAx; 19.06.2016 в 15:19.

  2. #2
    Аватар для L0ndl3m
    Пользователь

    Статус
    Оффлайн
    Регистрация
    19.10.2013
    Адрес
    Ярославль
    Сообщений
    1,366
    Репутация:
    774 ±
    Цитата Сообщение от wAx Посмотреть сообщение
    PHP код:
    for(new 0GetMaxPlayers(); i++) 
    Ась?

    Что на счёт того, чтобы добавить переключение между игроками во время наблюдения? Например нажав на KEY_JUMP ты начинаешь наблюдать за следующим игроком ( естественно этот игрок должен быть не мёртв, подключён и т.д. ). И на KEY_SPRINT аналогично, - наблюдение за предыдущим игроком.
    Последний раз редактировалось L0ndl3m; 07.03.2015 в 18:48.

  3. #3
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±
    Цитата Сообщение от Londlem Посмотреть сообщение
    Ась?

    Что на счёт того, чтобы добавить переключение между игроками во время наблюдения? Например нажав на KEY_JUMP ты начинаешь наблюдать за следующим игроком ( естественно этот игрок должен быть не мёртв, подключён и т.д. ). И на KEY_SPRINT аналогично, - наблюдение за предыдущим игроком.
    Ась? Ась?

    А что касаемо дополнения, то обязательно будет.

  4. #4
    Аватар для L0ndl3m
    Пользователь

    Статус
    Оффлайн
    Регистрация
    19.10.2013
    Адрес
    Ярославль
    Сообщений
    1,366
    Репутация:
    774 ±
    Цитата Сообщение от wAx Посмотреть сообщение
    Ась? Ась?

    А что касаемо дополнения, то обязательно будет.
    Ты действительно решил вызывать GetMaxPlayers при каждой итерации?

  5. #5
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±
    Обновил мануал и добавил пункт "Дополнение", в котором описана возможность переключения между игроками за которыми ведется наблюдение, посредством клавиш NUM 4 и NUM 6.

  6. #6
    Аватар для NewGreen
    Пользователь

    Статус
    Оффлайн
    Регистрация
    29.09.2014
    Сообщений
    61
    Репутация:
    44 ±
    Эту команду нужно доработать т.к. когда админ будет включать слежение за игроком находясь в интерьере/др. вирт. мире, то отключая слежение он будет проваливаться. Можно использовать дополнительные переменные или PVar
    PHP код:
    if(strcmp(cmd"/offspec"true) == 0
        { 
            if(
    IsPlayerConnected(playerid)) 
            { 
                
    //Устанавливаем следящему виртуальный мир, который используется при spawn, аналогично с интерьером 
                
    SetPlayerVirtualWorld(playerid,0); 
                
    SetPlayerInterior(playerid,0); 
                
    //Очищаем переменную 
                
    spectating[playerid] = -1
                
    //Отключаем режим наблюдения у следящего 
                
    TogglePlayerSpectating(playerid1); 
            } 
            return 
    1
        } 
    Вариант решения с использованием PVar:

    PHP код:
    if(strcmp(cmd"/spectate")) 
        { 
            new 
    player_id
            if(
    sscanf(params"d"player_id)) return SendClientMessage(playerid0xFFFFFF"/spectate [ID]"); 
            if(
    IsPlayerConnected(player_id)) 
            { 
    SetPVarInt(playerid,"GetPLVirtualWorld",GetPlayerVirtualWorld(playerid));
                
    SetPVarInt(playerid,"GetPLInterior",GetPlayerInterior(playerid));
                
    //Получаем виртуальный мир игрока за которым следим и устанавливаем такой-же игроку который следит, аналогично с интерьером 
                
    SetPlayerVirtualWorld(playerid,GetPlayerVirtualWorld(player_id)); 
                
    SetPlayerInterior(playerid,GetPlayerInterior(player_id));
                
    // Получаем виртуальный мир и интерьер в котором находится админ
                
                //Сейчас мы установим значение нашей переменной следящему игроку. 
                
    spectating[playerid] = player_id
                
    //Теперь, переведем следящего в режим наблюдения за игроком 
                
    TogglePlayerSpectating(playerid1); 

                
    //Разберёмся, находидтся ли игрок за которым следим в машине или нет. Установим соответствующий тип слежки. 
                
    if(IsPlayerInAnyVehicle(player_id)) PlayerSpectateVehicle(playeridGetPlayerVehicleID(player_id), SPECTATE_MODE_NORMAL); 
                else 
    PlayerSpectatePlayer(playeridplayer_idSPECTATE_MODE_NORMAL); 
            } 
            else return 
    SendClientMessage(playerid, -1"Игрок не найден!"); 
            return 
    1
        } 
    PHP код:
    if(strcmp(cmd"/offspec"true) == 0
        { 
            if(
    IsPlayerConnected(playerid)) 
            { 
                
    //Устанавливаем следящему сохраненный виртуальный мир, аналогично с интерьером 
                
    SetPlayerVirtualWorld(playerid,GetPVarInt(playerid,"GetPLVirtualWorld")); 
                
    SetPlayerInterior(playerid,GetPVarInt(playerid,"GetPLInterior")); 
                
    //Очищаем переменную 
                
    spectating[playerid] = -1
                
    //Отключаем режим наблюдения у следящего 
                
    TogglePlayerSpectating(playerid1); 
            } 
            return 
    1
        } 
    Последний раз редактировалось wAx; 09.03.2015 в 18:07.

  7. #7
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±
    Цитата Сообщение от NewGreen Посмотреть сообщение
    Эту команду нужно доработать т.к. когда админ будет включать слежение за игроком находясь в интерьере/др. вирт. мире, то отключая слежение он будет проваливаться. Можно использовать дополнительные переменные или PVar
    PHP код:
    if(strcmp(cmd"/offspec"true) == 0
        { 
            if(
    IsPlayerConnected(playerid)) 
            { 
                
    //Устанавливаем следящему виртуальный мир, который используется при spawn, аналогично с интерьером 
                
    SetPlayerVirtualWorld(playerid,0); 
                
    SetPlayerInterior(playerid,0); 
                
    //Очищаем переменную 
                
    spectating[playerid] = -1
                
    //Отключаем режим наблюдения у следящего 
                
    TogglePlayerSpectating(playerid1); 
            } 
            return 
    1
        } 
    Вариант решения с использованием PVar:

    PHP код:
    if(strcmp(cmd"/spectate")) 
        { 
            new 
    player_id
            if(
    sscanf(params"d"player_id)) return SendClientMessage(playerid0xFFFFFF"/spectate [ID]"); 
            if(
    IsPlayerConnected(player_id)) 
            { 
                
    //Получаем виртуальный мир игрока за которым следим и устанавливаем такой-же игроку который следит, аналогично с интерьером 
                
    SetPlayerVirtualWorld(playerid,GetPlayerVirtualWorld(player_id)); 
                
    SetPlayerInterior(playerid,GetPlayerInterior(player_id));
                
    // Получаем виртуальный мир и интерьер в котором находится админ
                
    SetPVarInt(playerid,"GetPLVirtualWorld",GetPlayerVirtualWorld(playerid));
                
    SetPVarInt(playerid,"GetPLInterior",GetPlayerInterior(playerid));
                
    //Сейчас мы установим значение нашей переменной следящему игроку. 
                
    spectating[playerid] = player_id
                
    //Теперь, переведем следящего в режим наблюдения за игроком 
                
    TogglePlayerSpectating(playerid1); 

                
    //Разберёмся, находидтся ли игрок за которым следим в машине или нет. Установим соответствующий тип слежки. 
                
    if(IsPlayerInAnyVehicle(player_id)) PlayerSpectateVehicle(playeridGetPlayerVehicleID(player_id), SPECTATE_MODE_NORMAL); 
                else 
    PlayerSpectatePlayer(playeridplayer_idSPECTATE_MODE_NORMAL); 
            } 
            else return 
    SendClientMessage(playerid, -1"Игрок не найден!"); 
            return 
    1
        } 
    PHP код:
    if(strcmp(cmd"/offspec"true) == 0
        { 
            if(
    IsPlayerConnected(playerid)) 
            { 
                
    //Устанавливаем следящему сохраненный виртуальный мир, аналогично с интерьером 
                
    SetPlayerVirtualWorld(playerid,GetPVarInt(playerid,"GetPLVirtualWorld")); 
                
    SetPlayerInterior(playerid,GetPVarInt(playerid,"GetPLInterior")); 
                
    //Очищаем переменную 
                
    spectating[playerid] = -1
                
    //Отключаем режим наблюдения у следящего 
                
    TogglePlayerSpectating(playerid1); 
            } 
            return 
    1
        } 
    Не нужно ничего доделывать. Игрок после выхода из слежки, отправляется на spawn.

  8. #8
    Аватар для Scot
    Пользователь

    Статус
    Оффлайн
    Регистрация
    27.04.2014
    Сообщений
    5
    Репутация:
    0 ±

  9. #9
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±
    Не буду лгать что идея возникла в моей голове внезапно. Я всего-лишь наткнулся на заморский топик, после чего решил перенести это в наше комьюнити.
    Читаем внимательнее и замечаем перевод и дополнения. Заметили? Будут еще претензии?

  10. #10
    Аватар для Pe4en9
    Пользователь

    Статус
    Оффлайн
    Регистрация
    16.08.2014
    Сообщений
    35
    Репутация:
    1 ±
    Цитата Сообщение от wAx Посмотреть сообщение
    Читаем внимательнее и замечаем перевод и дополнения. Заметили? Будут еще претензии?
    косяк ищи, боты следят друг за другом и ресуются по коордам других ботов, потом резко к себе и так по циклу.
    ищи дырку.

 

 
Страница 1 из 7 1 2 3 ... ПоследняяПоследняя

Информация о теме

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

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •