• Страница 1 из 1
  • 1
Модератор форума: Dimitro  
Форум » TrinityCore » Установка / Настройка TrinityCore » [Мануал] Написание босса на С++ (скриптуем через ScriptedAI)
[Мануал] Написание босса на С++
pulvik
Скаут
Всем привет. Решил поделится информацией, как же все таки заскриптовать босса, моба на С++.
Как мы знаем есть два способа скриптовки NPC. Это ScriptedAI и соответственно BossAI.
На данном случае я предлагаю использовать способ ScriptedAI.

Для начала давайте с Вами определимся, какие способности будет использовать наш пациент?
Для данного примера я выбрал 2 спелла:

Далее узнаем каким образом используются данные спеллы? Прочитали, поняли они кастуются на весь рейд, тоесть используем функцию SELECT_TARGET_RANDOM. Но об этом чуть позже.
Итак, приступим:

Для удобства в коде принято называть все своими именами:
Обозначим наши спеллы, перечислив их через 'перечислитель' Enum
Code

enum BossSpells
{
                   SPELL_IMPALE = 56090,
                   SPELL_UNHOLYSHADOW = 57369,
};


Дальше можно приступать к непосредственному оформлению самого босса: для начала создадим его шапочку (укажем имя скрипта)
Создаем отдельный класс для нашего моба/босса, присвоим классу имя нашего моба/босса. Присвоим АИ и зарегистрируем ее.
Code

class boss_wowjp_manual : public CreatureScript
{
public:
                 boss_wowjp_manual() : CreatureScript("boss_wowjp_manual") { }
       
                 CreatureAI* GetAI(Creature* creature) const
                 {
                 return new boss_wowjp_manualAI (creature);
                 }
       
                 struct boss_wowjp_manualAI : public ScriptedAI
                 {
                 boss_wowjp_manualAI(Creature* creature) : ScriptedAI(creature)
                 {
                   instance = creature->GetInstanceScript();
                 }
       
                 InstanceScript* instance;


Дальше мы с Вами разберем, как же ему использовать выбранные спеллы? Например через таймер.
Давайте введем переменные, таймеры для кастов и присвоим им значение
Code

       uint32 ImpaleTimer;
       uint32 UnholyshadowTimer;

       void Reset()
          {
        ImpaleTimer = 30000;
        UnholyshadowTimer = 65000;
          }

Время, используещеся в программировании исчисляется в милисекундах, то есть 30000мс это есть 30 секунд (1000мс=1с)

Чтобы сделать нашего босса более разговорчивым, давайте заставим его болтать, при агро и при смерти. (стандартный набор)
Code

                 void EnterCombat(Unit* /*who*/)
                 {
                   me->MonsterYell("Your death will come now!", LANG_UNIVERSAL, NULL);
                 }
       
                 void JustDied(Unit* /*pKiller*/)
                 {
                   me->MonsterYell("You have deceived me! My time will come ...", LANG_UNIVERSAL, NULL);
                 }


Давайте разберемся что к чему:

  • void EnterCombat(Unit* /*who*/) - условие, агро моба.
  • me->MonsterYell("Your death will come now!", LANG_UNIVERSAL, NULL); - дествие при выполнении предыдущего условия

    • "Your death will come now!" - реплика которую должен выкрикнуть наш пациент при агро. Можно вместо слов в кавычках использовать текст из БД, например (-25, LANG_UNIVERSAL, NULL)
    • LANG_UNIVERSAL - это язык, на котором должен наш босс/моб болтать, из названия думаю ясно что этот способ универсальный, то есть понимают его все.

  • Вторую часть кода расписывать не стану, думаю понятно, тут тоже самое за исключением условия - наш босс/моб умер.
  • Хотелось бы остановить внимание на язках, которые сипользуются в ТС



Дальше нужно заскриптовать наши спеллы, обновление АИ.
Принцип действия данной части кода таков: Если таймер способности меньше или равен нулю, то кастуем спелл и обновляем. Если не выполено предыдушее условие - таймер ведет отстчет в обратную сторону.
Code

