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

    Статус
    Оффлайн
    Регистрация
    29.09.2014
    Сообщений
    61
    Репутация:
    44 ±

    Передвижение статичных NPC (Sa-mp 0.3.7.) - moveactors.inc

    Приветствую вас.

    Как стало недавно известно, новая версия SA-MP 0.3.7. будет поддерживать создание статичных NPC, которые не будут занимать слоты на сервере, и в отличии от прежних более просты в управлении и создании.
    Цель их добавления очевидна, их можно использовать как продавцов в магазине, продавцов хотдогами и т.п. но они не умеют ходить т.е. передвигаться (т.к. они статичные).
    Я решил, что можно добавить возможность хотьбы для статичных NPC, и создал группу функций для этого.

    Представляю вам moveactors.inc - данный include позволяет статичным NPC передвигаться (ходить) по заданным координатам.

    Описание основных функций:

    MoveActorToPos - основная функция для передвижения статичного NPC
    PHP код:
    MoveActorToPos(actorid,X,Y,Z,action
    actorid - номер (ID) - передвигаемого NPC
    X,Y,Z - координаты (точка) к которым NPC должен подойти
    action - переключатель режима 0 - ходьба, 1 - бег.

    IsActorMoving - функция (макрозамена) проверяющая достиг ли NPC конечной точки назначения
    PHP код:
    IsActorMoving(actorid
    actorid - номер (ID) - передвигаемого NPC
    Функция IsActorMoving возвращает:
    true - если NPC находится в пути
    false - если NPC не двигается


    Описание вспомогательных функций:

    IsActorInCube - проверка нахождения NPC в заданных координатах (в кубе) (не работает при движении NPC)
    PHP код:
    IsActorInCube(actoridxyzedge
    actorid - номер (ID) - NPC
    x,y,z - координаты (точка) места проверки
    edge - радиус проверки (вернее говоря длина ребер куба)
    Функция ActorInPoint возвращает:
    true - если NPC находится в координатах
    false - если NPC не находится в координатах

    SetActorFacingPos - поворот NPC лицом к заданным координатам
    PHP код:
    SetActorFacingPos(actoridx,y
    actorid - номер (ID) - NPC
    x,y - координаты (точка) к которым NPC должен повернутся

    Подключение:

    Включите include после a_samp
    PHP код:
    #include <moveactors> 
    Использование:

    Применение функции зависит целиком и полностью от вашей фантазии, но не стоит ждать чудес, приведу простой пример:
    Команда - передвижение NPC к вашим координатам:
    PHP код:
    new id CreateActor(...);
    ...
    if (
    strcmp("/moveactor"cmdtrue,10))
        {
            if(
    IsActorMoving(id)) SendClientMessage(playerid,-1,"Ваш NPC все еще идет к вам"); // id - номер созданного ранее NPC    
            
    new Float:XFloat:YFloat:Z;
            
    GetPlayerPos(playeridXYZ);
            
    MoveActorToPos(id,XYZ0); // id - номер созданного ранее NPC    
            
    return 1;
        }
    ... 
    Достоинства и недостатки:

    + Гарантированное достижение NPC заданной точки

    - Передвижение происходит по времени
    - Передвижение только по прямым линиям*
    - Небольшая неточность анимации при движении*

    * - (возможно будет исправлено в след. версии)


    UPD 1 (07.05.2015):
    Код:
    - Оптимизация кода;
    - Изменены названия пользовательских функций и порядок их параметров:
    	ActorInPoint(Float:r, actorid, Float:x, Float:y, Float:z) на IsActorInCube(actorid, Float:x, Float:y, Float:z, Float:edge)
    	SetActorFaceToPos(Float:X,Float:Y, actorid) на SetActorFacingPos(actorid, Float:x, Float:y)
    	Функция OnActorMakeIt(actorid) заменена на макрос IsActorMoving(actorid)
    UPD 2 (12.05.2015):
    Код:
    - Добавлена возможность бега для NPC
    - В функцию MoveActorToPos добавлен параметр action для переключения режимов NPC (ходьба, бег)
    UPD 3 (12.05.2015):
    Код:
    - Исправлена ошибка проверки параметра action в функции MoveActorToPos
    Скачивание:

    Rghost.ru
    Pastebin.com

    Спасибо за внимание!
    Автор: NewGreen
    Последний раз редактировалось NewGreen; 12.05.2015 в 23:46.

  2. 10 пользователя(ей) сказали cпасибо:
    #ball (17.05.2015) $continue$ (12.05.2015) BaBuIIIkaDrifteR (16.05.2015) Desulaid (30.04.2015) Gabriel (07.05.2015) L0ndl3m (01.05.2015) makarov (30.04.2015) pastral (30.04.2015) Unreal (01.05.2015) ^_^ (12.05.2015)
  3. #2
    Аватар для Desulaid
    лесоруб продакшен

    Статус
    Оффлайн
    Регистрация
    15.03.2015
    Адрес
    Slobodskoy
    Сообщений
    667
    Репутация:
    236 ±
    В принципе с ними можно будет сделать штат оживленнее + добавить ЭРПЭшности на сервер. Уже придумал куда можно парочку засунуть :)

  4. 2 пользователя(ей) сказали cпасибо:
    NewGreen (30.04.2015) Zaur_Lumanov (15.06.2015)
  5. #3
    Аватар для L0ndl3m
    Пользователь

    Статус
    Оффлайн
    Регистрация
    19.10.2013
    Адрес
    Ярославль
    Сообщений
    1,366
    Репутация:
    774 ±
    Насчёт передвижений по прямой линии, то я бы не сказал, что это это минус. Можно несколько раз вызвать функцию для перемещения бота, создав массив с координатами, и переменную ( для счётчика ).

  6. Пользователь сказал cпасибо:
    NewGreen (01.05.2015)
  7. #4
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    PHP код:
    stock Float:GetDistanceBetweenCoords(actorid,Float:x2,Float:y2,Float:z2
    Сразу бросается в глаза обобщённое название функции - "GetDistanceBetweenCoords" - оно совершенно не говорит о том, что она возвращает расстояние между актёром и точкой.
    В качестве решения могу предложить название "GetDistanceFromActorToPoint".


    Код:
    return floatsqroot(floatpower(floatabs(floatsub(x2,x1)),2)+...
    1. Зачем вычислять модуль числа, если оно возводится в квадрат?
    2. Явное указание floatsub совершенно не нужно - всё равно компилятор заменит знак "-" на вызов нативной функции (подчёркиваю, именно нативной, а не какой-то функции-"обёртки" на Pawn).


    PHP код:
    stock ActorInPoint(Float:ractoridFloat:xFloat:yFloat:z
    Здесь я так и не понял, чего вы пытались добиться в этой функции.
    • Во-первых, если функция возвращает булевое значение, логично было бы начать её название с "Is".
    • Во-вторых, перепутан порядок аргументов функции - по логике сначала должен указываться актёр, а затем уже радиус и координаты.
      Возьмите для сравнения любые функции SA:MP для работы с транспортом - везде первым указывается ID машины.
    • В-третьих, название функции говорит о том, что для возврата true игрок должен находиться именно в указанной точке, а не возле неё.
      Для последнего было бы логичнее использовать название IsActorNearPoint.
    • В-четвёртых, настораживает реализация функции. Вы проверяете вхождение координат игрока не в шар с указанным радиусом, а в куб.
      Тогда так и назовите функцию: IsActorInCube(actorid, x, y, z, edge).
      Здесь edge - это длина ребра куба. Соответственно, вместо r можно будет использовать edge/2.



    PHP код:
    stock SetActorFaceToPos(Float:X,Float:Yactorid)  // This function allows you to change the actor's face turn to the coordinates
    {
            new     
    Float:pX,Float:pY,Float:pZ,Float:ang;
            
    GetActorPos(actoridpXpYpZ);
            if( 
    pY ang = (-acos((pX) / floatsqroot((pX)*(pX) + (pY)*(pY))) - 90.0);
            else if( 
    pY && pX ang = (acos((pX) / floatsqroot((pX)*(pX) + (pY)*(pY))) - 450.0);
            else if( 
    pY ang = (acos((pX) / floatsqroot((pX)*(pX) + (pY)*(pY))) - 90.0);
            if(
    pXang = (floatabs(floatabs(ang) + 180.0));
            else 
    ang = (floatabs(ang) - 180.0);
            
    SetActorFacingAngle(actoridang);
            return 
    false;

    • Опять же, перепутаны местами аргументы.
    • Реализовать функцию можно было куда проще:
    • В чём смысл возвращаемого функцией значения (false)?



    Код:
    stock OnActorMakeIt(actorid) {
            return actorMakeIt[actorid] ? true:false;
    }
    • Египетские скобки (K&R)? Ну вы уж определитесь-то со стилем...
    • С "On" обычно начинаются названия автовызываемых функций.
      Гораздо логичнее было бы сделать функцию "IsActorMoving".
    • Зачем усложнять возврат тернарным выражением?
    • Для чего вообще нужна функция, если массив actorMakeIt и без того доступен вне инклуда?
      Вы уж либо задайте массиву атрибут static, чтобы он был виден только в пределах инклуда, либо хотя бы уберите функцию.



    PHP код:
    public MoveActorToPos(actorid,Float:X,Float:Y,Float:Z) {
            if(
    actorTimers[actorid] != -1) {
                    
    ApplyActorAnimation(actorid,"CARRY","crry_prtial",4.0,0,0,0,0,0);
                    
    KillTimer(actorTimers[actorid]);
                    
    actorTimers[actorid] = -1;
            }
            
    actorMakeIt[actorid] = true;
            
    SetActorFaceToPos(X,Yactorid);
            
    ApplyActorAnimation(actorid"ped""WALK_civi"4.111100);
            
    actorTimers[actorid] = SetTimerEx("StopMoveActorToPos"floatround((GetDistanceBetweenCoords(actorid,X,Y,Z)/1.5357)*918), false"ifff"actorid,X,Y,Z);
            return 
    false;

    Зачем в if сбрасывается анимация, если потом всё равно будет задана анимация бега?
    Присвоение -1 в actorTimers[actorid] бессмысленно по аналогичной причине.


    PHP код:
    public StopMoveActorToPos(actorid,Float:X,Float:Y,Float:Z) {
            
    KillTimer(actorTimers[actorid]);
            
    SetActorPos(actorid,X,Y,Z-0.1);
            
    actorMakeIt[actorid] = false;
            
    ApplyActorAnimation(actorid,"CARRY","crry_prtial",4.0,0,0,0,0,0);
            return 
    false;

    • "StopActor"?
    • actorTimers[actorid] не сбрасывается в -1.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  8. Пользователь сказал cпасибо:
    NewGreen (01.05.2015)
  9. #5
    Аватар для NewGreen
    Пользователь

    Статус
    Оффлайн
    Регистрация
    29.09.2014
    Сообщений
    61
    Репутация:
    44 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Сразу бросается в глаза обобщённое название функции - "GetDistanceBetweenCoords" - оно совершенно не говорит о том, что она возвращает расстояние между актёром и точкой.
    В качестве решения могу предложить название "GetDistanceFromActorToPoint".



    1. Зачем вычислять модуль числа, если оно возводится в квадрат?
    2. Явное указание floatsub совершенно не нужно - всё равно компилятор заменит знак "-" на вызов нативной функции (подчёркиваю, именно нативной, а не какой-то функции-"обёртки" на Pawn).



    Здесь я так и не понял, чего вы пытались добиться в этой функции.
    • Во-первых, если функция возвращает булевое значение, логично было бы начать её название с "Is".
    • Во-вторых, перепутан порядок аргументов функции - по логике сначала должен указываться актёр, а затем уже радиус и координаты.
      Возьмите для сравнения любые функции SA:MP для работы с транспортом - везде первым указывается ID машины.
    • В-третьих, название функции говорит о том, что для возврата true игрок должен находиться именно в указанной точке, а не возле неё.
      Для последнего было бы логичнее использовать название IsActorNearPoint.
    • В-четвёртых, настораживает реализация функции. Вы проверяете вхождение координат игрока не в шар с указанным радиусом, а в куб.
      Тогда так и назовите функцию: IsActorInCube(actorid, x, y, z, edge).
      Здесь edge - это длина ребра куба. Соответственно, вместо r можно будет использовать edge/2.




    • Опять же, перепутаны местами аргументы.
    • Реализовать функцию можно было куда проще:
    • В чём смысл возвращаемого функцией значения (false)?




    • Египетские скобки (K&R)? Ну вы уж определитесь-то со стилем...
    • С "On" обычно начинаются названия автовызываемых функций.
      Гораздо логичнее было бы сделать функцию "IsActorMoving".
    • Зачем усложнять возврат тернарным выражением?
    • Для чего вообще нужна функция, если массив actorMakeIt и без того доступен вне инклуда?
      Вы уж либо задайте массиву атрибут static, чтобы он был виден только в пределах инклуда, либо хотя бы уберите функцию.




    Зачем в if сбрасывается анимация, если потом всё равно будет задана анимация бега?
    Присвоение -1 в actorTimers[actorid] бессмысленно по аналогичной причине.



    • "StopActor"?
    • actorTimers[actorid] не сбрасывается в -1.
    Написал просто так ради проверки, версия beta, хотел увидеть реакцию сообщества, что, нужно ли вообще кому либо передвигать NPC, в связи чем написал все быстро, особо не обращая внимания на названия функций и некоторые недочеты.
    Спасибо за адекватную критику, постараюсь в след. версии учесть недочеты.

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

    Статус
    Оффлайн
    Регистрация
    29.09.2014
    Сообщений
    61
    Репутация:
    44 ±
    UPD 1 (07.05.2015):
    Код:
    - Оптимизация кода;
    - Изменены названия пользовательских функций и порядок их аргументов:
    	ActorInPoint(Float:r, actorid, Float:x, Float:y, Float:z) на IsActorInCube(actorid, Float:x, Float:y, Float:z, Float:edge)
    	SetActorFaceToPos(Float:X,Float:Y, actorid) на SetActorFacingPos(actorid, Float:x, Float:y)
    	Функция OnActorMakeIt(actorid) заменена на макрос IsActorMoving(actorid)
    Последний раз редактировалось NewGreen; 07.05.2015 в 12:42.

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

    Статус
    Оффлайн
    Регистрация
    29.09.2014
    Сообщений
    61
    Репутация:
    44 ±
    UPD 2 (12.05.2015):
    Код:
    - Добавлена возможность бега для NPC
    - В функцию MoveActorToPos добавлен параметр action для переключения режимов NPC (ходьба, бег)
    UPD 3 (12.05.2015):
    Код:
    - Исправлена ошибка проверки параметра action в функции MoveActorToPos
    Последний раз редактировалось NewGreen; 12.05.2015 в 23:59.

  12. #8
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Позиция, изменяемая анимациями, не синхронизируется, поэтому это пригодно только для однопользовательского применения.

  13. #9
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от ziggi Посмотреть сообщение
    Позиция, изменяемая анимациями, не синхронизируется, поэтому это пригодно только для однопользовательского применения.
    Если игрок находится далеко от актёра (вне зоны стрима) и его телепортировать рядом с этим актёром (либо он сам подойдёт достаточно близко), то да, анимация и местоположение не синхронизируются. Тем не менее, позиция синхронизируется, как только актёр дойдёт до заданной точки.
    Не такая уж и большая потеря... Особенно если учитывать, что другого выбора и нету (this is SAMP, just deal with it).
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  14. Пользователь сказал cпасибо:
    NewGreen (19.05.2015)
  15. #10
    Аватар для Gressie
    Пользователь

    Статус
    Оффлайн
    Регистрация
    03.05.2013
    Сообщений
    258
    Репутация:
    6 ±
    Актер, не передвигается, а телепортируется.

 

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

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

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

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

Ваши права

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