Главная » Статьи GTA » Работа с модами и скриптами SAMP »



Информация по созданию модов SAMP [2]
Исчерпывающая информация и фак'и по созданию модов и скриптов GTA SAMP
Информация по соданию скриптов SAMP [3]
Инструкции и описания по созданию SAMP скриптов
Оптимизация модов и скриптов [4]
Статьи по оптимизации модов и скриптов SAMP
Ошибки и их решения [0]
Ошибки при работе с созданием и оптимизацией SAMP модов и скриптов
FAQ по установке и настройке [1]
Вопрос-ответ по установке и настройке модов и скриптов SAMP
Статьи о компиляции PAWN [1]
Вся информация, касающаяся компиляции на языке PAWN с помощью компилятора.
Руководства по NPC [13]
Как работать с NPC в SAMP узнаем из этого раздела



В разделе статей: 24
Показано статей: 1-5
Страницы: 1 2 3 4 5 »

Мануал по добавлению объектов на сервер.

Мануал подготовил DeadSmile

 

Допустим вы расставили объекты в МТА или скачали карту.Тут то и у большинства новичков возникает вопрос:"Как же поставить всё это на сервер?"

 

Ниже я поясню весь процесс пошагово.

 

Шаг 1 - Конвертация объектов из МТА в pawn код.

 

Карты МТА имеют расширение .map (англ "карта").Открываем свой файл в любом текстовом редакторе и видим много каракулей:это и есть наши объекты.Копируем содержимое (Ctr+C) и заходим на сайт

convertffs. com

 

Вставляем скопированный код в окошко:

 

 

Жмём Convert и получаем наш pawno код,выглядит он примерно вот так:

 

 

 

Сделали?Отлично,переходим ко второму шагу.

 

Шаг 2 - добавление кода в мод.

 

Открываем ваш мод(я взял new.pwn для наглядности) .Жмём Ctrl+F и

вписываем вот так

Программа находит нужный нам public

 

 

После первой скобки вставляем наши переконвертированные объекты,выглядеть будет вот так:

 

Но это ещё не всё!

Вы мысленно спросите "Что же ещё?!"

Если вам не плевать на код,то советую выполнить табуляцию,тоесть выравнить код,после табуляции код будет выглядеть так:

 

 

 

Далее компилируем мод(надеюсь вы знаете как это делать),как вы увидите ниже - мой мод скомпилировался без ошибок:

 

 

Финиш!

Информация по соданию скриптов SAMP | Просмотров: 3051 | Дата: 20.03.2015 | Комментарии (0)

Читайте предыдущую часть статьи по ссылкеРазбор скрипта "NPC боксёр в SAMP" (Часть 6)

switch(random(3)) выбираем из трех вариантов, либо NPC

нажмет правую кнопку, а затем левую, попробуйте сделать так сами, когда противоположный игрок находится вблизи от вас, что выполнит комбо 1, либо ох, вообщем запутаешься в этих кнопках, дело в том, что все их переназначают обычно, мало у кого на пробел спринт, а на шифт прыжок. Поэтому вот, что я Вам скажу, потестите на Вашем друге какие кнопки Вы нажимаете, затем гляньте, если пробел это уже прыжок, а не бег, как в оригинале, то она будет KEY_JUMP, иначе KEY_JUMP будет шифт, думаю разберетесь, здесь правда ничего сложного, а домашнее задание всем сделать 3е комбо, в кунг-фу, например, это удар с ноги в прыжке. Итак, что у нас получилось на данные момент – 2 комба и блок, всё используется случайно каждые 250 секунд, то ударим, то заблокируем, не предугадать ведь в схватке)

if(dist> 0.8 && dist<15.0 && GetPVarInt(pid, "box")== 1)

                   {

                            SetPVarInt(npc[npcid][npc_ID], "Condition",0);

                   }

Если игрок далее чем в 0.8 метров от нас, но не далее 15, то ставим состояние 0, и теперь выполняется оно.

if(dist>26.0)

                   {

                       for (new i = 0; i < 499; i++) {

                   if(GetPVarInt(i, "box")== 1){

                            DeletePVar(i,"box");}}

                            KillTimer(boxertimer);

                            FCNPC_Destroy(npc[npcid][npc_ID]);

                            ringused=0;

                            SetTimer("Renewbox",15000,0);

         } если же дистанция между игроком, вызвавшим на бой NPC и NPC более 26 метров, удаляем NPC, можете и бан сразу вписать, ибо ринг, в который портает, из него вообщем нереально выбраться, только с читами, ну может кто-то баги знает, лично я нет, а так если вдруг так получилось, ну вдруг админ портнул Вас далеко, то удаляем NPC и обновляем пикап, что из-за одного другим-то мучиться?

public OnPlayerCommandText(playerid, cmdtext[])

{

    if(!strcmp(cmdtext, "/bc", true))

    {

        SetPlayerInterior(playerid, 5);

        SetPlayerPos(playerid,767.5128,6.9371,1000.7142);

                   SetPlayerFacingAngle(playerid,90.9281);

    }

    return 0;

}

Пишем команду /bc и нас портает в спортзал.

Проблемы скрипта

Итак, здесь мы обсудим, чем же неидеален наш скрипт, ничто не идеально, наверное, но тем не менее. Про дистанцию, я подбирал такую дистанцию, когда NPC ещё не врезается в игрока, ведь если тупо писать goto в игрока, то он будет бежать и бежать в игрока, расстояние 0.8 по практическим исследования показалось оптимальным, дело в том, что если мы будет стоять далеко от нашего соперника и жать кнопки, то мы его даже в фокус не возьмем, данном расстояние позволяет брать игрока в фокус, можно же было бы как-то получать угол, или, для продвинутых кватернион, ну точнее изменять кватернион NPC, чтобы он плавно поворачивался к игроку и дрался с ним, но я не знаю как это делается, кватернионы – это типа повороты в пространстве, но плавные, а не сразу с 45, например, градусов перескачить в 180. Идея типа получать зеркальный угол от игрока – бред, если игрок стоит не лоб в лоб, то NPC будет бить по воздуху, вообщем работает очень не круто, если у кого-то есть способы оптимизации скрипта, значительной оптимизации, пишите в комментариях.

Вернуться в начало статьи: Разбор скрипта "NPC боксёр в SAMP" (Часть 1)

 

Руководства по NPC | Просмотров: 3397 | Дата: 02.11.2014 | Комментарии (0)

Читайте предыдущую часть статьи по ссылкеРазбор скрипта "NPC боксёр в SAMP" (Часть 5)

Паблик для вычисления ближайшего игрока – примем как данное, это математика.

forward boxerfight();

public boxerfight()

