Index: npc_victor_nefarius.cpp =================================================================== --- npc_victor_nefarius.cpp (revision 134) +++ npc_victor_nefarius.cpp (working copy) @@ -17,12 +17,15 @@ #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 " @@ -31,9 +34,17 @@ #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 @@ -52,7 +63,10 @@ #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 @@ -62,125 +76,104 @@ //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) - { - NefarianGUID = 0; - EnterEvadeMode(); - srand(time(NULL)); - switch (rand()%20) - { - case 0: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 1: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 2: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 3: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 4: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 5: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 6: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 7: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 8: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 9: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 10: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 11: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 12: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 13: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 14: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 15: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 16: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 17: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 18: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 19: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - } - } + boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) { EnterEvadeMode(); } - uint32 SpawnedAdds; - uint32 AddSpawnTimer; - uint32 ShadowBoltTimer; - uint32 MindControlTimer; - uint32 ResetTimer; - uint32 DrakType1; - uint32 DrakType2; - uint64 NefarianGUID; - uint32 NefCheckTime; + 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() { - SpawnedAdds = 0; - AddSpawnTimer = 10000; - ShadowBoltTimer = 5000; - ResetTimer = 60000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier - NefarianGUID = 0; - NefCheckTime = 2000; + 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(); - DoGoHome(); + m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 9472); //Original One m_creature->SetUInt32Value(UNIT_NPC_FLAGS,1); - m_creature->setFaction(35); + m_creature->setFaction(35); //Friendly m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoGoHome(); } void BeginEvent(Player* target) @@ -197,6 +190,7 @@ 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); @@ -206,13 +200,12 @@ void AttackStart(Unit *who) { - if (!who) + if(!who) return; if (who->isTargetableForAttack() && who!= m_creature) { - //Begin melee attack if we are within range - DoStartMeleeAttack(who); + DoStartMeleeAttack(who);// Don't think is needed for him since he never really attack. } } @@ -227,128 +220,186 @@ } } + + 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) { - //Return since we have no target - if (!m_creature->SelectHostilTarget() || !m_creature->getVictim() ) + if(!m_creature->isAlive()) return; - //Only do this if we haven't spawned nef yet - if (SpawnedAdds < 42) + Unit* target; + uint8 summonIndex; + if(phase == 1) { - //ShadowBoltTimer - if (ShadowBoltTimer < diff) + if( m_creature->SelectHostilTarget() && m_creature->getVictim()) { - //Cast - Unit* target = NULL; + 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) - DoCast(target,SPELL_SHADOWBOLT); + if(!target) + return; - //Random time till recast between 3 and 10 seconds - ShadowBoltTimer = 3000 + (rand()%7000); - }else ShadowBoltTimer -= diff; + 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; - //Add spawning mechanism - if (AddSpawnTimer < diff) - { - //Spawn 2 random types of creatures at the 2 locations - uint32 CreatureID; - Creature* Spawned = NULL; - Unit* target = NULL; + if( shadowBoltTimer < diff ) //ShadowBoltTimer + { + DoCast(target,SPELL_SHADOWBOLT); + shadowBoltTimer = irand(7000,10000); + }else shadowBoltTimer -= diff; - //1 in 3 chance it will be a chromatic - if (rand()%3 == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else CreatureID = DrakType1; - - SpawnedAdds++; - - //Spawn creature and force it to start attacking a random target - Spawned = m_creature->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - target = SelectUnit(SELECT_TARGET_RANDOM,0); - if (target && Spawned) + if( mindControlTimer < diff ) //ShadowBoltTimer { - Spawned->AI()->AttackStart(target); - Spawned->setFaction(103); - } + DoCast(target,SPELL_MINDCONTROL); + mindControlTimer = irand(7000,10000); + }else mindControlTimer -= diff; - //1 in 3 chance it will be a chromatic - if (rand()%3 == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else CreatureID = DrakType2; - - SpawnedAdds++; - - target = NULL; - Spawned = NULL; - Spawned = m_creature->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - target = SelectUnit(SELECT_TARGET_RANDOM,0); - if (target && Spawned) + Creature *summon; + if( summonTimer < diff && m_summons[0] < MAX_SUMMON) //Add spawning mechanism { - Spawned->AI()->AttackStart(target); - Spawned->setFaction(103); - } + 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; - //Begin phase 2 by spawning Nefarian and what not - if (SpawnedAdds >= 42) + Unit* summonCheck; + if(summonCheckTimer < diff) { - //Teleport Victor Nefarius way out of the map - //MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->CreatureRelocation(m_creature,0,0,-5000,0); - - //Inturrupt any spell casting - m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); - - //Root self - DoCast(m_creature,33356); - - //Make super invis - DoCast(m_creature,8149); - - //Teleport self to a hiding spot (this causes errors in the mangos log but no real issues) - m_creature->Relocate(HIDE_X,HIDE_Y,HIDE_Z,0); - m_creature->SendMonsterMove(HIDE_X,HIDE_Y,HIDE_Z,0,true,0); - m_creature->addUnitState(UNIT_STAT_FLEEING); - - //Spawn nef and have him attack a random target - Creature* Nefarian = NULL; - Nefarian = m_creature->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); - target = NULL; - target = SelectUnit(SELECT_TARGET_RANDOM,0); - if (target && Nefarian) + for(uint8 i = 1; i <= m_summons[0]; i++) { - Nefarian->AI()->AttackStart(target); - Nefarian->setFaction(103); - NefarianGUID = Nefarian->GetGUID(); + summonCheck = Unit::GetUnit((*m_creature),m_summons[i]); + if(summonCheck && summonCheck->isAlive()) + { + phase = 1; + break; + } + else phase = 2; } - else DoYell("UNABLE TO SPAWN NEF PROPERLY",LANG_UNIVERSAL,NULL); - } + summonCheckTimer = 2000; + }else summonCheckTimer -= diff; + } + DoMeleeAttackIfReady(); + } - AddSpawnTimer = 5000; - }else AddSpawnTimer -= diff; - } - else if (NefarianGUID) + if(phase == 2 || phase == 3) { - if (NefCheckTime < diff) + if(!nefarianGUID) { - Unit* Nefarian = NULL; - Nefarian = Unit::GetUnit((*m_creature),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 - //If nef is dead then we die to so the players get out of combat - //and cannot repeat the event - if (!Nefarian || !Nefarian->isAlive()) + 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) { - NefarianGUID = 0; - m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false); + nefarian->AI()->AttackStart(target); + nefarianGUID = nefarian->GetGUID(); } - - NefCheckTime = 2000; - }else NefCheckTime -= diff; - + 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); @@ -356,7 +407,8 @@ bool GossipSelect_boss_victor_nefarius(Player *player, Creature *_Creature, uint32 sender, uint32 action ) { - if (action == GOSSIP_ACTION_INFO_DEF + 1)//Fight time + //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);