PDA

Просмотр полной версии : [Урок] Урок 1. Создания NPC и его передвижение



Витёк
24.01.2017, 06:15
Всем привет
В этом уроке я вас научу:
1. Создания NPC и подключения его к серверу
2. Передвежение NPC по кординатам
3. Убийство NPC с огнестрельного оружия или рукопашкой

Приступим:

В начало мода добавим строку

#include <FCNPC>
если вы собрали писать FS то в самое начало добавте

#inclide <a_samp>
#include <FCNPC>

#if defined MOVE_SPEED_SPRINT
#undef MOVE_SPEED_SPRINT
#define MOVE_SPEED_SPRINT (0.896884)
#endif

#if defined MOVE_SPEED_RUN
#undef MOVE_SPEED_RUN
#define MOVE_SPEED_RUN (0.53444)
#endif

#if defined MOVE_SPEED_WALK
#undef MOVE_SPEED_WALK
#define MOVE_SPEED_WALK (0.1532086)
#endif
// выше дефайлы отвечаю за скорость
static MyFirstBot; //Создаём переменную в которую будем записывать id NPC

Далее если вы пишите сразу в мод то в OnGameModeInit если в FS то в OnFilterScriptInit добавте


MyFirstBot = FCNPC_Create("Bot_Name"); //FCNPC_Create - подключаем бота к серверу с ником "Bot_Name" и записываем его id в переменную MyFirstBot
FCNPC_Spawn(MyFirstBot, 70, -199.3511,248.3464,12.0772);//FCNPC_Spawn Спавним нашего бота которого токо что создали MyFirstBot (70 - это id скина, -199.3511,248.3464,12.0772 кординаты где будем спавнить нашего бота)
Всё мы создали нашего NPC и заспавнили. Теперь он будет просто стоять...
Давайте его при спавне заставим ходить по мосту (мост около фермы)
Создадим массив для бота с нашеми точками куда он будет ходить

new Float:FCNPC_GoT[][3] =
{
{-205.4210,252.1659,12.2813},
{-192.7112,299.2160,12.2813},
{-179.6456,296.6065,12.2813},
{-191.8794,249.7988,12.2813}
};
static col; //для подчёта точек (потом в коде увидете где используется)
чтобы добавить ещё 1 точку с коридантами куда будет ходить бот то
к последней точке ставим , и создаём новую {кориднаты x,y,z}
Теперь давайте сделаем чтобы после спавна NPC бегал по точкам
за спавн NPC отвечает FCNPC_OnSpawn создадим его

public FCNPC_OnSpawn(npcid)
{
FCNPC_GoTo(MyFirstBot, FCNPC_GoT[col][0], FCNPC_GoT[col][1], FCNPC_GoT[col][2], MOVE_TYPE_RUN, MOVE_SPEED_RUN, true); //Застовляем нашего бота MyFirstBot бежать по точкам из FCNPC_GoT , MOVE_TYPE_RUN стиль как ходит бот MOVE_SPEED_RUN скорость передвижения которую мы указали выше
col ++;// Присваиваем переменной +1 для кординат с масива которые пробижал NPC
return 1;
}
Всё наш игрок бежит на точку и остановится на ней теперь давайте сделаем чтобы он двигался дальше
за это отвечает public FCNPC_OnReachDestination (вызывается когда игрок добежал до позиции указанной в FCNPC_GoTo)
создаём его

public FCNPC_OnReachDestination(npcid)
{
if(col == sizeof(FCNPC_GoT)) col = 0;//если col == строкам из FCNPC_GoT то сбрасываем на 0 чтобы NPC бежал по кругу
FCNPC_GoTo(MyFirstBot, FCNPC_GoT[col][0], FCNPC_GoT[col][1], FCNPC_GoT[col][2], MOVE_TYPE_RUN, MOVE_SPEED_RUN, true);//Уже писал что это
col ++; //Уже писал что это
return 1;
}
теперь создадим убийство бота
для этого создадим пабилик который отвечает за повреждения бота FCNPC_OnTakeDamage

public FCNPC_OnTakeDamage(npcid, damagerid, weaponid)
{
switch(weaponid)
{
case 0: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 3.0);
case 1: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 5.0);
case 2: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 7.0);
case 3: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 6.0);
case 4: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 8.0);
case 5: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 10.0);
case 6: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 10.0);
case 7: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 9.0);
case 8: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 15.0);
case 14: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 0.5);
case 15: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 5.0);
case 16: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 70.0);
case 18: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 5.0);
case 22: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 11.0);
case 23: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 11.0);
case 24: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 45.0);
case 25: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 50.0);
case 26: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 50.0);
case 27: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 65.0);
case 28: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 10.0);
case 29: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 15.0);
case 30: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 27.0);
case 31: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 23.0);
case 32: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 15.0);
case 33: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 55.0);
case 34: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 70.0);
}
if(FCNPC_GetHealth(npcid) < 0.0) FCNPC_Kill(npcid); // если у бота 0 хп убиваем либо в - пойдёт
return 1;
}
Вот и всё урок окончен
Мы создали нашего NPC который будет бегать по заданным кординатам
Если у вас появились вопросы или ошибки задовайте в теме отвечу
Следующий урок выйдет скоро ))))
Автор урока: Витёк(мой 2 ник Island (всего 2 ника на этом и другом форуме больше не где не зареган))
Копирование статьи без разрешения автора запрешено!