     void UpdateAI(const uint32 diff)
                 {
                   if (ImpaleTimer <= diff)
                   {
                   if (Unit* target = SELECT_TARGET_RANDOM)
                     DoCast(target, SPELL_IMPALE);
       
                   ImpaleTimer = 30000;
                   } else ImpaleTimer -= diff;
       
                   if (UnholyshadowTimer <= diff)
                   {
        if (Unit* target = SELECT_TARGET_RANDOM)
        DoCast(target, SPELL_UNHOLYSHADOW);
           
                   UnholyshadowTimer = 65000;
                   } else UnholyshadowTimer -= diff;
       
                   DoMeleeAttackIfReady();
                 }

DoMeleeAttackIfReady(); - эта часть дает боссу/мобу бить обычными атаками, если данной части в коде не будет наш босс будет бегать за вами и бить только тогда, когда подойдет время каста.

Вот вприниципе и вся кодовая часть нашего босса/моба. Давайте теперь из этого всего соберем полный код:
Code

enum BossSpells
{
                   SPELL_IMPALE = 56090,
                   SPELL_UNHOLYSHADOW = 57369,
};
       
class boss_wowjp_manual : public CreatureScript
{
public:
                 boss_wowjp_manual() : CreatureScript("boss_wowjp_manual") { }
       
                 CreatureAI* GetAI(Creature* creature) const
                 {
                 return new boss_wowjp_manualAI (creature);
                 }
       
                 struct boss_wowjp_manualAI : public ScriptedAI
                 {
                 boss_wowjp_manualAI(Creature* creature) : ScriptedAI(creature)
                 {
                   instance = creature->GetInstanceScript();
                 }
       
                 InstanceScript* instance;
       
                 uint32 ImpaleTimer;
                 uint32 UnholyshadowTimer;
       
                 void Reset()
                 {
                   ImpaleTimer = 30000;
                   UnholyshadowTimer = 65000;
                 }
       
                 void EnterCombat(Unit* /*who*/)
                 {
                   me->MonsterYell("Your death will come now!", LANG_UNIVERSAL, NULL);
                 }
       
                 void JustDied(Unit* /*pKiller*/)
                 {
                   me->MonsterYell("You have deceived me! My time will come ...", LANG_UNIVERSAL, NULL);
                 }
       
                 void UpdateAI(const uint32 diff)
                 {
                   if (ImpaleTimer <= diff)
                   {
                   if (Unit* target = SELECT_TARGET_RANDOM)
                     DoCast(target, SPELL_IMPALE);
       
                   ImpaleTimer = 30000;
                   } else ImpaleTimer -= diff;
       
                   if (UnholyshadowTimer <= diff)
                   {
        if (Unit* target = SELECT_TARGET_RANDOM)
        DoCast(target, SPELL_UNHOLYSHADOW);
           
                   UnholyshadowTimer = 65000;
                   } else UnholyshadowTimer -= diff;
       
                   DoMeleeAttackIfReady();
                 }
                 };
};
       
void AddSC_boss_wowjp_manual()
{
                 new boss_wowjp_manual();
}    

void AddSC_boss_wowjp_manual() - этим мы добавим загрузку скрипта в ядро.

Наш босс готов.

P.S. Если вдруг вы захотите его немного изменить, поменять спеллы то тогда это будет кстати:
Цель, которую выберет босс/моб для удара определяется следующим условием:
Code
    
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)

Также бывают и другие типы выбора цели:
SELECT_TARGET_RANDOM - цель выбирается случайно.
SELECT_TARGET_TOPAGGRO - выбирает юнита, который по аггрессии занимает позицию с начала.
SELECT_TARGET_BOTTOMAGGRO - выбирает юнита, который по аггрессии занимает позицию с конца.
SELECT_TARGET_NEAREST - выбирает юнита, который находится ближе всех.
SELECT_TARGET_FARTHEST - выбирает юнита, который находится дальше всех.

спс Dimitro за подсказку по двум последним способам.
Сообщение # 1 отредактировано pulvik - Пятница, 02.03.2012, 09:21
Dimitro
Praise the sun!
Quote (pulvik)
SELECT_TARGET_NEAREST - эту я незнаю, если кто подскажет я укажу.
SELECT_TARGET_FARTHEST - эту я незнаю, если кто подскажет я укажу.

Ближайшая и дальнейшая цель.
Arcanum Core © Dev.
Для запросов на выдачу наград/снятие замечаний есть темы в Работе Портала. Не пишите по этому поводу в личку.
Сообщение # 2 написано 02.03.2012 в 09:11
Djuma_
Скаут
Спасибо за мануал.
Сообщение # 3 написано 04.03.2012 в 12:27
Gangasta
Капрал
как объявить идентификатор
Сообщение # 4 написано 08.03.2012 в 20:26
keonji
I ♥ S-PB
Gangasta, если это скриптовка и идентификатор имеет вид типа
Quote (pulvik)
SPELL_IMPALE
то, зачастую, просто внести в .h файл по аналогии с другими
Сообщение # 5 отредактировано keonji - Четверг, 08.03.2012, 21:38
Форум » TrinityCore » Установка / Настройка TrinityCore » [Мануал] Написание босса на С++ (скриптуем через ScriptedAI)
  • Страница 1 из 1
  • 1
Поиск: