|
|
Модератор форума: Dimitro |
Форум TrinityCore Установка / Настройка TrinityCore [Мануал] Написание босса на С++ (скриптуем через ScriptedAI) |
[Мануал] Написание босса на С++ |
Всем привет. Решил поделится информацией, как же все таки заскриптовать босса, моба на С++.
Как мы знаем есть два способа скриптовки 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); } Давайте разберемся что к чему:
Дальше нужно заскриптовать наши спеллы, обновление АИ. Принцип действия данной части кода таков: Если таймер способности меньше или равен нулю, то кастуем спелл и обновляем. Если не выполено предыдушее условие - таймер ведет отстчет в обратную сторону. 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 за подсказку по двум последним способам. |
Quote (pulvik) SELECT_TARGET_NEAREST - эту я незнаю, если кто подскажет я укажу. SELECT_TARGET_FARTHEST - эту я незнаю, если кто подскажет я укажу. Ближайшая и дальнейшая цель.
Arcanum Core © Dev.
Для запросов на выдачу наград/снятие замечаний есть темы в Работе Портала. Не пишите по этому поводу в личку.
Сообщение # 2 написано 02.03.2012 в 09:11
|
| |||
| |||