{ начинается самое интересное, готовы? Поехали!

for (new npcid = 0; npcid < 1; npcid++) {

                   new Float:dist;

                   new pid = GetClosestPlayer(npc[npcid][npc_ID],dist);

для NPC-боксера задаем переменную дистанция, через переменную pid мы получаем ближайшего игрока к NPC на какой-либо дистанции.

if(dist<15.0 && GetPVarInt(pid, "box")== 1)

                   {

                            SetPVarInt(npc[npcid][npc_ID], "Condition",0);

                   }

Собственно сама дистанция, если дистанция менее 15 и этот человек именно тот, кто бросил вызов NPC, задать состояние NPC равное нулю.

Так как таймер каждые 250 миллисекунд всё проверяет, то просканировав в следующий раз он такой смотрит

if(GetPVarInt(pid, "box")== 1 && GetPVarInt(npc[npcid][npc_ID], "Condition")==0)

                   {

                            new Float:xnc, Float:ync, Float:znc;

                            GetPlayerPos(pid,xnc,ync,znc);

                            FCNPC_GoTo(npc[npcid][npc_ID],xnc,ync,znc,MOVE_TYPE_RUN,0,0);

                   }

Игрок, мол есть, идентификатор у него бокс, а теперь и у NPC ещё состояние нулевое, что означает состояние “беги” в данном случае. Задаем локальные координаты, получаем координаты ближайшего игрока через pid, ну и, конечно же, функцию GetPlayerPos, фишка в том, что pvar нам нужен для того, чтобы NPC не бил просто ближайшего игрока, он будет бить именно того, что бросил вызов, надеюсь теперь немного понятно зачем они здесь. Далее говорим NPC беги в игрока.

Таймер все также по 250 миллисекунд сканирует, вот подбегает он к игроку и тут

if(dist < 0.8 && dist<15.0 && GetPVarInt(pid, "box")== 1)

                   {

                            FCNPC_Stop(npc[npcid][npc_ID]);

                            SetPVarInt(npc[npcid][npc_ID], "Condition",1);

                   }

Опа, дистанция то у нас теперь менее 0.8 и не более 15, а игрок наш тот, что вызов бросил, говорим NPC прекратить бег, бегая удар-то не нанесешь, нормальный по крайней мере, хотя есть такая функция для FCNPC, но лучше её не использовать, итак остановили NPC и перевели его в состояние 1.

Таймер снова сканирует всё

if(GetPVarInt(pid, "box")== 1 && GetPVarInt(npc[npcid][npc_ID], "Condition")==1)

                   {

                            switch(random(3))

                            {

                            case 0: FCNPC_SetKeys(npc[npcid][npc_ID],KEY_HANDBRAKE+KEY_FIRE);

                            case 1: FCNPC_SetKeys(npc[npcid][npc_ID],KEY_HANDBRAKE+KEY_SECONDARY_ATTACK);

                            case 2: FCNPC_SetKeys(npc[npcid][npc_ID],KEY_HANDBRAKE+KEY_JUMP);

                            }

                   }

Теперь у нас выполняется условие, что игрок с индентификатором бокс рядом, в пределах от 0.8 до 15, а состояние NPC равно единичке. Про то, почему такие дистанции, напишу позже.

Читай скорее далее: Разбор скрипта "NPC боксёр в SAMP" (Заключение и выводы)

 

Руководства по NPC | Просмотров: 3416 | Дата: 02.11.2014 | Комментарии (0)

Читайте предыдущую часть статьи по ссылкеРазбор скрипта "NPC боксёр в SAMP" (Часть 4)

SetTimer("spawnNPC", 500, 0); - феил, не стер со старого скрипта, он ничего не делает, раньше NPC вызывался через паблик, паблик удалил, а вот то, что его вызывать один раз не удалил, вообщем он ни на что не влияет можете смело удалить эту строчку.

} – закрываем пикап.

Return 1; - ну обычно его ставят, пусть постоит, он нужен не везде, например, вы вызывали выдачу какого-то сообщения через таймер, таймер крайне мал по времени, в том плане, что вызывается каждые 200 секунд, скажем, чтобы Вам 2 раза не выдало одно и то же, ставим в конце return 0, типа не повторять и удаляем его, это как пример, подробнее на samp wiki)

}Закрываем паблик скобочкой.

forward destroyNPC(npcid);

public destroyNPC(npcid)

{

        FCNPC_Destroy(npcid);

}

Удаляем NPC, используется при смерти NPC.

forward Renewbox(npcid);

public Renewbox(npcid)

{

        pickupkase = CreatePickup(1314,2, 757.4380,5.8088,1000.7014, -1);

        SendClientMessageToAll(-1,"Боксерский ринг обновлен!");

}

Обновляем боксерский ринг и пишем об этом всем

public FCNPC_OnDeath(npcid, killerid, weaponid) вызывается когда NPC умер

{

Проверяем если скин NPC 81 и его состояния равно 0, либо 1, либо 2, то

    if(FCNPC_GetSkin(npcid)==81 && GetPVarInt(npcid, "Condition")== 0 || GetPVarInt(npcid, "Condition")== 1 || GetPVarInt(npcid, "Condition")== 2)

    {

    if(ringused==1) если стоит, что ринг используется, перевести в не используется

    {

    ringused=0;

    SetTimer("Renewbox",15000,0); обновляем ринг

    }

    DeletePVar(npcid,"Condition"); удаляем Pvar для NPC

    SetTimerEx("destroyNPC",5000,0,"dd",npcid); удаляем конкретного NPC

    KillTimer(boxertimer); убиваем таймер

    if(GetPVarInt(killerid, "box")== 1){ если игрок убивший NPC имел идентификатор box, выдадим ему стиль и напишем об этом

    SetPlayerFightingStyle(killerid,FIGHT_STYLE_BOXING);

    SendClientMessage(killerid,COLOR_GREEN,"Вы овладели боксом! ");}

    for (new i = 0; i < 499; i++) {

для всех игроков, если у них идентификатор 1, то зададим виртуальный мир, позицию и угол, а так же удалим идентификатор.

    if(GetPVarInt(i, "box")== 1){

    SetPlayerInterior(i, 5);

    SetPlayerPos(i, 766.2117,6.1029,1000.7167);

    SetPlayerFacingAngle(i, 170.4782);

         DeletePVar(i,"box");}}

    }

         return 1;

}

static stock GetClosestPlayer(playerid,&Float:cdist)

