Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 6 из 6
  1. #1
    Аватар для Skipter
    Пользователь

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

    Как сделать переключение игроков при слежке?

    Доброго времени суток.

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

    Тестирую с другом. Захожу за ним в наблюдение - все ок. Нажимаю NEXT и по логике должно остаться на этом же ID'e, ибо игрок с id 2 не онлайн, а получается либо выход за пределы массива, либо прочая фигня.

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

    1. case 0: // next
    2. {
    3. new
    4. current_id, i;
    5.  
    6. i = Iter_First(Player);
    7. while(i != Iter_End(Player)) {
    8.  
    9. current_id = Iter_Next(Player, i);
    10.  
    11. if(i == playerid || !IsPlayerLogin(i))
    12. continue;
    13.  
    14. StartSpec(playerid, i);
    15.  
    16. i = current_id;
    17.  
    18. break;
    19. }
    20. }


    Либо так:

    1. new
    2. current_id;
    3.  
    4. foreach(new i: Player) {
    5.  
    6. current_id = Iter_Next(Player, i);
    7. if(current_id == playerid || !IsPlayerLogin(current_id))
    8. continue;
    9.  
    10. StartSpec(playerid, current_id);
    11.  
    12. break;
    13. }


    И многое другое... Ничего не хочет работать. Подскажите, пожалуйста, где ошибка.

  2. #2
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Смотри:
    При вызове Iter_Next, когда передаётся самое последнее доступное значение, функция возвращает значение Iter_End.
    При вызове Iter_Prev, когда передаётся самое первое значение из доступных в итераторе, функция возвращает значение Iter_Begin (по сути, тот же Iter_End с тем же кодом, только название изменено, дабы было более говорящим для конкретной ситуации).

    Соответственно, тебе нужно написать следующую логику:

    1) Iter_Next
    2) Iter_Next == Iter_End?
    2.1) Если да, вызываем Iter_First (чтоб начать "новый круг")
    2.1.1) Если функция Iter_First так же возвращает значение Iter_End, значит подходящих игроков больше нет
    2.2) Если нет, то проверяем совпадение с playerid/другими следящими админами/прочей нужной инфой (в случае совпадения опять вызывать Iter_Next, только уже для значения, которое до этого вернула Iter_Next. Ну а если совпадений нет, то используем значение Iter_Next)

    И в Iter_Next передавай не значение из foreach, а текущий ID игрока, за которым идёт слежка. Iter_Next/Iter_Prev созданы именно для определения следующего/предыдущего значения от текущего (указанного).


    С Iter_Prev всё точно так же:
    1) Iter_Prev
    2) Iter_Prev == Iter_Begin?
    2.1) Если да, вызываем Iter_Last (чтоб начать "новый круг")
    2.1.1) Если функция Iter_Last так же возвращает значение Iter_Begin, значит подходящих игроков больше нет
    2.2) Если нет, то проверяем совпадение с playerid/другими следящими админами/прочей нужной инфой (в случае совпадения опять вызывать Iter_Prev, только уже для значения, которое до этого вернула Iter_Prev. Ну а если совпадений нет, то используем значение Iter_Prev)

    И точно так же никакого цикла foreach быть не должно. Внутри функций хранятся все нужные циклы и вычисления. Тебе нужно только сверять значения и использовать их.

    Для проверок на совпадение с playerid и т.п. можно использовать goto, а не цикл (если, конечно, умеешь пользоваться). Код будет в разы компактнее и понятнее (ну с моей точки зрения).
    goto тут лучше, ибо количество итераций, нужных для проверки, заранее неизвестно, и с циклом, скорее всего, придётся воротить дополнительные условия, раздувая код. А с goto у тебя будет тот же самый "голый" алгоритм + 2 строки с goto для зацикливания.
    Последний раз редактировалось DeimoS; 05.03.2019 в 02:15.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  3. Пользователь сказал cпасибо:
    Skipter (05.03.2019)
  4. #3
    Аватар для Skipter
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.10.2016
    Сообщений
    41
    Репутация:
    0 ±
    Спасибо за хорошее пояснения, но верно ли я понял?

    1. case 0: // next
    2. {
    3. new
    4. curr_next = Iter_Next(Player, GetSpecID(playerid)),
    5. curr_end = Iter_End(Player),
    6. next_id, i;
    7.  
    8. if(curr_next) {
    9. if(curr_next == curr_end) {
    10.  
    11. i = Iter_First(Player);
    12. if(i == curr_end) {
    13. return true;
    14. }
    15.  
    16. else if(!pTemp[i][pLogined] || i == playerid) {
    17. next_id = Iter_Next(Player, curr_next);
    18. } else {
    19. next_id = curr_next;
    20. }
    21. }
    22. }
    23. StartSpec(playerid, next_id);
    24. }


    UPD: Кхм, не работает. Нажимаю на next, а он меня спавнит, хотя в паблик StartSpec передаются правильные значения.
    Последний раз редактировалось Skipter; 05.03.2019 в 23:01.

  5. #4
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Странноватый код. Если условие "curr_next == curr_end" не сработает, next_id останется с нулевым значением.

    Как-то так:
    1. case 0: // next
    2. {
    3. new
    4. curr_next,
    5. curr_end = Iter_End(Player),
    6. start_id;
    7.  
    8. start_id = curr_next = GetSpecID(playerid);
    9.  
    10. __loop:
    11. curr_next = Iter_Next(Player, curr_next);
    12. if(curr_next == curr_end)
    13. {
    14. curr_next = Iter_First(Player);
    15. if(curr_next == curr_end)
    16. {
    17. // Тут нужна функция, которая завершает слежку
    18. return true;
    19. }
    20. }
    21.  
    22. if(start_id != curr_next && (curr_next == playerid || !pTemp[curr_next][pLogined]))
    23. {
    24. goto __loop;
    25. }
    26. StartSpec(playerid, curr_next);
    27. }


    Нужно проверить код на ситуациях, когда:
    1) Есть только один залогиненный игрок, помимо тебя, а так же есть ещё один или несколько незалогиненных игроков (в этом случае должно вновь показать залогиненного игрока, а не уйти в бесконечный цикл)
    2) Если на сервере только один игрок, помимо тебя.

    Если всё сработает как надо, то код на обратную прокрутку будет точно таким же, только вместо Iter_Next будет Iter_Prev, а вместо Iter_First будет Iter_Last (Iter_End можно и не менять, ибо, как говорил, значение Iter_End и Iter_Begin выдают одинаковое)
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  6. Пользователь сказал cпасибо:
    Skipter (05.03.2019)
  7. #5
    Аватар для Skipter
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.10.2016
    Сообщений
    41
    Репутация:
    0 ±
    Работает отлично, позже проверю остальное, но я думаю ситуация не изменится.

    Большое спасибо!

  8. #6
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Если будут проблемы - в личку отпиши и открою тему.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

 

 

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

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

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

Ваши права

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