vovandolg
24.01.2017, 07:13
к примеру тут(и не только тут) вызывается float() из за того что ты не указал число как дробное


case 34: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 70.0);



далее эта строка с убийством, тут бы я так сделал чтобы знать наверняка что он не умрёт от 0.9 HP


if(FCNPC_GetHealth(npcid) <= 0.0) FCNPC_Kill(npcid);

Витёк
24.01.2017, 07:40
к примеру тут(и не только тут) вызывается float() из за того что ты не указал число как дробное


case 34: FCNPC_SetHealth(npcid, FCNPC_GetHealth(npcid) - 70.0);



далее эта строка с убийством, тут бы я так сделал чтобы знать наверняка что он не умрёт от 0.9 HP


if(FCNPC_GetHealth(npcid) <= 0.0) FCNPC_Kill(npcid);

Поправил

vovandolg
24.01.2017, 08:18
Можно ещё такой вариант попробовать



public FCNPC_OnTakeDamage(npcid, damagerid, weaponid)
{
new Float:startHP = FCNPC_GetHealth(npcid),
Float:damage;
// можно ещё задефайнить весь урон для удобства
// можно для быстроты ещё создать массив с кол-вом урона к каждому оружию
switch(weaponid)
{
case 0: damage = 3.0;
case 1: damage = 5.0;
case 2: damage = 7.0;
case 3: damage = 6.0;
case 4: damage = 8.0;
case 5: damage = 10.0;
case 6: damage = 10.0;
case 7: damage = 9.0;
case 8: damage = 15.0;
case 14: damage = 0.5;
case 15: damage = 5.0;
case 16: damage = 70.0;
case 18: damage = 5.0;
case 22: damage = 11.0;
case 23: damage = 11.0;
case 24: damage = 45.0;
case 25: damage = 50.0;
case 26: damage = 50.0;
case 27: damage = 65.0;
case 28: damage = 10.0;
case 29: damage = 15.0;
case 30: damage = 27.0;
case 31: damage = 23.0;
case 32: damage = 15.0;
case 33: damage = 55.0;
case 34: damage = 77.0;
default: return 1;
}
if(_:damage == _:0.0) return 1;
new Float:totalHP = floatsub(startHP, damage);
if(totalHP <= 0.0) return FCNPC_Kill(npcid);
FCNPC_SetHealth(npcid, totalHP);
return 1;
}

Long-
24.01.2017, 21:54
#if defined MOVE_SPEED_SPRINT
#undef MOVE_SPEED_SPRINT
#define MOVE_SPEED_SPRINT (0.896884)
#endif

#if defined MOVE_SPEED_RUN
#undef MOVE_SPEED_RUN
#define MOVE_SPEED_RUN (0.53444)
#endif

#if defined MOVE_SPEED_WALK
#undef MOVE_SPEED_WALK
#define MOVE_SPEED_WALK (0.1532086)
#endif

Не нужно было их вырезать из AI_BOTS.
В AI_BOTS , я перехватил скорость бота и немного снизил, дабы игрок мог убежать от бота.
Это не нужно, в твоем случае. В FCNPC он и так есть просто они придерживаются скорости стандартного игрока.
Вроде видел этот урок на другом портале.. :sad::sad:

Витёк
25.01.2017, 02:00
#if defined MOVE_SPEED_SPRINT
#undef MOVE_SPEED_SPRINT
#define MOVE_SPEED_SPRINT (0.896884)
#endif

#if defined MOVE_SPEED_RUN
#undef MOVE_SPEED_RUN
#define MOVE_SPEED_RUN (0.53444)
#endif

#if defined MOVE_SPEED_WALK
#undef MOVE_SPEED_WALK
#define MOVE_SPEED_WALK (0.1532086)
#endif

Не нужно было их вырезать из AI_BOTS.
В AI_BOTS , я перехватил скорость бота и немного снизил, дабы игрок мог убежать от бота.
Это не нужно, в твоем случае. В FCNPC он и так есть просто они придерживаются скорости стандартного игрока.
Вроде видел этот урок на другом портале.. :sad::sad:
да и я просто с твоего примера AI_BOTS начал изучать FCNPC и топо после урока когда полез в include за функциями заметил эти параметры
на п-в был урок (я писал его) щас мои темы удалили тип из за авторских прав что тут выложил эту тему :negative:

ziggi
25.01.2017, 13:35
А можно использовать стандартную систему урона, а менять урон с помощью соответствующих функций.

$continue$
25.01.2017, 17:03
Совет на будущее: у всех оружии есть соответствующая константа, например WEAPON_SNIPER, WEAPON_MINGUN. Куда наглядней их использовать.

Можно ещё такой вариант попробовать



public FCNPC_OnTakeDamage(npcid, damagerid, weaponid)
{
new Float:startHP = FCNPC_GetHealth(npcid),
Float:damage;
// можно ещё задефайнить весь урон для удобства
// можно для быстроты ещё создать массив с кол-вом урона к каждому оружию
switch(weaponid)
{
case 0: damage = 3.0;
case 1: damage = 5.0;
case 2: damage = 7.0;
case 3: damage = 6.0;
case 4: damage = 8.0;
case 5: damage = 10.0;
case 6: damage = 10.0;
case 7: damage = 9.0;
case 8: damage = 15.0;
case 14: damage = 0.5;
case 15: damage = 5.0;
case 16: damage = 70.0;
case 18: damage = 5.0;
case 22: damage = 11.0;
case 23: damage = 11.0;
case 24: damage = 45.0;
case 25: damage = 50.0;
case 26: damage = 50.0;
case 27: damage = 65.0;
case 28: damage = 10.0;
case 29: damage = 15.0;
case 30: damage = 27.0;
case 31: damage = 23.0;
case 32: damage = 15.0;
case 33: damage = 55.0;
case 34: damage = 77.0;
default: return 1;
}
if(_:damage == _:0.0) return 1;
new Float:totalHP = floatsub(startHP, damage);
if(totalHP <= 0.0) return FCNPC_Kill(npcid);
FCNPC_SetHealth(npcid, totalHP);
return 1;
}

[ForD]
26.01.2017, 18:19
Ну вот "удалите тему" =\
Это слабохарактерность такая что-ли?

Osetin
26.01.2017, 23:06
;81850']Ну вот "удалите тему" =\
Это слабохарактерность такая что-ли?
Восстановил пост.

Витёк
27.01.2017, 06:06
dell

vovandolg
27.01.2017, 09:18
Совет на будущее: у всех оружии есть соответствующая константа, например WEAPON_SNIPER, WEAPON_MINGUN. Куда наглядней их использовать.

Знаю)
Я там в коде потом комментарий указал что можно было через массив всё прогнать, на что и не пригодились бы эти константы)

DeimoS
27.01.2017, 17:55
Знаю)
Я там в коде потом комментарий указал что можно было через массив всё прогнать, на что и не пригодились бы эти константы)

С константами можно так же через массив всё прогнать. Только если вдруг однажды мы доживём до выхода новой версии сампа и там Куй вдруг решит изменить ID какого-то оружия, весь твой код придётся править вручную, в отличии от констант :)

Витёк
28.01.2017, 04:21
С константами можно так же через массив всё прогнать. Только если вдруг однажды мы доживём до выхода новой версии сампа и там Куй вдруг решит изменить ID какого-то оружия, весь твой код придётся править вручную, в отличии от констант :)

не дождёшся нового выхода сампа:girl_cry:

vovandolg
28.01.2017, 15:29
С константами можно так же через массив всё прогнать. Только если вдруг однажды мы доживём до выхода новой версии сампа и там Куй вдруг решит изменить ID какого-то оружия, весь твой код придётся править вручную, в отличии от констант :)

..и там Куй вдруг решит исправить все ошибки и выпустить 0.4.7 вхвхвх))
вот ему делать не чего, он там и так небусь путается в коде что баг на баге,
на мта даже ID всех вещей скинов оружия подобен сампцовым.

А если даже и добавил бы что то поменял, то в такие участки кода пришлось бы лезть
и константам ID переписывать, как не крути а менять пришлось бы..

DeimoS
28.01.2017, 16:30
..и там Куй вдруг решит исправить все ошибки и выпустить 0.4.7 вхвхвх))
вот ему делать не чего, он там и так небусь путается в коде что баг на баге,
на мта даже ID всех вещей скинов оружия подобен сампцовым.

А если даже и добавил бы что то поменял, то в такие участки кода пришлось бы лезть
и константам ID переписывать, как не крути а менять пришлось бы..

Эмм, константы хранятся в стандартных инклудах и если вдруг Куй изменит ID оружия, он изменит и константу. То бишь, ничего менять не нужно будет.
Это как с "MAX_PLAYERS" или "MAX_PLAYER_NAME"