pro[100]Deadly | Дата: Неділя, 05.12.2010, 20:01 | Сообщение # 1 |
Группа: Видалені
|
В предыдущих уроках мы ознакомились с основными функциями и методами класса npc_escortAI. Сейчас пришло время ознакомиться с тонкостями скриптов с эскортом. Лучше всего это сделать, рассмотрев готовый пример. За пример я взял скрипт с папки ...\TrinityCore 335a\src\server\scripts\Examples который называется example_escort.cpp. Этот скрипт в котором разработчики ядра наглядно показывают как устроена работа скриптов с эскортом. Вот этот скрипт: Code #include "ScriptPCH.h" #include "ScriptedEscortAI.h"
enum eEnums { NPC_FELBOAR = 21878,
SPELL_DEATH_COIL = 33130, SPELL_ELIXIR_OF_FORTITUDE = 3593, SPELL_BLUE_FIREWORK = 11540,
SAY_AGGRO1 = -1999910, SAY_AGGRO2 = -1999911, SAY_WP_1 = -1999912, SAY_WP_2 = -1999913, SAY_WP_3 = -1999914, SAY_WP_4 = -1999915, SAY_DEATH_1 = -1999916, SAY_DEATH_2 = -1999917, SAY_DEATH_3 = -1999918, SAY_SPELL = -1999919, SAY_RAND_1 = -1999920, SAY_RAND_2 = -1999921 };
#define GOSSIP_ITEM_1 "Click to Test Escort(Attack, Run)" #define GOSSIP_ITEM_2 "Click to Test Escort(NoAttack, Walk)" #define GOSSIP_ITEM_3 "Click to Test Escort(NoAttack, Run)"
//( 1 ) class example_escort : public CreatureScript { public: //( 2 ) example_escort() : CreatureScript("example_escort") { } //( 3 ) struct example_escortAI : public npc_escortAI { // CreatureAI functions example_escortAI(Creature* pCreature) : npc_escortAI(pCreature) { }
//( 4 ) uint32 m_uiDeathCoilTimer; uint32 m_uiChatTimer;
//( 5 ) void Reset() { m_uiDeathCoilTimer = 4000; m_uiChatTimer = 4000; }
//( 6 ) // Pure Virtual Functions (Have to be implemented) void WaypointReached(uint32 uiWP) { switch (uiWP) { case 1: DoScriptText(SAY_WP_1, me); break; case 3: DoScriptText(SAY_WP_2, me); me->SummonCreature(NPC_FELBOAR, me->GetPositionX()+5.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); break; case 4: if (Player* pPlayer = GetPlayerForEscort()) { //pTmpPlayer is the target of the text DoScriptText(SAY_WP_3, me, pPlayer); //pTmpPlayer is the source of the text DoScriptText(SAY_WP_4, pPlayer); } break; } }
//( 7 ) void EnterCombat(Unit* /*pWho*/) { if (HasEscortState(STATE_ESCORT_ESCORTING)) { if (Player* pPlayer = GetPlayerForEscort()) DoScriptText(SAY_AGGRO1, me, pPlayer); } else DoScriptText(SAY_AGGRO2, me); }
//( 8 ) void JustDied(Unit* pKiller) { if (HasEscortState(STATE_ESCORT_ESCORTING)) { if (Player* pPlayer = GetPlayerForEscort()) { // not a likely case, code here for the sake of example if (pKiller == me) { DoScriptText(SAY_DEATH_1, me, pPlayer); } else DoScriptText(SAY_DEATH_2, me, pPlayer); } } else DoScriptText(SAY_DEATH_3, me); }
//( 9 ) void UpdateAI(const uint32 uiDiff) { //Must update npc_escortAI npc_escortAI::UpdateAI(uiDiff);
//Combat check if (me->getVictim()) { if (m_uiDeathCoilTimer <= uiDiff) { DoScriptText(SAY_SPELL, me); DoCast(me->getVictim(), SPELL_DEATH_COIL, false); m_uiDeathCoilTimer = 4000; } else m_uiDeathCoilTimer -= uiDiff; } else { //Out of combat but being escorted if (HasEscortState(STATE_ESCORT_ESCORTING)) { if (m_uiChatTimer <= uiDiff) { if (me->HasAura(SPELL_ELIXIR_OF_FORTITUDE, 0)) { DoScriptText(SAY_RAND_1, me); DoCast(me, SPELL_BLUE_FIREWORK, false); } else { DoScriptText(SAY_RAND_2, me); DoCast(me, SPELL_ELIXIR_OF_FORTITUDE, false); }
m_uiChatTimer = 12000; } else m_uiChatTimer -= uiDiff; } } }
//( 10 ) void JustSummoned(Creature* pSummoned) { pSummoned->AI()->AttackStart(me); } };
//( 11 ) CreatureAI* GetAI(Creature* pCreature) const { return new example_escortAI(pCreature); }
//( 12 ) bool OnGossipHello(Player* pPlayer, Creature* pCreature) { pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); pPlayer->PrepareGossipMenu(pCreature, 0);
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
pPlayer->SendPreparedGossip(pCreature);
return true; }
//( 13 ) bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) { pPlayer->PlayerTalkClass->ClearMenus(); npc_escortAI* pEscortAI = CAST_AI(example_escort::example_escortAI, pCreature->AI());
switch(uiAction) { case GOSSIP_ACTION_INFO_DEF+1: pPlayer->CLOSE_GOSSIP_MENU();
if (pEscortAI) pEscortAI->Start(true, true, pPlayer->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+2: pPlayer->CLOSE_GOSSIP_MENU();
if (pEscortAI) pEscortAI->Start(false, false, pPlayer->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+3: pPlayer->CLOSE_GOSSIP_MENU();
if (pEscortAI) pEscortAI->Start(false, true, pPlayer->GetGUID()); break; default: return false; // nothing defined -> trinity core handling }
return true; // no default handling -> prevent trinity core handling } };
//( 14 ) void AddSC_example_escort() { new example_escort(); } Так же я привожу тексты, которые используются в этом скрипте: Code DELETE FROM `script_texts` WHERE entry BETWEEN -1999925 AND -1000000; INSERT INTO `script_texts` (`npc_entry`,`entry`,`content_default`,`sound`,`type`,`language`,`emote`,`comment`) VALUES (0,-1999910,'Help $N! I''m under attack!',0,0,0,0,'example_escort SAY_AGGRO1'), (0,-1999911,'Die scum!',0,0,0,0,'example_escort SAY_AGGRO2'), (0,-1999912,'Hmm a nice day for a walk alright',0,0,0,0,'example_escort SAY_WP_1'), (0,-1999913,'Wild Felboar attack!',0,0,0,0,'example_escort SAY_WP_2'), (0,-1999914,'Time for me to go! See ya around $N!',0,0,0,3,'example_escort SAY_WP_3'), (0,-1999915,'Bye Bye!',0,0,0,3,'example_escort SAY_WP_4'), (0,-1999916,'How dare you leave me like that! I hate you! =*(',0,3,0,0,'example_escort SAY_DEATH_1'), (0,-1999917,'...no...how could you let me die $N',0,0,0,0,'example_escort SAY_DEATH_2'), (0,-1999918,'ugh...',0,0,0,0,'example_escort SAY_DEATH_3'), (0,-1999919,'Taste death!',0,0,0,0,'example_escort SAY_SPELL'), (0,-1999920,'Fireworks!',0,0,0,0,'example_escort SAY_RAND_1'), (0,-1999921,'Hmm, I think I could use a buff.',0,0,0,0,'example_escort SAY_RAND_2'); Добавлено (05.12.2010, 20:00) --------------------------------------------- Для большей наглядности я разделил скрипт на пункты. Каждый пункт будет детально рассмотрен. Как мы видим, для того что мы создать любой скрипт, первоначально мы создаем подкласс класса CreatureScript (пункт 1). Code //( 1 ) class example_escort : public CreatureScript Далее следует объявление названия скрипта (не совсем корректно написано, будет исправлено). (пункт 2) Code //( 2 ) example_escort() : CreatureScript("example_escort") { } Дальше следует класс/структура (не совсем корректно написано, будет исправлено) в которой будут объявлены основные функции нашего скрипта(пункт 3). Code //( 3 ) struct example_escortAI : public npc_escortAI Рассмотрим эту структуру более подробно: Сначала идет объявление переменных, которые используются в этой структуре(пункт 4) Code //( 4 ) uint32 m_uiDeathCoilTimer; uint32 m_uiChatTimer; Как мы можем увидеть, в этом скрипте используются 2 переменные. Когда вы будете создавать свой скрипт, я настоятельно рекомендую использовать в названиях переменных ключевые слова, что бы потом не было путаницы. Как вы можете догадаться эти переменные используются для создания таймеров. Какие именно это таймеры, как и для чего они используются мы рассмотрим немного позже. После переменных идут функции структуры. Обычно первой оглашают функцию Reset();(пункт 5) Code //( 5 ) void Reset() { m_uiDeathCoilTimer = 4000; m_uiChatTimer = 4000; } Эта функция вызывается что бы вернуть существо в исходное состояние. Например, когда существо умирает или эвейдится. Далее следует функция, которая используется в каждом скрипте с эскортом. Это функция WaypointReached(uint32 uiWP);(пункт 6) Code //( 6 ) // Pure Virtual Functions (Have to be implemented) void WaypointReached(uint32 uiWP) { switch (uiWP) { case 1: DoScriptText(SAY_WP_1, me); break; case 3: DoScriptText(SAY_WP_2, me); me->SummonCreature(NPC_FELBOAR, me->GetPositionX()+5.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); break; case 4: if (Player* pPlayer = GetPlayerForEscort()) { //pTmpPlayer is the target of the text DoScriptText(SAY_WP_3, me, pPlayer); //pTmpPlayer is the source of the text DoScriptText(SAY_WP_4, pPlayer); } break; } } Как вы уже знаете существо, которое использует скрипт с эскортом путешествует по заданному нами пути. Этот путь состоит из точек. Существо идет с одной точки в другую. Так вот, каждый раз, когда существо достигает определенной точки а, вызывается функция WaypointReached(а); Например: когда наше существо дойдет до точки 1, будет вызвана функция WaypointReached(1);следовательно, как вы можете увидеть, сработает вот этот участок кода Code case 1: DoScriptText(SAY_WP_1, me); break; а именно, будет вызван метод класса CreatureEventAI Code void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target); Добавлено (05.12.2010, 20:01) --------------------------------------------- Давайте детально рассмотрим эту функцию. Как вы видите функция имеет 3 аргумента: int32 textEntry - ид текста с таблицы script_text базы World WorldObject* pSource - источник воспроизведение текста в игре. Unit* target - цель к которой обращается источник текста. В нашем случае Code DoScriptText(SAY_WP_1, me); ид текста = SAY_WP_1, а источником воспроизведения текста является существо, которое использует данный скрипт (переменная me используется для идентификации существа, которое использует скрипт). Теперь посмотрим что произойдет, когда существо достигнет точки 4 своего пути. Будет вызвана функция WaypointReached(4); и соответственно сработает вот этот участок кода: Code case 4: if (Player* pPlayer = GetPlayerForEscort()) { //pTmpPlayer is the target of the text DoScriptText(SAY_WP_3, me, pPlayer); //pTmpPlayer is the source of the text DoScriptText(SAY_WP_4, pPlayer); } break;
Как видите в данном случае использует метод GetPlayerForEscort(); о котором я говорил в предыдущем уроке, а так же в методе DoScriptText(SAY_WP_3, me, pPlayer); объявлен объект Unit* target.
|
|
|
|