/* 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 "../../../../../game/Player.h" #include "../../../../../game/GossipDef.h" #include "../../../../../game/TargetedMovementGenerator.h" #define SAY_GAMESBEGIN "Let the games begin!" #define SAY_VAEL_INTRO "" #define SAY_DEATH "This cannot be! I am the Master here! You mortals are nothing to my kind! DO YOU HEAR? NOTHING!" #define SOUND_GAMESBEGIN 8280 #define SOUND_VAEL_INTRO 8279 #define SOUND_DEATH 8292 #define GOSSIP_ITEM "Start Event " #define CREATURE_BRONZE_DRAKANOID 14263 #define CREATURE_BLUE_DRAKANOID 14261 #define CREATURE_RED_DRAKANOID 14264 #define CREATURE_GREEN_DRAKANOID 14262 #define CREATURE_BLACK_DRAKANOID 14265 #define CREATURE_CHROMATIC_DRAKANOID 14302 #define SPELL_DRAKONOIDS_RED 22655 //Summon #define SPELL_DRAKONOIDS_GREEN 22656 #define SPELL_DRAKONOIDS_BRONZE 22657 #define SPELL_DRAKONOIDS_BLUE 22658 #define SPELL_DRAKONOIDS_BLACK 22654 #define SPELL_DRAKONOIDS_CHROMATIC 22680 #define CREATURE_NEFARIAN 11583 #define ADD_X1 -7591.151855 #define ADD_X2 -7514.598633 #define ADD_Y1 -1204.051880 #define ADD_Y2 -1150.448853 #define ADD_Z1 476.800476 #define ADD_Z2 476.796570 #define NEF_X -7445 #define NEF_Y -1332 #define NEF_Z 536 #define HIDE_X -7592 #define HIDE_Y -1264 #define HIDE_Z 481 #define SPELL_SHADOWBOLT 21077 #define SPELL_MINDCONTROL 56 // Replaced By a Stunt Since Not Possible to MindControl #define MAX_SUMMON 17 // Normal = 42, Lower to 15 #define TIMER_RESET //This script is complicated //Instead of morphing Victor Nefarius we will have him control phase 1 //And then have him spawn "Nefarian" for phase 2 //When phase 2 starts Victor Nefarius will go into hiding and stop attacking //If Nefarian despawns because he killed the players then this guy will EnterEvadeMode //and allow players to start the event over //If nefarian dies then he will kill himself then he will kill himself in his hiding place //To prevent players from doing the event twice struct MANGOS_DLL_DECL boss_victor_nefariusAI : public ScriptedAI { boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) { EnterEvadeMode(); } int32 shadowBoltTimer; int32 mindControlTimer; int32 summonTimer; int32 summonCheckTimer; int32 sleep; uint8 phase; bool respawnSummon; uint32 summonId[3]; uint64 m_summons[MAX_SUMMON+1]; float x[2], y[2], z[2], o[2]; uint32 mapId; uint64 nefarianGUID; int32 resetTimer; void EnterEvadeMode() { nefarianGUID = 0; resetTimer = 0; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier mindControlTimer = 1000; shadowBoltTimer = 5000; summonTimer = 4000; summonCheckTimer = 2000; sleep = 0; phase = 0; respawnSummon = false; for(uint8 n = 0; n < MAX_SUMMON+1; ++n) m_summons[n] = 0; //Index 0 Gave us the Count summonId[0] = 14302; summonId[1] = 0; summonId[2] = 0; uint8 n = 1; while(summonId[2]==0) { srand(time(NULL)); switch(irand(0,4)) { case 0: { //red if(n == 2 && summonId[1] == 14264) break; summonId[n] = 14264; n = 2; break; } case 1: { //Green if(n == 2 && summonId[1] == 14262) break; summonId[n] = 14262; n = 2; break; } case 2: { //Bronze if(n == 2 && summonId[1] == 14263) break; summonId[n] = 14263; n = 2; break; } case 3: { //Blue if(n == 2 && summonId[1] == 14261) break; summonId[n] = 14264; n = 2; break; } case 4: { //Black if(n == 2 && summonId[1] == 14265) break; summonId[n] = 14265; n = 2; break; } } } mapId = 469; x[0] = -7593.2585; y[0] = -1200.5969; z[0] = 476.7811; o[0] = 5.314193; //Sud x[1] = -7517.3140; y[1] = -1147.3402; z[1] = 476.7811; o[1] = 5.1314; //Nord m_creature->RemoveAllAuras(); m_creature->DeleteThreatList(); m_creature->CombatStop(); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 9472); //Original One m_creature->SetUInt32Value(UNIT_NPC_FLAGS,1); m_creature->setFaction(35); //Friendly m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoGoHome(); } void BeginEvent(Player* target) { DoYell(SAY_GAMESBEGIN,LANG_UNIVERSAL,NULL); DoPlaySoundToSet(m_creature,SOUND_GAMESBEGIN); //MaNGOS::Singleton::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); /* list ::iterator i = MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); for (i = MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); i != MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().end(); ++i) { AttackStart((*i)); } */ phase = 1; m_creature->SetUInt32Value(UNIT_NPC_FLAGS,0); m_creature->setFaction(103); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); AttackStart(target); } void AttackStart(Unit *who) { if(!who) return; if (who->isTargetableForAttack() && who!= m_creature) { DoStartMeleeAttack(who);// Don't think is needed for him since he never really attack. } } void MoveInLineOfSight(Unit *who) { //We simply use this function to find players until we can use Map->GetPlayers() if (who && who->GetTypeId() == TYPEID_PLAYER && m_creature->IsHostileTo(who)) { //Add them to our threat list m_creature->AddThreat(who,0.0f); } } void DamageTaken(Unit* Victim, uint32 &damage) { if(phase != 3) damage = 0; if( m_creature->GetHealth() < damage) { DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); DoPlaySoundToSet(m_creature, SOUND_DEATH); } } void UpdateAI(const uint32 diff) { if(!m_creature->isAlive()) return; Unit* target; uint8 summonIndex; if(phase == 1) { if( m_creature->SelectHostilTarget() && m_creature->getVictim()) { if(!(m_creature->GetUInt32Value(UNIT_FIELD_FLAGS) & UNIT_FLAG_NOT_SELECTABLE)) m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target = SelectUnit(SELECT_TARGET_RANDOM,0); if(!target) return; if(sleep < diff) //Changing Random target { if(target->isInAccessablePlaceFor(m_creature)) { m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->Mutate(new TargetedMovementGenerator((*target),6.0f,PET_FOLLOW_ANGLE)); } sleep = irand(3000,5000); }else sleep -= diff; if( shadowBoltTimer < diff ) //ShadowBoltTimer { DoCast(target,SPELL_SHADOWBOLT); shadowBoltTimer = irand(7000,10000); }else shadowBoltTimer -= diff; if( mindControlTimer < diff ) //ShadowBoltTimer { DoCast(target,SPELL_MINDCONTROL); mindControlTimer = irand(7000,10000); }else mindControlTimer -= diff; Creature *summon; if( summonTimer < diff && m_summons[0] < MAX_SUMMON) //Add spawning mechanism { srand(time(NULL)); if(irand(1,100) > 42) { summonIndex = irand(0,1); summon = m_creature->SummonCreature(summonId[0],x[summonIndex],y[summonIndex],z[summonIndex],o[summonIndex],TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,3600000); srand(time(NULL)); target = SelectUnit(SELECT_TARGET_RANDOM,0); if(summon && target) { summon->AI()->AttackStart(target); m_summons[++m_summons[0]] = summon->GetGUID(); } } else { for(summonIndex = 0; summonIndex < 1; summonIndex++) { summon = m_creature->SummonCreature(summonId[summonIndex+1],x[summonIndex],y[summonIndex],z[summonIndex],o[summonIndex],TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,3600000); srand(time(NULL)); target = SelectUnit(SELECT_TARGET_RANDOM,0); if(summon && target) { summon->AI()->AttackStart(target); m_summons[++m_summons[0]] = summon->GetGUID(); } } } summonTimer = irand(3000,5000); }else summonTimer -= diff; Unit* summonCheck; if(summonCheckTimer < diff) { for(uint8 i = 1; i <= m_summons[0]; i++) { summonCheck = Unit::GetUnit((*m_creature),m_summons[i]); if(summonCheck && summonCheck->isAlive()) { phase = 1; break; } else phase = 2; } summonCheckTimer = 2000; }else summonCheckTimer -= diff; } DoMeleeAttackIfReady(); } if(phase == 2 || phase == 3) { if(!nefarianGUID) { m_creature->GetMotionMaster()->Clear(); m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); //Invisible for event start DoCast(m_creature,8149); //Make super invis //DoCast(m_creature,33356); //Root self Creature* nefarian = m_creature->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000); target = SelectUnit(SELECT_TARGET_TOPAGGRO,0); if(target && nefarian) { nefarian->AI()->AttackStart(target); nefarianGUID = nefarian->GetGUID(); } else DoYell("UNABLE TO SPAWN NEF PROPERLY",LANG_UNIVERSAL,NULL); m_creature->CombatStop(); } else { if(summonCheckTimer < diff && !(phase == 3)) { Unit* nefarian = Unit::GetUnit((*m_creature),nefarianGUID); if(!nefarian || !nefarian->isAlive()) { m_creature->Relocate(-7588.438477f,-1261.883789f,482.1f,0.849401f); m_creature->SendMonsterMove(-7588.438477f,-1261.883789f,482.1f,0.849401f,true,0); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 9472); //Original DisplayId m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); nefarianGUID = 0; phase = 3; m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false); phase = 0; EnterEvadeMode(); } else if( AIHPPercent(nefarian) < 21 && !respawnSummon) { respawnSummon = true; Creature *summon; srand(time(NULL)); for(uint8 n = 0; n < MAX_SUMMON; ++n) { if(irand(1,100) > 42) { summonIndex = irand(0,1); summon = m_creature->SummonCreature(summonId[0],x[summonIndex],y[summonIndex],z[summonIndex],o[summonIndex],TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,3600000); srand(time(NULL)); target = SelectUnit(SELECT_TARGET_RANDOM,0); if(summon && target) summon->AI()->AttackStart(target); } else { for(summonIndex = 0; summonIndex < 1; summonIndex++) { summon = m_creature->SummonCreature(summonId[summonIndex+1],x[summonIndex],y[summonIndex],z[summonIndex],o[summonIndex],TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,3600000); srand(time(NULL)); target = SelectUnit(SELECT_TARGET_RANDOM,0); if(summon && target) summon->AI()->AttackStart(target); } } } } summonCheckTimer = 2000; }else summonCheckTimer -= diff; } } } }; CreatureAI* GetAI_boss_victor_nefarius(Creature *_Creature) { return new boss_victor_nefariusAI (_Creature); } bool GossipSelect_boss_victor_nefarius(Player *player, Creature *_Creature, uint32 sender, uint32 action ) { //Must have more text then that to tell if (action == GOSSIP_ACTION_INFO_DEF + 1) //Fight time { player->PlayerTalkClass->CloseGossip(); ((boss_victor_nefariusAI*)_Creature->AI())->BeginEvent(player); } return true; } bool GossipHello_boss_victor_nefarius(Player *player, Creature *_Creature) { player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); player->PlayerTalkClass->SendGossipMenu(907,_Creature->GetGUID()); return true; } void AddSC_boss_victor_nefarius() { Script *newscript; newscript = new Script; newscript->Name="boss_victor_nefarius"; newscript->GetAI = GetAI_boss_victor_nefarius; newscript->pGossipHello = &GossipHello_boss_victor_nefarius; newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius; m_scripts[nrscripts++] = newscript; }