{

         new cid = INVALID_PLAYER_ID;

         new Float:dist;

         new Float:x,Float:y,Float:z;

         new Float:mx,Float:my,Float:mz;

         cdist = 65000.0;

         GetPlayerPos(playerid,mx,my,mz);

         for(new i = GetMaxPlayers();i >= 0;i--)

         {

                   if(playerid == i) continue;

                   if(!IsPlayerConnected(i)) continue;

                   if (IsPlayerNPC(i)) continue;

                   GetPlayerPos(i,x,y,z);

                   x -= mx;

                   y -= my;

                   z -= mz;

                   dist = floatsqroot(x*x + y*y + z*z);

                   if(dist < cdist)

                   {

                            cdist = dist;

                            cid = i;

                   }

         }

         return cid;

}

Читай далее: Разбор скрипта "NPC боксёр в SAMP" (Часть 6)

 

Руководства по NPC | Просмотров: 3333 | Дата: 02.11.2014 | Комментарии (0)

Читайте предыдущую часть статьи по ссылкеРазбор скрипта "NPC боксёр в SAMP" (Часть 3)

ringused=1; - в принципе необязательно это использовать было, можно было бы как-то по-другому сделать, но пусть будет так. Мы сделаем так, что при ringused=1 ринг будет занят, а при ringused=0 ринг свободен, опять же говорю, здесь можно было продумать и по-другому, но когда я создавал какие-то арены, для всех пользователей это было критично, потому что вход туда производился через команду рядом с NPC, которая проверяла, есть ли кто сейчас на арене или нет, чтобы не писать проверки по всем игрокам или какие-то Pvar’ы сканировать, просто одна переменная и проблема решена.

for (new npcid = 0; npcid < 1; npcid++) {

открываем наш цикл, для самого первого нашего NPC имеющего идентификатор в цикле 0 (да-да всё тут начинается на с единички, а с нуля), и говорим, что же от него хотим.

npc[npcid][npc_ID] = FCNPC_Create(npc[npcid][npc_Name]);

Об этом написано в прошлом уроке, вместо имени для каждого NPC из enum’а берем его.

FCNPC_Spawn(npc[npcid][npc_ID], npc[npcid][npc_Skin], npc[npcid][npc_X], npc[npcid][npc_Y], npc[npcid][npc_Z]); - спавним NPC на ринге с такими-то координатами и скином, указанном в enum’е.

FCNPC_SetAngle(npc[npcid][npc_ID], npc[npcid][npc_A]); - угол поворота задаем из enum’а.

FCNPC_SetInterior(npc[npcid][npc_ID], npc[npcid][npc_Interior]); - задаем интерьер, я написал в комментариях, но напишу и тут, извиняюсь, пока не делал этот скрипт, забыл, что виртуальные миры и интерьеры разные вещи, интерьер – это место где находится наш зал, который тоже в данном случае берется из enum’а, а виртульных миров может быть очень и очень много, но в данном случае нам не нужны виртуальные миры, а вот интерьер, для зала бокса в ЛС нужен.

SetPlayerFightingStyle(npc[npcid][npc_ID], npc[npcid][npc_FightStyle]); - зададим для NPC стиль боя, указанный в enum’е.

SetPVarInt(npc[npcid][npc_ID], "Condition",0); - задаем для NPC состояние равном нулю, про смену Pvar’ов и их наглядное действие вы увидите позже в цикле самого боя для NPC.

boxertimer = SetTimer("boxerfight", 250, 1); - чтобы действия не выполнялись разово мы говорим, что каждые 250 миллисекунд (1/4 секунды) выполнять таймер, который мы обозначили как boxertimer. Таймеры работают и без обозначений, но имея обозначения таймера, позже его можно удалить, это важно, чтобы не было нагрузок, да и багов, чтобы не было, а то по 100 раз будете один и тот же таймер вызывать, даже не знаю, что будет, он ведь не разовый, а постоянный о чём свидетельствует цифра 1, а “boxerfight” – это тот паблик, куда нам надо перейти, то есть тот паблик, который выполнять каждые 250 миллисекунд.

}

Далее закрываем цикл для данного NPC, больше нам от него здесь ничего не надо.

Читаем далее: Разбор скрипта "NPC боксёр в SAMP" (Часть 5)

 

Руководства по NPC | Просмотров: 3235 | Дата: 02.11.2014 | Комментарии (0)

1-5 6-10 11-15 16-20 21-24