/* Copyright (C) 2006,2007 ScriptDev2 * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../../sc_defines.h" #include "../../../../../shared/WorldPacket.h" #define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!" #define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?" #define OZ_GOSSIP1 "I'm not an actor." #define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!" #define OZ_GOSSIP2 "Ok, I'll give it a try, then." #define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?" #define RAJ_GOSSIP1 "I've never been more ready." // I made this one up for Big Bad Wolf event, as I do not know what it is on official #define SAY_HOOD_INTRO1 "Whoa! Scared me for a second there, I thought you were someone else" #define HOOD_GOSSIP1 "I get that a lot." #define SOUND_OZ1 9174 #define SAY_OZ1 "Welcome Ladies and Gentlemen, to this evening's presentation!" #define SOUND_OZ2 9338 #define SAY_OZ2 "Tonight we plumb the depths of the human soul as we join a lost, lonely girl trying desperately -- with the help of her loyal companions -- to find her way home!" #define SOUND_OZ3 9339 #define SAY_OZ3 "But she is pursued ... by a wicked malevolent crone!" #define SOUND_OZ4 9340 #define SAY_OZ4 "Will she survive? Will she prevail? Only time will tell. And now ... on with the show!" #define SOUND_HOOD1 9175 #define SAY_HOOD1 "Good evening, Ladies and Gentlemen! Welcome to this evening's presentation!" #define SOUND_HOOD2 9335 #define SAY_HOOD2 "Tonight, things are not what they seem. For tonight, your eyes may not be trusted." #define SOUND_HOOD3 9336 #define SAY_HOOD3 "Take for instance, this quiet, elderly woman, waiting for a visit from her granddaughter. Surely there is nothing to fear from this sweet, grey-haired, old lady." #define SOUND_HOOD4 9337 #define SAY_HOOD4 "But don't let me pull the wool over your eyes. See for yourself what lies beneath those covers! And now...on with the show!" #define SOUND_RAJ1 9176 #define SAY_RAJ1 "Welcome, Ladies and Gentlemen, to this evening's presentation!" #define SOUND_RAJ2 9341 #define SAY_RAJ2 "Tonight, we explore a tale of forbidden love!" #define SOUND_RAJ3 9342 #define SAY_RAJ3 "But beware, for not all love stories end happily, as you may find out. Sometimes, love pricks like a thorn." #define SOUND_RAJ4 9343 #define SAY_RAJ4 "But don't take it from me, see for yourself what tragedy lies ahead as the paths of star-crossed lovers meet. And now...on with the show!" #define SAY_JUL_RES_ROMEO "Come, gentle night; and give me back my Romulo!" #define SPELL_ETERNALAFF 30878 #define EVENT_HOOD 1 #define EVENT_OZ 2 #define EVENT_RAJ 3 #define POS_Z 90.5 #define POS_OR 4.5 #define WOLF_X -10892 #define WOLF_Y -1758 #define OZ_Y -1750 #define ROAR_X -10891 #define DOR_X -10896 #define TIN_X -10884 #define STRAW_X -10902 #define CRONE_X -10890 #define CRONE_Y -1747 #define JUL_X -10892 #define JUL_Y -1758 #define B_X1 -10868 #define B_Y1 -1781 #define B_O1 1.56 #define B_X2 -10867.9 #define B_Y2 -1779.7 #define B_O2 3.13 #define B_X3 -10890.9 #define B_Y3 -1777.9 #define B_O3 3.00 #define B_X4 -10891.1 #define B_Y4 -1781.4 #define B_O4 4.68 #define SPELL_SPOTLIGHT 25824 #define SPELL_ROOTSELF 31366 struct MANGOS_DLL_DECL npc_barnesAI : public ScriptedAI { npc_barnesAI(Creature *barnes) : ScriptedAI(barnes) {EnterEvadeMode();} uint32 Event; uint32 DeathCount; uint32 SpeechTimer; uint32 SpeechNum; uint32 WalkTimer; uint32 WalkPos; uint32 ResurrectTimer; // RAJ only uint32 HealTimer; // RAJ only bool SpeechOz; bool SpeechHood; bool SpeechRAJ; bool StageWalk; bool SpawnWalk; bool HasSummoned; bool HasSummonedCrone; // OZ only bool HasSummonedRomulo; // RAJ only bool InCombat; Unit* Holder; Creature* Performer; Creature* Wolf; Creature* Dorothee; Creature* Tinhead; Creature* Strawman; Creature* Roar; Creature* Crone; Creature* Romulo; Creature* Julianne; void EnterEvadeMode() { Event = 0; DeathCount = 0; SpeechTimer = NULL; SpeechNum = 0; WalkTimer = NULL; WalkPos = 0; HealTimer = 20000; // RAJ only ResurrectTimer = 10000; // RAJ only SpeechOz = false; SpeechHood = false; SpeechRAJ = false; StageWalk = false; SpawnWalk = false; HasSummoned = false; HasSummonedCrone = false; HasSummonedRomulo = false; InCombat = false; Holder = NULL; Performer = NULL; Wolf = NULL; Dorothee = NULL; Tinhead = NULL; Strawman = NULL; Roar = NULL; Crone = NULL; Romulo = NULL; Julianne = NULL; Yell("Resetting"); m_creature->RemoveAllAuras(); m_creature->DeleteThreatList(); m_creature->CombatStop(); DoGoHome(); } void AttackStart(Unit *who) { if (!who) return; if (who->isTargetableForAttack() && who!= m_creature) { //Begin melee attack if we are within range DoStartMeleeAttack(who); } } void JustDied(Unit *killer) { DoTextEmote("is dead", NULL); } void WalkToStage(Player* player, uint32 EventID) { Holder = ((Unit*)player); WalkTimer = 0; WalkPos = 1; StageWalk = true; Event = EventID; } void BeginSpeechOz() { //7 seconds DoYell(SAY_OZ1,LANG_UNIVERSAL,NULL); DoPlaySoundToSet(m_creature,SOUND_OZ1); SpeechTimer = 7000; SpeechNum = 1; SpeechOz = true; } void BeginSpeechHood() { //10 seconds DoYell(SAY_HOOD1,LANG_UNIVERSAL,NULL); DoPlaySoundToSet(m_creature,SOUND_HOOD1); SpeechTimer = 10000; SpeechNum = 1; SpeechHood = true; } void BeginSpeechRAJ() { //10 seconds DoYell(SAY_RAJ1,LANG_UNIVERSAL,NULL); DoPlaySoundToSet(m_creature,SOUND_RAJ1); SpeechTimer = 10000; SpeechNum = 1; SpeechRAJ = true; } void BeginEventHood() { if(!HasSummoned) { Yell("Summoning Big Bad Wolf"); Wolf = m_creature->SummonCreature(17521, WOLF_X, WOLF_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); HasSummoned = true; } } void BeginEventOz() { if(!HasSummoned) { Yell("Summoning Dorothee, Tinhead, Strawman and Roar"); Dorothee = m_creature->SummonCreature(17535, DOR_X, OZ_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); Tinhead = m_creature->SummonCreature(17547, TIN_X, OZ_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); Strawman = m_creature->SummonCreature(17543, STRAW_X, OZ_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); Roar = m_creature->SummonCreature(17546, ROAR_X, OZ_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); HasSummoned = true; } } void BeginEventRAJ() { if(!HasSummoned) { Yell("Summoning Julianne"); Julianne = m_creature->SummonCreature(17534, JUL_X, JUL_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); HasSummoned = true; } } void UpdateAI(const uint32 diff) { if(StageWalk) { if(WalkTimer < diff) { DoTextEmote("is walking", NULL); switch(WalkPos) { case 0: Yell("Case 0"); SpecialMove(B_X1, B_Y1, POS_Z, 5000); m_creature->Relocate(B_X1, B_Y1, POS_Z, B_O1); Yell("Move complete"); if(SpawnWalk) { Yell("Rooting self"); Performer = m_creature->SummonCreature(16473, B_X4, B_Y4, 80, 5, TEMPSUMMON_TIMED_DESPAWN, 2000); if(Performer) Performer->Yell("It's so cold, so dark ... I'm not overacting, am I?", LANG_UNIVERSAL, NULL); Yell("Rooting self"); DoCast(m_creature, SPELL_ROOTSELF); if(Event == 1) { Yell("Event Hood"); BeginEventHood(); } if(Event == 2) { Yell("Event Oz"); BeginEventOz(); } if(Event == 3) { Yell("Event RAJ"); BeginEventRAJ(); } if(Holder) { Yell("Attack Start $N"); AttackStart(Holder); } Yell("End of ifs"); StageWalk = false; Yell("StageWalk set to false"); break; } case 1: Yell("Case 1"); SpecialMove(B_X2, B_Y2, POS_Z, 5000); m_creature->Relocate(B_X2, B_Y2, POS_Z, B_O2); Yell("Movements complete"); WalkTimer = 5000; Yell("WAlk Timer at 5000, breaking"); if(SpawnWalk) WalkPos = 0; else WalkPos = 2; break; case 2: Yell("Case 2"); if(SpawnWalk) { SpecialMove(B_X3, B_Y3, POS_Z, 5000); m_creature->Relocate(B_X3, B_Y3, POS_Z, B_O3); Yell("Movements complete, SpawnWalk true, WalkPos 1"); WalkPos = 1; } else { SpecialMove(B_X3, B_Y3, POS_Z, 15000); m_creature->Relocate(B_X3, B_Y3, POS_Z, B_O3); Yell("Movements complete, Spawnwalk false, WalkPos 3"); WalkPos = 3; } Yell("Walktimer set to 15000, breaking"); WalkTimer = 15000; break; case 3: Yell("Case 3"); if(SpawnWalk) { m_creature->setEmoteState(EMOTE_STATE_NONE); Yell("EMOTE_STATE_NONE"); SpecialMove(B_X4, B_Y4, POS_Z, 15000); m_creature->Relocate(B_X4, B_Y4, POS_Z, B_O4); Yell("Movements complete, SpawnWalk true, WalkPos 2"); WalkPos = 2; } else { SpecialMove(B_X4, B_Y4, POS_Z, 5000); m_creature->Relocate(B_X4, B_Y4, POS_Z, B_O4); Yell("Movements complete, SpawnWalk false, WalkPos 4"); WalkPos = 4; } Yell("Walktimer set to 5000, breaking"); WalkTimer = 5000; break; case 4: DoCast(m_creature, SPELL_SPOTLIGHT); Yell("Casting spotlight"); m_creature->setEmoteState(EMOTE_STATE_TALK); Yell("Talking"); if(Event == 1) BeginSpeechHood(); if(Event == 2) BeginSpeechOz(); if(Event == 3) BeginSpeechRAJ(); Yell("WalkPos set to 2, StageWalk set to false, breaking"); StageWalk = false; break; } }else WalkTimer -= diff; } if(SpeechOz) { if(SpeechTimer < diff) { switch(SpeechNum) { case 1: DoYell(SAY_OZ2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_OZ2); SpeechTimer = 16000; SpeechNum = 2; break; case 2: DoYell(SAY_OZ3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_OZ3); SpeechTimer = 7000; SpeechNum = 3; break; case 3: DoYell(SAY_OZ4, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_OZ4); SpeechTimer = 10000; SpeechNum = 4; break; case 4: StageWalk = true; SpawnWalk = true; Yell("StageWalk, SpawnWalk true; removing all auras, WalkPos 3, SpeechOz false"); m_creature->RemoveAllAuras(); WalkPos = 3; SpeechOz = false; break; } }else SpeechTimer -= diff; } if(SpeechHood) { if(SpeechTimer < diff) { switch(SpeechNum) { case 1: DoYell(SAY_HOOD2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_HOOD2); SpeechTimer = 6000; SpeechNum = 2; break; case 2: DoYell(SAY_HOOD3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_HOOD3); SpeechTimer = 15000; SpeechNum = 3; break; case 3: DoYell(SAY_HOOD4, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_HOOD4); StageWalk = true; SpawnWalk = true; WalkPos = 3; Yell("StageWalk, SpawnWalk true; removing all auras, WalkPos 3, SpeechHood false"); m_creature->RemoveAllAuras(); SpeechHood = false; break; } }else SpeechTimer -= diff; } if(SpeechRAJ) { if(SpeechTimer < diff) { switch(SpeechNum) { case 1: DoYell(SAY_RAJ2, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_RAJ2); SpeechTimer = 6000; SpeechNum = 2; break; case 2: DoYell(SAY_RAJ3, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_RAJ3); SpeechTimer = 15000; SpeechNum = 3; break; case 3: DoYell(SAY_RAJ4, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_RAJ4); StageWalk = true; SpawnWalk = true; WalkPos = 3; Yell("StageWalk, SpawnWalk true; removing all auras, WalkPos 3, SpeechRAJ false"); m_creature->RemoveAllAuras(); SpeechRAJ = false; break; } }else SpeechTimer -= diff; } //Return since we have no target if (!m_creature->SelectHostilTarget()) return; //Check if we have a current target if( m_creature->getVictim() && m_creature->isAlive()) { if(Event == 1) // Red Riding Hood { if(Wolf && (!Wolf->isAlive())) { Wolf = NULL; Yell("Big Bad Wolf dead, killing self"); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false); } } if(Event == 2) // Wizard of Oz { if(Dorothee && (!Dorothee->isAlive())) { Yell("Dorothee dead"); DeathCount++; } if(Tinhead && (!Tinhead->isAlive())) { Yell("Tinhead dead"); DeathCount++; } if(Strawman && (!Strawman->isAlive())) { Yell("Strawman dead"); DeathCount++; } if(Roar && (!Roar->isAlive())) { Yell("Roar dead"); DeathCount++; } if(DeathCount >= 4 && (!HasSummonedCrone)) { Yell("Summoning Crone"); Crone = m_creature->SummonCreature(17535, CRONE_X, CRONE_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); HasSummonedCrone = true; } if(Crone && (!Crone->isAlive())) { Dorothee = NULL; Tinhead = NULL; Strawman = NULL; Roar = NULL; Crone = NULL; Yell("Crone dead, killing self"); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false); } } if(Event == 3) //Romeo and Juliet { if(Julianne && (!Julianne->isAlive())) { Yell("Julianne dead"); DeathCount++; } if(DeathCount >= 1 && (!HasSummonedRomulo) && Julianne) { Yell("Summoning Romulo"); Romulo = Julianne->SummonCreature(17533, JUL_X, JUL_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); HasSummonedRomulo = true; } if((Julianne) && HealTimer < diff) { Yell("Beginning heal"); if(!Romulo || (!Romulo->isAlive())) { Yell("Julianne heal Julianne"); Julianne->CastSpell(Julianne, SPELL_ETERNALAFF, false); } else { switch(rand()&2) { case 0: Yell("Switch 0, Julianne heal Julianne"); Julianne->CastSpell(Julianne, SPELL_ETERNALAFF, false); break; case 1: Yell("Switch 1, Julianne heal Romulo"); Julianne->CastSpell(Romulo, SPELL_ETERNALAFF, false); break; } } HealTimer = 20000; }else HealTimer -= diff; if(HasSummonedRomulo && Julianne && Romulo) { if(ResurrectTimer < diff) { Yell("Beginning Resurrection"); if((!Romulo->isAlive()) && (Julianne->isAlive())) { Julianne->Yell(SAY_JUL_RES_ROMEO, LANG_UNIVERSAL, NULL); Romulo = Julianne->SummonCreature(17533, JUL_X, JUL_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); } if((!Julianne->isAlive()) && (Romulo->isAlive())) { Yell("Resummoning Julianne"); Julianne = m_creature->SummonCreature(17534, JUL_X, JUL_Y, POS_Z, POS_OR, TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000); } ResurrectTimer = 10000; }else ResurrectTimer -= diff; } if(HasSummonedRomulo && (!Romulo->isAlive()) && (!Julianne->isAlive())) { Yell("Both Romulo and Julianne dead, killing self"); m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false); } } } } void SpecialMove(float X, float Y, float Z, uint32 Time) { WorldPacket data( SMSG_MONSTER_MOVE, (41+m_creature->GetPackGUID().size()) ); data.append(m_creature->GetPackGUID()); data << m_creature->GetPositionX() << m_creature->GetPositionY() << m_creature->GetPositionZ(); // unknown field - unrelated to orientation // seems to increment about 1000 for every 1.7 seconds // for now, we'll just use mstime data << getMSTime(); data << uint8(0); // walkback when walking from A to B data << uint32(0x100); //data << uint32(0x0200); // flags /* Flags: 512: Floating, moving without walking/running */ data << Time; // Time in between points data << uint32(1); // 1 single waypoint data << X << Y << Z; // the single waypoint Point B m_creature->SendMessageToSet( &data, true ); } // Temporary to make debug yells easier. void Yell(const char* text) { DoYell(text, LANG_UNIVERSAL, NULL); } }; CreatureAI* GetAI_npc_barnes(Creature *_Creature) { return new npc_barnesAI (_Creature); } void SendBarnesFirstGossip(Player *player, Creature *_Creature, uint32 action) { if(action == GOSSIP_ACTION_INFO_DEF + 1) // Oz { _Creature->Yell(SAY_OZ_INTRO2, LANG_UNIVERSAL, NULL); player->ADD_GOSSIP_ITEM( 0, OZ_GOSSIP2, GOSSIP_SENDER_INFO, GOSSIP_ACTION_INFO_DEF + 1); } if(action == GOSSIP_ACTION_INFO_DEF + 2) // RAJ { _Creature->Yell(SAY_READY, LANG_UNIVERSAL, NULL); ((npc_barnesAI*)_Creature->AI())->WalkToStage(player, EVENT_RAJ); } if(action == GOSSIP_ACTION_INFO_DEF + 3) // Hood { _Creature->Yell(SAY_READY, LANG_UNIVERSAL, NULL); ((npc_barnesAI*)_Creature->AI())->WalkToStage(player, EVENT_HOOD); } player->PlayerTalkClass->CloseGossip(); } void SendBarnesOzReady(Player *player, Creature *_Creature, uint32 action) { if(action == GOSSIP_ACTION_INFO_DEF + 1) { _Creature->Yell(SAY_READY, LANG_UNIVERSAL, NULL); ((npc_barnesAI*)_Creature->AI())->WalkToStage(player, EVENT_OZ); } player->PlayerTalkClass->CloseGossip(); } bool GossipSelect_npc_barnes(Player *player, Creature *_Creature, uint32 sender, uint32 action ) { if(sender == GOSSIP_SENDER_MAIN) SendBarnesFirstGossip(player, _Creature, action); if(sender == GOSSIP_SENDER_INFO) SendBarnesOzReady(player, _Creature, action); return true; } bool GossipHello_npc_barnes(Player *player, Creature *_Creature) { switch(rand()%3) { case 0: _Creature->Yell(SAY_OZ_INTRO1, LANG_UNIVERSAL, NULL); player->ADD_GOSSIP_ITEM( 0, OZ_GOSSIP1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); break; case 1: _Creature->Yell(SAY_RAJ_INTRO1, LANG_UNIVERSAL, NULL); player->ADD_GOSSIP_ITEM( 0, RAJ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); break; case 2: _Creature->Yell(SAY_HOOD_INTRO1, LANG_UNIVERSAL, NULL); player->ADD_GOSSIP_ITEM( 0, HOOD_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); break; } player->PlayerTalkClass->SendGossipMenu(907,_Creature->GetGUID()); return true; } void AddSC_npc_barnes() { Script *newscript; newscript = new Script; newscript->Name="npc_barnes"; newscript->GetAI = GetAI_npc_barnes; newscript->pGossipHello = &GossipHello_npc_barnes; newscript->pGossipSelect = &GossipSelect_npc_barnes; m_scripts[nrscripts++] = newscript; }