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

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

    PrivateArea.inc - создание приватных зон

    PrivateArea.inc

    PrivateArea.inc - это библиотека, которая позволяет создавать приватные зоны на сервере в SA:MP.

    Как это работает: Когда игрок пытается зайти в приватную зону, его откидывает обратно.

    Ограничения:
    • Для работы с данной библиотекой необходимо иметь streamer и foreach.
    • Создавать можно только зоны с типом Sphere (сфера).

    Константы:
    • MAX_PRIVATE_AREA - Максимальное количество созданных приватных зон (по умолчанию 50);
    • PRIVATE_AREA_NONE - Приватной зоны не существует;
    • PRIVATE_AREA_FULL_LIMIT - Превышен лимит создания приватных зон.

    Функции:
    1. public OnPlayerTriedEnterPrivateArea(playerid, areaid);
    2. CreatePrivateArea(Float:x, Float:y, Float:z, Float:size, worldid = -1, interiorid = -1, playerid = -1, priority = 0);
    3. DestroyPrivateArea(areaid);
    4. DenyEntryToPrivateArea(areaid, playerid = -1);
    5. AllowEntryToPrivateArea(areaid, playerid = -1);
    6. IsPlayerAddInPrivateArea(playerid, areaid);


    Описание функций:
    • OnPlayerTriedEnterPrivateArea - Автовызываемая функция, которая вызывается когда игрок пытается войти в приватную зону.

      Параметры:
      • playerid - ID игрока;
      • areaid - ID динамической зоны.

    • CreatePrivateArea - Создает приватную зону на сервере.

      Возвращаемые значения:
      • ID динамической зоны в случае успеха;
      • PRIVATE_AREA_FULL_LIMIT - если превышен лимит создания приватных зон.

      Параметры:
      • x, y, z - координаты зоны;
      • size - размер зоны;
      • worldid - виртуальный мир (по умолчанию -1);
      • interiorid - интерьер (по умолчанию -1);
      • playerid - укажите Id игрока, если необходимо создать зону только для него (по умолчанию -1);
      • priority - установить приоритет загрузки зоны (по умолчанию 0).

    • DestroyPrivateArea - Уничтожает приватную зону с сервера.

      Возвращаемые значения:
      • 1 - если приватная зона была успешно удалена;
      • PRIVATE_AREA_NONE - если приватной зоны не существует.

      Параметры:
      • areaid - ID динамической зоны;

    • DenyEntryToPrivateArea - Запрещает игроку входить в приватную зону.

      Возвращаемые значения:
      • 1 - в случае успеха;
      • 0 - если ID игрока меньше 0 или больше MAX_PLAYERS-1;
      • PRIVATE_AREA_NONE - если приватной зоны не существует.

      Параметры:
      • areaid - ID динамической зоны;
      • playerid - ID игрока которому нужно запретить вход (по умолчанию -1 (запрещает входим всем)).

    • AllowEntryToPrivateArea - Разрешает игроку входить в приватную зону.

      Возвращаемые значения:
      • 1 - в случае успеха;
      • 0 - если ID игрока меньше 0 или больше MAX_PLAYERS-1;
      • PRIVATE_AREA_NONE - если приватной зоны не существует.

      Параметры:
      • areaid - ID динамической зоны;
      • playerid - ID игрока которому нужно разрешить вход (по умолчанию -1 (разрешает входим всем)).

    • IsPlayerAddInPrivateArea - Проверяет добавлен ли игрок в приватную зону.

      Возвращаемые значения:
      • 1 - если игрок добавлен в приватную зону;
      • 0 - если ID игрока меньше 0 или больше MAX_PLAYERS-1, либо игрок не добавлен в приватную зону;
      • PRIVATE_AREA_NONE - если приватной зоны не существует.

      Параметры:
      • playerid - ID игрока;
      • areaid - ID динамической зоны.


    Пример использования:
    1. new PrivateArea;
    2. public OnGameModeInit() {
    3.  
    4. PrivateArea = CreatePrivateArea(0.0, 0.0, 0.0, 100.0);
    5. DenyEntryToPrivateArea(PrivateArea);
    6. return 1;
    7. }
    8. public OnPlayerTriedEnterPrivateArea(playerid, areaid) {
    9.  
    10. if(areaid == PrivateArea)
    11. SendClientMessage(playerid, -1, !"Запретная территория. Вход запрещен!");
    12. return 1;
    13. }




     Лог изменений

    Код:
    Version 1.1 (17.11.2020):
        - Добавлена функция IsPlayerAddInPrivateArea(playerid, areaid);
    
    Version 1.2 (17.11.2020):
        - Исправлена ошибка при записи координат, когда игрок находится в автомобиле;

    Автор статьи и библиотеки: punkochel
    Скачать Include : GitHub
    *Примечание: Данная версия инклуда содержит в себе функции, логика работы которых будет пересмотрена в ближайшее время. Вы можете его использовать, но выход новых версий возможно заставит вас изменить некоторые параметры.

    *Исключительно для pro-pawn.ru
    Копирование данной статьи на других ресурсах без разрешения автора или Daniel_Cortez запрещено!
    Последний раз редактировалось punkochel; 19.11.2020 в 00:21.

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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Во-первых, у тебя функция DenyEntryToPrivateArea не будет работать корректно при указании "-1", ибо ты используешь foreach, который добавит только игроков, которые есть на сервере (соответственно, твой код из примера не добавит вообще никого из игроков в список запрещённых). Вполне возможно, что есть ещё какие-то недочёты. Буквально мельком глянул код.

    Во-вторых, почему не создал итератор для своих зон?

    В-третьих, алгоритм не очень надёжный. Упади игрок прямиком внутрь динамической зоны и он либо словит рекурсию, постоянно откидываясь в воздух и падая (а вместе с ним и сервер), либо просто упадёт и сможет спокойно бегать по зоне. Надёжнее сделать реализацию по типу нативной SetPlayerWorldBounds, только на стороне сервера - то бишь, определять ближайшую к игроку точку, которая находится за зоной, и телепортировать на неё.

    Ну и не проще ли было бы в CreatePrivateArea возвращать не ID динамической зоны, а индекс массива? Тогда можно будет избавиться большинства циклов с перебором всех твоих приватных зон только ради того, чтоб найти нужную динамическую зону. У тебя всё равно нигде нет нужды давать пользователю возможность обращаться именно к динамической зоне, а не к твоему массиву.

    UPD: Так же тебе стоит как-то контролировать момент с указанием конкретного ID игрока в CreatePrivateArea, дабы нельзя было потом в DenyEntryToPrivateArea/AllowEntryToPrivateArea манипулировать приватной зоной для тех игроков, для которых не создаётся динамическая зона. Лучше всего будет просто избавиться от массива "BannedPlayerId" и перенести функционал разрешения/запрета на параметр "playerid" динамической зоны, используя функции стримера Streamer_AppendArrayData/Streamer_RemoveArrayData. Это и решит упомянутую проблему, и сделает код более оптимизированным, ибо у тебя и память освободиться, и, в целом, код не будет срабатывать для тех игроков, для кого не включен запрет.
    Последний раз редактировалось DeimoS; 18.11.2020 в 03:04.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

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

    Steve Pavlina

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

    Статус
    Оффлайн
    Регистрация
    08.12.2018
    Адрес
    Россия
    Сообщений
    146
    Репутация:
    25 ±
    Спасибо за идеи, обязательно в скором времени выпущу релиз.

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

    Статус
    Оффлайн
    Регистрация
    23.12.2016
    Адрес
    Казахстан
    Сообщений
    148
    Репутация:
    26 ±
    На мой скромный взгляд лучше давать возможность создавать динамические зоны самим, а после уже можно запрещать в них заходить.
    1. PrivateArea = CreateDynamicSphere(0.0, 0.0, 0.0, 100.0);
    2. DenyEntryToPrivateArea(PrivateArea);


    А координаты узнавать через направление от центра до ближайшей точки доступной игроку./
    PHP код:
    static Float:axFloat:ayFloat:az;
        if(
    GetPlayerPos(playeridaxayaz))
        {
            static
                
    Float:xFloat:yFloat:z,
                
    Float:angle,
                
    Float:size;

            
    Streamer_GetItemPos(STREAMER_TYPE_AREAareaidxyz);
            
    angle atan2(y-ayx-ax) + 90.00// - Вычисляем угол поворота обратный от центра зоны

            
    Streamer_GetFloatData(STREAMER_TYPE_AREASTREAMER_TYPE_AREAE_STREAMER_SIZEsize);

            
    // - Вычисляем координаты за границы зоны(может правильнее size / 2) не проверял

            
    ax += ((size 15.0) * floatsin(-angledegrees));
            
    ay += ((size 15.0) * floatcos(-angledegrees));

            
    SetPlayerPos(playeridaxayaz);
        } 
    Ну или сохранять позицию игрока всегда.
    Последний раз редактировалось Seviel; 19.11.2020 в 12:50.

  6. Пользователь сказал cпасибо:
    punkochel (19.11.2020)
 

 

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

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

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

Ваши права

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