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

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±

    Дополнительные функции стримера / Другие функции [Часть 3]

    Первая часть: перейти.
    Вторая часть: перейти.


    Дисклеймер

    Эта статья исключительно для тех, кто заинтересован в более глубоком изучении дополнительного функционала стримера, и не рекомендуется к прочтению, если вы используете его только для того, чтобы ставить через него свой маппинг на сервер и дальше этого он вам не нужен. Актуально для последних версий стримера (2.8.2 - 2.9.4).

    Предисловие

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

    Речь в этом уроке пойдёт о "других", "разнообразных" дополнительных функциях стримера, которые не попадают в какие-то определённые группы функций, как например функции настройки или манипуляции данными. Тем не менее в этой категории "остального" есть очень интересный и полезный функционал, который при хорошей интеграции со стримером мог бы пригодиться внутри основного мода для реализации даже каких-то базовых систем. К примеру, здесь будут разобраны удобные функции для узнавания позиции любого созданного стримером элемента (причём в отличие от ранее разобранных функций вроде Streamer_GetFloatData, здесь мы сможем узнать позицию X, Y и Z всего одним нативом, вместо того, чтобы вызывать ту функцию три раза отдельно для каждой оси), функции для узнавания дистанции от произвольных координат до нужного стримерского элемента (опять же, с помощью всего лишь одного натива), а также функции, позволяющие узнать, в стриме ли нужный нам элемент у конкретного игрока (т.е. видит ли его игрок в данный момент) и даже функции, которые разом могут удалять все созданные стримером элементы одного типа (и снова одним нативом, никаких циклов).

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

    Другие функции
    Streamer_GetDistanceToItem, Streamer_(Get/Set)ItemPos и другие

    По традиции, знакомство с функциями будет начинаться с практического примера, в котором они нам понадобятся.

    Давайте представим сейчас самую банальную задачу: нам просто нужно узнать дистанцию между игроком и объектом банкомата. Живи бы мы в 2011-ом, мы бы конечно же начали проверять дистанцию от позиции игрока до вручную заданных координат банкомата, которые совпадают с теми, на которых создан его объект. А живи мы в 2014-ом, мы бы уже узнавали позицию стримерского объекта через GetDynamicObjectPos, а потом бы проверяли дистанцию до позиции игрока. Но сейчас нам нужно сделать это ещё более красиво, эффективно и просто, и в данном случае нам на помощь приходит...

    • Streamer_GetDistanceToItem
      Эта функция узнаёт расстояние от указанных координат до нужного стримерского элемента.

      PHP код:
      Streamer_GetDistanceToItem(Float:xFloat:yFloat:ztypeid, &Float:distancedimensions 3
      Параметры:
      x: Координата X, от которой будет считаться расстояние до элемента.
      y: Координата Y, от которой будет считаться расстояние до элемента.
      z: Координата Z, от которой будет считаться расстояние до элемента.
      type: Тип элемента.
      id: ID элемента.
      distance: Переменная, в которую запишется дистанция.
      dimensions: Количество измерений, которые будут использоваться при расчёте расстояния (2 или 3).

      Возвращает:
      1 при успешном выполнении, 0 при неудаче (дистанция передаётся в вами указанную переменную distance в аргументах функции).

      Примечание:
      Количество измерений в параметре dimensions означает, будет ли считаться расстояние только по X и Y координатам без учёта Z (т.е. это будет 2 измерения), или в расчёт будут браться все 3: X, Y и Z.

      Использование:
      PHP код:
      stock Float:GetDistBetweenPlayerAndDynObj(playeridobjectid)
      {
          
      //Создаём переменные для получения и хранения позиции игрока
          
      new Float:xFloat:yFloat:z;

          
      //Узнаём позицию игрока
          
      GetPlayerPos(playeridxyz);

          
      //Создаём переменную, куда запишется дистанция
          
      new Float:dist;

          
      //В первый аргумент передали x координату - x
          //Во второй аргумент y координату - y
          //В третий аргумент z координату - z
          //В четвёртый аргумент передали тип элемента - STREAMER_TYPE_OBJECT
          //В пятый аргумент сам ID элемента - objectid
          //В шестой аргумент передали переменную, в которую запишется полученная дистанция - dist
          //По итогу: узнаём и возвращаем дистанцию между стримерским объектом и игроком
          
      Streamer_GetDistanceToItem(xyzSTREAMER_TYPE_OBJECTobjectiddist); //Мы не указали аргумент dimensions, соответственно по умолчанию в него подставится значение 3 (расстояние будет считаться по x, y и z)

          
      return dist//Вернём дистанцию из функции



    Ок, одной проблемой меньше. Теперь давайте представим, что нам нужно иногда скрывать какой-то элемент стримера, будь то объект, 3d-текст, map иконку или что бы то ни было ещё (но за пример возьмём 3d-текст). У нас есть довольно очевидный план действий: мы можем его удалять в нужный момент, а потом просто пересоздавать. Но стример позволяет делать это удобнее, а именно скрывать нужный нам 3d-текст (и не только 3d-текст) для конкретного игрока без его пересоздания нами вручную. При этом даже после того, как он локально удалится у нашего игрока, у других он всё также останется, как и останется в памяти стримера (а соответственно мы сможем и дальше узнавать его позицию и иные данные), и при этом в любой момент всё той же нехитрой функцией его можно будет вернуть в поле зрения ранее выбранного игрока. Речь идёт о функции Streamer_ToggleItem.

    • Streamer_ToggleItem
      Эта функция скрывает/показывает стримерский элемент для указанного игрока.

      PHP код:
      Streamer_ToggleItem(playeridtypeidtoggle
      Параметры:
      playerid: ID игрока, для которого нужно показать/скрыть элемент.
      type: Тип элемента.
      id: ID элемента.
      toggle: 0 для скрытия элемента, 1 для показа.

      Возвращает:
      1 при успешном выполнении, 0 при неудаче.

      Важное примечание:
      Поскольку стример работает на основе имеющихся в сампе функций по умолчанию, он взаимодействует и обрабатывает такие элементы, как пикапы и актёров через "глобальные" нативы (которые показывают и удаляют их для всех игроков одновременно, не имея аналогов "ForPlayer"). Так, стример не может удалить (скрыть) актёра или пикап для конкретного игрока, если этого актёра или пикап в это время видят другие. И поэтому, применяя Streamer_ToggleItem, она возымеет эффект (т.е. успешно скроет) актёра или пикап только в том случае, если его в это время видит лишь один игрок. Остальные типы элементов имеют возможность создаваться и удаляться для отдельных игроков, потому проблем с ними и с этой функцией уже нет.

      Использование:
      PHP код:
      public OnPlayerGiveDamageDynamicActor(playeridactoridFloat:amountweaponidbodypart)
      {
          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элемента - STREAMER_TYPE_3D_TEXT_LABEL
          //В третий аргумент ID элемента - QuestLabel01 (предположим, что это переменная, которая хранит ID ранее созданного 3d-текста)
          //В четвёртый аргумент передали "состояние скрытия" - 0
          //По итогу: скрываем 3d-текст для указанного игрока
          
      Streamer_ToggleItem(playeridSTREAMER_TYPE_3D_TEXT_LABELQuestLabel010);
          return 
      1;



    А для проверки, скрыт или показан элемент (наш 3d-текст) конкретному игроку, нам тоже нужна отдельная функция. И вот она:

    • Streamer_IsToggleItem
      Эта функция узнаёт, включен ли Streamer_ToggleItem для указанного игрока и стримерского элемента.

      PHP код:
      Streamer_IsToggleItem(playeridtypeid
      Параметры:
      playerid: ID игрока, для которого нужно узнать, показан для него элемент или скрыт.
      type: Тип элемента.
      id: ID элемента.

      Возвращает:
      1, если элемент показан и 0, если скрыт.

      Использование:
      PHP код:
      public OnPlayerEnterDynamicRaceCP(playeridcheckpointid)
      {
          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элемента - STREAMER_TYPE_3D_TEXT_LABEL
          //В третий аргумент ID элемента - QuestLabel01 (предположим, что это переменная, которая хранит ID ранее созданного 3d-текста)
          //По итогу: выводим игроку некое сообщение, при условии, что для него не скрыт нужный 3d-текст
          
      if(Streamer_IsToggleItem(playeridSTREAMER_TYPE_3D_TEXT_LABELQuestLabel01)) SendClientMessage(playerid, -1"Механик: Припаркуй свою машину у гаража");
          return 
      1;



    Хорошо, скажете вы. А как насчёт скрытия/показа сразу всех элементов определённого типа (все 3d-тексты разом, например)? А вот, оказывается, даже на такой случай есть одна удобная функция - Streamer_ToggleAllItems.

    • Streamer_ToggleAllItems
      Эта функция скрывает/показывает все стримерские элементы указанного типа для указанного игрока.

      PHP код:
      Streamer_ToggleAllItems(playeridtypetoggleexceptions[] = { -}, maxexceptions sizeof exceptions
      Параметры:
      playerid: ID игрока, для которого нужно показать/скрыть все элементы.
      type: Тип элементов.
      toggle: 0 для скрытия элементов, 1 для показа.
      exceptions[]: ID'ы элементов для исключения (скроются/покажутся все, кроме них).
      maxexceptions: Размер массива с исключениями (размер "exceptions" по умолчанию).

      Возвращает:
      1 при успешном выполнении, 0 при неудаче.

      Использование:
      PHP код:
      public OnPlayerEnterDynamicCP(playeridcheckpointid)
      {
          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элементов - STREAMER_TYPE_3D_TEXT_LABEL
          //В третий аргумент передали "состояние скрытия" - 0
          //По итогу: скрываем все стримерские 3d-тексты для указанного игрока
          
      Streamer_ToggleAllItems(playeridSTREAMER_TYPE_3D_TEXT_LABEL0); //Поскольку мы не указали 4 и 5 аргумент, то исключений нет
          
      return 1;
      }

      public 
      OnPlayerLeaveDynamicCP(playeridcheckpointid)
      {
          
      //Создадим массив с ID'ами 3d-текстов для исключения
          
      new QuestLabels[] = {123};

          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элементов - STREAMER_TYPE_3D_TEXT_LABEL
          //В третий аргумент передали "состояние скрытия" - 1
          //В четвёртый аргумент передали массив с перечислением исключений - QuestLabels
          //В пятый аргумент размер этого массива с исключениями - sizeof QuestLabels
          //По итогу: показываем все стримерские 3d-тексты (кроме 1, 2 и 3 ID'а, которые и указаны в массиве QuestLabels) для указанного игрока
          
      Streamer_ToggleAllItems(playeridSTREAMER_TYPE_3D_TEXT_LABEL1QuestLabelssizeof QuestLabels);

          return 
      1;



    Отлично, с возможностью скрывать и показывать различные элементы разобрались. Теперь давайте перейдём чуть к более глубоко зарытым вещам. Если вы понимаете, что стримерский ID любого элемента сам по себе довольно условный и он отличается от ID'а фактически созданного стримером элемента, с которым он взаимодействует, то вы наверняка могли задумываться, как же различать и преобразовывать, например, стримерский ID пикапа в реальный ID, созданный в данный момент перед игроком или наоборот, брать какой-либо реально созданный ID пикапа и узнавать из него стримерский ID, ну или хотя бы проверять, не используется ли этот реально созданный пикап под нужды стримера в принципе. И на такой случай стример имеет две крайне полезные функции: Streamer_GetItemInternalID и Streamer_GetItemStreamerID.

    • Streamer_GetItemInternalID
      Эта функция возвращает внутренний ID элемента (который назначается сервером SA-MP) для указанного игрока на основе указанного типа элемента и стримерского ID'а элемента (который назначается самим стримером).

      PHP код:
      Streamer_GetItemInternalID(playeridtypestreamerid
      Параметры:
      playerid: ID игрока, для которого нужно узнать из стримерского ID'а внутренний.
      type: Тип элемента.
      streamerid: "Стримерский" ID элемента.

      Возвращает:
      "Внутренний" ID элемента (ID фактически созданного элемента на сервере).

      Использование:
      PHP код:
      public OnPlayerPickUpDynamicPickup(playeridpickupid)
      {
          
      //Создадим переменную для записи в неё "внутреннего" ID'а пикапа
          
      new internalid;

          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элемента - STREAMER_TYPE_PICKUP
          //В третий аргумент стримерский ID элемента - pickupid
          
      internalid Streamer_GetItemInternalID(playeridSTREAMER_TYPE_PICKUPpickupid);

          
      //По итогу: узнаём и выводим в консоль внутренний ID пикапа
          
      printf("Стримерский пикап ID %d создан для вас на сервере под фактическим ID'ом %d"pickupidinternalid);
          return 
      1;

    • Streamer_GetItemStreamerID
      Эта функция возвращает стримерский ID элемента (который назначается самим стримером) для указанного игрока на основе указанного типа элемента и внутреннего ID'а элемента (который назначается сервером SA-MP).

      PHP код:
      Streamer_GetItemStreamerID(playeridtypeinternalid
      Параметры:
      playerid: ID игрока, для которого нужно узнать из внутреннего ID'а стримерский.
      type: Тип элемента.
      internalid: "Внутренний" ID элемента (ID фактически созданного элемента на сервере).

      Возвращает:
      "Стримерский" ID элемента.

      Использование:
      PHP код:
      public OnPlayerPickUpPickup(playeridpickupid)
      {
          
      //Создадим переменную для записи в неё стримерского ID'а пикапа
          
      new streamerid;

          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элемента - STREAMER_TYPE_PICKUP
          //В третий аргумент "внутренний" ID элемента - pickupid
          
      streamerid Streamer_GetItemStreamerID(playeridSTREAMER_TYPE_PICKUPpickupid);

          
      //По итогу: узнаём стримерский ID пикапа при подборе обычного
          //И, если стример использует этот пикап (стримерский ID этого пикапа существующий), то сообщаем об этом в консоль
          
      if(IsValidDynamicPickup(streamerid)) printf("Подобранный пикап ID %d является стримерским. Стримерский ID этого пикапа: %d"pickupidstreamerid);
          return 
      1;



    Да, сейчас мы способны даже на такие вот вещи, о которых вы до этого, возможно, и не задумывались. А теперь рассмотрим следующие ситуации и случаи, где нам бы понадобилось уже узнать, находится ли любой элемент стримера в стриме у нужного нам игрока (то есть видит ли нужный игрок в данный момент какой-либо из стримерских элементов). Ведь, как мы знаем, в сампе "обычным" элементам это доступно только для транспорта (IsVehicleStreamedIn), актёров (IsActorStreamedIn), да и самих игроков (IsPlayerStreamedIn). А здесь мы сможем узнавать подобное вообще для всего, что создано через стример, и в этом нам поможет следующая функция чуть ниже.

    • Streamer_IsItemVisible
      Эта функция узнаёт, находится ли элемент в данный момент в стриме для указанного игрока.

      PHP код:
      Streamer_IsItemVisible(playeridtypeid
      Параметры:
      playerid: ID игрока, для которого нужно узнать, виден ли ему указанный стримерский элемент.
      type: Тип элемента.
      id: ID элемента.

      Возвращает:
      1, если элемент находится в стриме и 0, если нет.

      Примечание:
      То, что игрок его "видит" здесь подразумевается в том смысле, что элемент находится на неком достаточно близком к игроку расстоянии, при котором стример начинает создавать и показывать этот элемент для игрока (это и есть, что называется, "в стриме"). Если вы хотели бы точно знать, когда игрок его видит на самом мониторе, а когда он скрыт за каким-либо другим объектом и не виден фактически, то это уже совсем другое и данная функция вам в этом не поможет.

      Использование:
      PHP код:
      public OnPlayerExitVehicle(playeridvehicleid)
      {
          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элемента - STREAMER_TYPE_MAP_ICON
          //В третий аргумент ID элемента - DumpMapIcon (предположим, что это переменная, которая хранит ID ранее созданной map иконки)
          //По итогу: выводим игроку некое сообщение, при условии, что map иконка для него вне зоны стрима
          
      if(!Streamer_IsItemVisible(playeridSTREAMER_TYPE_MAP_ICONDumpMapIcon)) SendClientMessage(playerid, -1"Вы слишком далеко от свалки, вернитесь в автомобиль");
          return 
      1;



    Узнавать, в стриме ли определённый элемент, это, конечно же, неплохо. Но что, если я скажу вам, что можно узнавать ещё и общее количество всех элементов определённого типа, которые видит нужный нам игрок в данный момент? "Да это же просто чудесно!" - наверное, ответите мне вы, и правильно сделаете, потому дальше мы разбираем именно такую функцию.

    • Streamer_CountVisibleItems
      Эта функция узнаёт количество элементов определённого типа, которые в данный момент находятся в стриме у указанного игрока.

      PHP код:
      Streamer_CountVisibleItems(playeridtypeserverwide 1
      Параметры:
      playerid: ID игрока, для которого нужно узнать количество видимых ему стримерских элементов.
      type: Тип элементов, для которого будет возвращено их количество, видимое игроку.
      serverwide: Откуда будет считаться общее количество видимых игроку элементов (0 - количество всех элементов в стриме, которые созданы в текущем скрипте, 1 - количество видимых игроку элементов, которые были созданы во всех скриптах).

      Возвращает:
      Количество элементов в стриме.

      Использование:
      PHP код:
      stock CountVisibleDynamicObjects(playerid)
      {
          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элементов - STREAMER_TYPE_OBJECT
          //По итогу: узнаём и возвращаем общее количество стримерских объектов в стриме для игрока
          
      return Streamer_CountVisibleItems(playeridSTREAMER_TYPE_OBJECT); //Третий аргумент serverwide передан не был, потому он примет своё значение по умолчанию, т.е. 1
          //(количество видимых игроку объектов, созданных во всех фильтрскриптах/моде, а не только в текущем скрипте)



    Такс, а теперь представим себе ситуацию, когда нам нужно узнать не просто количество элементов в стриме для игрока, а буквально ID'ы каждого из всех этих видимых элементов нужного нам типа. А ещё представим, что в этой ситуации нам помимо всего прочего нужно получить эти ID'ы в отсортированном порядке, в зависимости от того, насколько они далеко от игрока (не сортируя их самим). Вы, конечно, уже начинаете думать, что всё это невозможно и вообще я тут какие-то сказки рассказываю. А вот и нет! Следуем дальше, на очереди Streamer_GetAllVisibleItems.

    • Streamer_GetAllVisibleItems
      Эта функция получает все элементы, видимые в данный момент игроку, сортируя их по расстоянию и сохраняя результат в переданный массив.

      PHP код:
      Streamer_GetAllVisibleItems(playeridtypeitems[], maxitems sizeof items
      Параметры:
      playerid: ID игрока, для которого необходимо получить видимые ему стримерские элементы.
      type: Тип элементов для получения.
      items: Массив, в который будут переданы все найденные элементы в стриме.
      maxitems: Размер массива с хранимыми элементами (по умолчанию размер массива из аргумента items).

      Возвращает:
      Количество элементов в стриме (не ограничивается размером переданного массива, т.е. аргументом maxitems).

      Примечания:
      • Чтобы получить текущий видимый чекпоинт или гоночный чекпоинт, используйте GetPlayerVisibleDynamicCP или GetPlayerVisibleDynamicRaceCP.
      • Чтобы получить динамическую(ие) зону(ы), в которой(ых) в данный момент находится игрок, используйте GetPlayerDynamicAreas.


      Использование:
      PHP код:
      public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
      {
          
      //Если игрок нажал клавишу C в состоянии пешком
          
      if((newkeys KEY_CROUCH) && GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)
          {
              
      //То создаём массив для записи в него ID'ов ближайших к игроку 5-ти пикапов (которые обязательно должны быть в стриме у этого игрока)
              
      new pickups[5] = {-1, ...}; //и по умолчанию заполняем его значениями -1

              //В первый аргумент передали ID игрока - playerid
              //Во второй аргумент тип элементов - STREAMER_TYPE_PICKUP
              //В третий аргумент сам массив, в который запишутся ID'ы первых 5 найденных в зоне стрима пикапов - pickups
              //По итогу: получаем первые 5 пикапов, которые видит игрок, и записываем их общее количество в зоне стрима в переменную icount
              
      new icount Streamer_GetAllVisibleItems(playeridSTREAMER_TYPE_PICKUPpickups);

              
      //Создаём массив для дальнейшего форматирования текста и его вывода игроку
              
      new string[64];

              
      //Выводим заголовок информационного сообщения игроку
              
      SendClientMessage(playerid, -1"В данный момент у вас в стриме следующие пикапы:");

              
      //Запускаем цикл по всем ячейкам нашего теперь уже заполненного массива
              
      for(new isizeof pickupsi++)
              {
                  
      //Только если пикап существует (ведь в стриме может вообще не оказаться именно 5 пикапов и массив может быть заполнен не до конца)
                  
      if(IsValidDynamicPickup(pickups[i]))
                  {
                      
      //То лишь в этом случае выводим информацию об этом пикапе в чат
                      
      format(stringsizeof string"Пикап id %d"pickups[i]);
                      
      SendClientMessage(playerid, -1string);
                  }
              }

              
      //А здесь выводим финальное сообщение об общем количестве пикапов в стриме у игрока
              //При этом мы уведомим, если в чат выведены не все пикапы, которые есть в стриме
              //(т.е. массив pickups полностью заполнен, но при этом были ещё пикапы, которые в него не вошли)
              
      if(icount sizeof pickups)
              {
                  
      //Если количество пикапов в стриме на деле больше, чем нам удалось показать, то...
                  
      format(stringsizeof string"Показаны первые %d пикапов из %d найденных"sizeof pickupsicount);
              }
              else
              {
                  
      //Иначе, если показаны все пикапы, которые были в зоне стрима
                  
      format(stringsizeof string"Найдено и показано %d пикапов"icount); //icount более надёжный счётчик, чем размер нашего массива sizeof pickups, потому что он может быть не заполнен (к примеру, если пикапов найдётся только 4)
              
      }
              
      SendClientMessage(playerid, -1string); //Выводим в обоих случаях выше отформатированное сообщение
          
      }
          return 
      1;



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

    • Streamer_DestroyAllVisibleItems
      Эта функция удаляет все элементы определённого типа, которые в данный момент находятся в стриме у указанного игрока.

      PHP код:
      Streamer_DestroyAllVisibleItems(playeridtypeserverwide 1
      Параметры:
      playerid: ID игрока, в зоне стрима которого нужно удалить все элементы.
      type: Тип удаляемых элементов.
      serverwide: Какие элементы будут удалены (0 - всех элементы в стриме, которые созданы в текущем скрипте, 1 - видимые игроку элементы, которые были созданы во всех скриптах).

      Возвращает:
      1 при успешном выполнении, 0 при неудаче.

      Использование:
      PHP код:
      stock DestroyAllVisibleDynObjects(playerid)
      {
          
      //В первый аргумент передали ID игрока - playerid
          //Во второй аргумент тип элементов - STREAMER_TYPE_OBJECT
          //По итогу: удаляем все стримерские объекты в стриме у игрока и возвращаем результат выполнения функции
          
      return Streamer_DestroyAllVisibleItems(playeridSTREAMER_TYPE_OBJECT); //Третий аргумент serverwide передан не был, потому он примет своё значение по умолчанию, т.е. 1
          //(удаляются все видимые игроку объекты, созданные во всех фильтрскриптах/моде, а не только в текущем скрипте)



    Чтоб два раза не вставать, разберём заодно и функцию, которая позволяет удалять вообще все созданные элементы определённого типа.

    • Streamer_DestroyAllItems
      Эта функция удаляет все созданные стримерские элементы определённого типа.

      PHP код:
      Streamer_DestroyAllItems(typeserverwide 1
      Параметры:
      type: Тип удаляемых элементов.
      serverwide: Какие элементы будут удалены (0 - всех элементы, которые созданы в текущем скрипте, 1 - элементы, которые были созданы во всех скриптах).

      Возвращает:
      1 при успешном выполнении, 0 при неудаче.

      Использование:
      PHP код:
      //Для примера на этот раз возьмём актёров, а то они единственные обделены этой функцией по умолчанию
      stock DestroyAllDynamicActors()
      {
          
      //В первый аргумент передали тип элементов - STREAMER_TYPE_ACTOR
          //По итогу: удаляем всех стримерских актёров и возвращаем результат выполнения функции
          
      return Streamer_DestroyAllItems(STREAMER_TYPE_ACTOR); //Второй аргумент serverwide передан не был, потому он примет своё значение по умолчанию, т.е. 1
          //(удаляются все актёры, созданные во всех фильтрскриптах/моде, а не только в текущем скрипте)



    Хм, и вроде чего-то ещё всё равно не хватает, так? Мы разобрали Streamer_CountVisibleItems, но при этом забыли про случаи, когда посчитать нам нужно вообще все созданные стримером элементы нужного нам типа, а не только те, которые в данный момент у кого-либо в стриме. Что же, исправляемся.

    • Streamer_CountItems
      Эта функция узнаёт количество всех созданных стримером элементов определённого типа.

      PHP код:
      Streamer_CountItems(typeserverwide 1
      Параметры:
      type: Тип элементов, для которого будет возвращено их количество, которое сейчас создано на сервере.
      serverwide: Откуда будет считаться общее количество созданных элементов (0 - количество всех элементов, которые созданы в текущем скрипте, 1 - количество элементов, которые были созданы во всех скриптах).

      Возвращает:
      Количество созданных элементов.

      Примечание:
      Эта функция отличается от разобранной в первой части функции Streamer_GetUpperBound тем, что Streamer_CountItems возвращает количество созданных элементов, а не самый высокий созданный ID. Таким образом, для циклов эту функцию использовать не следует.

      Использование:
      PHP код:
      stock CountDynamicActors()
      {
          
      //В первый аргумент передали тип элементов - STREAMER_TYPE_ACTOR
          //По итогу: узнаём и возвращаем общее количество созданных стримерских актёров
          
      return Streamer_CountItems(STREAMER_TYPE_ACTOR); //Второй аргумент serverwide передан не был, потому он примет своё значение по умолчанию, т.е. 1
          //(количество стримерских актёров, созданных во всех фильтрскриптах/моде, а не только в текущем скрипте)



    Статья близится к завершению, а на горизонте у нас очень интересная функция, наверное, одна из самых интересных с точки зрения взаимодействия стримера с модом и более эффективного построения на ней своих игровых систем. Речь идёт о функции, которая по своей логике схожа со Streamer_GetAllVisibleItems, однако в отличие от неё позволит вам узнавать ID'ы всех ближайших стримерских элементов указанного типа с возможностью самому указывать позицию (от которой она будет их искать), дистанцию (на которой она будет их искать) и виртуальный мир для их нахождения. И это - Streamer_GetNearbyItems.

    • Streamer_GetNearbyItems
      Эта функция ищет все элементы в указанном радиусе от заданной позиции, сортируя их по расстоянию и сохраняя результат в переданный массив.

      PHP код:
      Streamer_GetNearbyItems(Float:xFloat:yFloat:ztypeitems[], maxitems sizeof itemsFloat:range 300.0worldid = -1
      Параметры:
      x: Координата X, от которой будет вестись поиск ближайших элементов.
      y: Координата Y, от которой будет вестись поиск ближайших элементов.
      z: Координата Z, от которой будет вестись поиск ближайших элементов.
      type: Тип элементов для поиска.
      items: Массив, в который будут переданы все найденные элементы.
      maxitems: Размер массива с хранимыми элементами (по умолчанию размер массива из аргумента items).
      range: Максимальное расстояние от заданной позиции для поиска предметов в её пределах (по умолчанию 300.0).
      worldid: ID виртуального мира (по умолчанию -1 - все).

      Возвращает:
      Количество найденных элементов (не ограничивается размером переданного массива, т.е. аргументом maxitems).

      Использование:
      PHP код:
      public OnPlayerDeath(playeridkilleridreason)
      {
          
      //Если игрок умер от гранаты
          
      if(reason == WEAPON_GRENADE)
          {
              
      //То создаём массив для записи в него ID'ов ближайших к игроку 3-ёх актёров (которые при этом должны быть в радиусе 10-ти метров)
              
      new actors[3] = {-1, ...}; //и по умолчанию заполняем его значениями -1

              
      new Float:xFloat:yFloat:z//Создаём переменные для хранения в них позиции умершего игрока
              
      GetPlayerPos(playeridxyz); //Узнаём позицию умершего игрока в эти переменные

              //В первый аргумент передали координату x - x
              //Во второй аргумент координату y - y
              //В третий аргумент координату z - z
              //В четвёртый аргумент передаём тип элементов - STREAMER_TYPE_ACTOR
              //В пятый аргумент сам массив, куда запишутся ID'ы первых 5-ти найденных актёров - actors
              //В шестой аргумент размер этого массива - sizeof actors
              //В седьмой аргумент передали максимальную дистанцию, в пределах которой будет вестись поиск - 10.0
              //По итогу: получаем первых 3 актёра в радиусе 10-ти метров от умершего игрока и (далее по коду) убиваем их
              
      Streamer_GetNearbyItems(xyzSTREAMER_TYPE_ACTORactorssizeof actors10.0); //Последний аргумент worldid передан не был, соответственно он примет значение по умолчанию, т.е. -1 (поиск по всем виртуальным мирам)

              //Запускаем цикл по всем ячейкам нашего теперь уже заполненного массива
              
      for(new isizeof actorsi++)
              {
                  
      //Только если актёр существует (ведь в стриме может вообще не оказаться именно 3-ёх актёров и массив может быть заполнен не до конца)
                  
      if(IsValidDynamicActor(actors[i])) SetDynamicActorHealth(actors[i], 0.0); //То лишь в этом случае убиваем этого актёра
              
      }
          }
          return 
      1;



    Всё, основные функции позади. Теперь перейдём к менее масштабным, но при этом значительно упрощающим взаимодействие со стримерскими элементами, а именно, функции для узнавания и установки позиции любого элемента (на замену Streamer_GetFloatData и Streamer_SetFloatData, где x, y и z позиция теперь удобно пишется в три аргумента при единичном вызове функции). И это - Streamer_GetItemPos и Streamer_SetItemPos.

    • Streamer_GetItemPos
      Эта функция узнаёт (получает) позицию указанного стримерского элемента.

      PHP код:
      Streamer_GetItemPos(typeid, &Float:x, &Float:y, &Float:z
      Параметры:
      type: Тип элемента.
      id: ID элемента.
      x: Координата X этого стримерского элемента.
      y: Координата Y этого стримерского элемента.
      z: Координата Z этого стримерского элемента.

      Возвращает:
      0 при неудаче, 1 при успешном выполнении (позиция передаётся в вами указанные переменные в аргументах функции).

      Использование:
      PHP код:
      stock GetDynamicPickupPos(pickupid, &Float:x, &Float:y, &Float:z)
      {
          
      //В первый аргумент передали тип элемента - STREAMER_TYPE_PICKUP
          //Во второй аргумент передали сам ID элемента - pickupid
          //В третий аргумент передали переменную, в которую запишется координата x - x
          //В четвёртый аргумент переменную, в которую запишется координата y - y
          //В пятый аргумент переменную, в которую запишется координата z - z
          //По итогу: узнаём позицию динамического пикапа и возвращаем результат выполнения функции
          
      return Streamer_GetItemPos(STREAMER_TYPE_PICKUPpickupidxyz);

    • Streamer_SetItemPos
      Эта функция устанавливает позицию для стримерского элемента.

      PHP код:
      Streamer_SetItemPos(typeidFloat:xFloat:yFloat:z
      Параметры:
      type: Тип элемента.
      id: ID элемента.
      x: Координата X, которую желаете установить.
      y: Координата Y, которую желаете установить.
      z: Координата Z, которую желаете установить.

      Возвращает:
      0 при неудаче, 1 при успешном выполнении.

      Использование:
      PHP код:
      stock SetDynamicPickupPos(pickupidFloat:xFloat:yFloat:z)
      {
          
      //В первый аргумент передали тип элемента - STREAMER_TYPE_PICKUP
          //Во второй аргумент передали сам ID элемента - pickupid
          //В третий аргумент передали переменную с координатой x - x
          //В четвёртый аргумент переменную с координатой y - y
          //В пятый аргумент переменную с координатой z - z
          //По итогу: устанавливаем позицию динамического пикапа и возвращаем результат выполнения функции
          
      return Streamer_SetItemPos(STREAMER_TYPE_PICKUPpickupidxyz);



    Заключение

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

    Домашнее задание

    Здесь предлагаю сделать некоторые задания, которые помогут вам убедиться, что вы теперь точно понимаете, как со всем этим работать. Первые посты с правильной реализацией каждого задания (не противоречащей любому из условий) пролайкаю
    Третье задание, как говорится, со звёздочкой.

    1. Написать функцию, которая будет узнавать дистанцию от игрока до созданного стримером 3D-текста. Желательно задействовать на это как можно меньше функций, хорошей мыслью будет две.
      Примерный шаблон функции: Float:GetDistanceToDyn3DTextLabel(playerid, labelid);
      Должна возвращать: дистанцию от игрока до указанного стримерского 3D-текста как Float значение.
    2. Написать функцию, которая будет вычислять: находится ли игрок недалеко (в пределах 50 метров) от какого-либо стримерского пикапа. При этом циклы с перебором всех стримерских пикапов использовать запрещается.
      Примерный шаблон функции: IsPlayerNearDynamicPickup(playerid);
      Должна возвращать: 1, если в пределах 50 метров от игрока есть любой созданный стримером пикап и 0, если в указанном радиусе ничего нет.
    3. Написать функцию, которая будет вычислять, является ли переданный в неё объект player object'ом (т.е. это объект, созданный через CreatePlayerObject) или это dynamic object (т.е. стримерский объект). Напомню, что стримерские объекты базируются на объектах для игроков (player objects) и функции вроде IsValidPlayerObject будут возвращать истину и для стримерских объектов. При этом вам надо учитывать, что под переданным ID'ом реально существующего объекта для игрока (player object) может параллельно быть занят и стримерский объект под таким же идом, и это будут два разных объекта. Иными словами вам нужно точно узнать, является ли конкретный ID объекта объектом для игрока и при этом его ид не использует стример.
      Примерный шаблон функции: GetObjectType(objectid);
      Должна возвращать: 0, если это player object и 1, если это dynamic, т.е. стримерский объект.


    Ссылки по теме

    Streamer Plugin
    Streamer Functions include
    Streamer Plugin Wiki
    Последний раз редактировалось Nexius_Tailer; 08.10.2021 в 20:04.
    Не хотите постоянно проверять обновления моих скриптов?
    Подключите его последним, после всех остальных
    Nexius's Update Checker

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

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±
    Обновил слетевшие ссылки на инклуд StreamerFunctions в конце каждой из трёх частей урока.
    Не хотите постоянно проверять обновления моих скриптов?
    Подключите его последним, после всех остальных
    Nexius's Update Checker

 

 

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

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

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

Ваши права

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