#include "StdAfx.h" #include "Setup.h" /************************************************************************/ /* Raid_GruulsLair.cpp Script */ /************************************************************************/ // Lair BruteAI #define CN_LAIR_BRUTE 19389 #define MORTALSTRIKE 35054 #define CLEAVE 31345 #define CHARGE 35754 class LairBruteAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(LairBruteAI); SP_AI_Spell spells[3]; bool m_spellcheck[3]; LairBruteAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 3; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { RemoveAIUpdateEvent(); } void AIUpdate() { float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { target = _unit->GetAIInterface()->GetNextTarget(); case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Gronn PriestAI #define CN_GRONN_PRIEST 21350 #define PSYCHICSCREAM 34322 //33130 - death coil #define RENEW 36679 #define HEAL_GRONN_PRIEST 36678 // it's instead of PRAYER_OF_HEALING //#define PRAYER_OF_HEALING 33152 // couldn't find infos about it so disabled class GronnPriestAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(GronnPriestAI); SP_AI_Spell spells[3]; bool m_spellcheck[3]; GronnPriestAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 3; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { RemoveAIUpdateEvent(); } void AIUpdate() { float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; /*****************************/ /* */ /* Boss AIs */ /* */ /*****************************/ // Kiggler The CrazedAI #define CN_KIGGLER_THE_CRAZED 18835 #define LIGHTNING_BOLT 36152 #define GREATER_POLYMORPH 33173 #define ARCANE_EXPLOSION 33237 #define ARCANE_SHOCK 33175 //#define HEX 36700 //#define ARCANE_BLAST 31457 //have none 10yd SPELL class KigglerTheCrazedAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(KigglerTheCrazedAI); SP_AI_Spell spells[4]; bool m_spellcheck[4]; KigglerTheCrazedAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 4; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { RemoveAIUpdateEvent(); } void AIUpdate() { /* if(_unit->GetDistanceSq(target)<20) <--- why do you need this?? _unit->CastSpell(_unit, spells[2].info, spells[2].instant); */ /* if(m_spellcheck[1] == true) //<^-------- Both functions crash server in this place _unit->GetAIInterface()->GetNextTarget(); */ float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: Unit *target; int nrspells; }; // Blindeye The SeerAI #define CN_BLINDEYE_THE_SEER 18836 #define PRAYER_OF_HEALING 33152 #define GREAT_POWER_WORD_SHIELD 33147 #define HEAL 33144 class BlindeyeTheSeerAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(BlindeyeTheSeerAI); SP_AI_Spell spells[3]; bool m_spellcheck[3]; BlindeyeTheSeerAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 3; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { RemoveAIUpdateEvent(); } void AIUpdate() { float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Olm The SummonerAI #define CN_OLM_THE_SUMMONER 18834 #define DEATH_COIL 33130 // ? #define SUMMON_WILD_FEL_STALKER 33131 // Need to add AI for it to make it blizzlike anyway (it's wild felhunter and should be fel stalker?) #define DARK_DECAY 33129 #define HEAL_OLM 31730 // not sure if this should be that healing spell class OlmTheSummonerAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(OlmTheSummonerAI); SP_AI_Spell spells[4]; bool m_spellcheck[4]; OlmTheSummonerAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 4; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { RemoveAIUpdateEvent(); } void AIUpdate() { float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Krosh FirehandAI #define CN_KROSH_FIREHAND 18832 #define GREAT_FIREBALL 33051 #define BALST_WAVE 33061 #define FIRE_WARD 37844 //#define FIREBALL 37463 //#define SPELLSHIELD 33054 class KroshFirehandAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(KroshFirehandAI); SP_AI_Spell spells[3]; bool m_spellcheck[3]; KroshFirehandAI(Creature* pCreature) : CreatureAIScript(pCreature) { FireWardCooldown=30; nrspells = 3; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { FireWardCooldown=30; _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { FireWardCooldown=30; RemoveAIUpdateEvent(); } void AIUpdate() { FireWardCooldown--; if(!FireWardCooldown)//_unit->getAttackTarget()) { _unit->CastSpell(_unit, spells[2].info, spells[2].instant); FireWardCooldown=30; } /* if(_unit->GetDistanceSq(target)<20) // bad idea, as long as I can see that _unit->CastSpell(_unit, spells[2].info, spells[2].instant); */ else { float val = sRand.rand(100.0f); SpellCast(val); } } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: Unit *target; uint32 FireWardCooldown; int nrspells; }; // MaulgarAI #define CN_HIGH_KING_MAULAGR 18831 #define ARCINGSMASH 38761 #define MIGHTYBLOW 33230 #define WHIRLWIND 33239 #define ENRAGE 34970 // no idea about id, can be also: 34970, 37023 and others as nowhere is told which Enrage it should be class HighKingMaulgarAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(HighKingMaulgarAI); SP_AI_Spell spells[4]; bool m_spellcheck[4]; HighKingMaulgarAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 4; for(int i=0;iSendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, " on a real power in Outland!"); _unit->PlaySoundToSet(11367); RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Grull will crash you!"); _unit->PlaySoundToSet(11376); RemoveAIUpdateEvent(); } void OnTargetDied(Unit* mTarget) { if (_unit->GetHealthPct() > 0) // Hack to prevent double yelling (OnDied and OnTargetDied when creature is dying) { int RandomSpeach; sRand.randInt(1000); RandomSpeach=rand()%3; switch (RandomSpeach) { case 0: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You're not so tough after all!"); _unit->PlaySoundToSet(11373); break; case 1: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Whahaha!"); // more accurate? _unit->PlaySoundToSet(11374); break; case 2: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Maulgar is king!"); _unit->PlaySoundToSet(11375); break; } } } void AIUpdate() { float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } if (spells[i].speech != "") { _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str()); _unit->PlaySoundToSet(spells[i].soundid); } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // GruulsAI #define CN_GRUUL_THE_DRAGONKILLER 19044 #define GROWTH 36300 #define CAVE_IN 36240 #define GROUND_SLAM 33525 #define SHATTER 33671 // Should be used only when Stoned #define HURTFUL_STRIKE 33813 #define REVERBERATION 36297 #define STONED 33652 #define GRONN_LORDS_GRASP 33572 // Should be used only after Ground Slam // % chances changed to let boss use normal attks too // Note: Maybe we should add additional spell description option to // define next spells. // TO DO: Find out what rest of sounds are for and add feature to random choose between // several spell sounds. class GruulsTheDragonkillerAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(GruulsTheDragonkillerAI); SP_AI_Spell spells[8]; bool m_spellcheck[8]; GruulsTheDragonkillerAI(Creature* pCreature) : CreatureAIScript(pCreature) { GrowthCooldown = 30; nrspells = 8; for(int i=0;iSendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Come and die!"); _unit->PlaySoundToSet(11355); RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); _unit->CastSpell(_unit, spells[0].info, spells[0].instant); } void OnTargetDied(Unit* mTarget) { if (_unit->GetHealthPct() > 0) // Hack to prevent double yelling (OnDied and OnTargetDied when creature is dying) { int RandomSpeach; sRand.randInt(1000); RandomSpeach=rand()%3; switch (RandomSpeach) { case 0: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "No more!"); _unit->PlaySoundToSet(11360); break; case 1: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Unworthy!"); _unit->PlaySoundToSet(11361); break; case 2: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Die!"); _unit->PlaySoundToSet(11362); break; } } } void OnCombatStop(Unit *mTarget) { _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); GrowthCooldown = 30; RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Wraaaa!"); // more correct please ? :P _unit->PlaySoundToSet(11363); RemoveAIUpdateEvent(); GrowthCooldown = 30; } void AIUpdate() { GrowthCooldown--; if(!GrowthCooldown)//_unit->getAttackTarget()) { _unit->CastSpell(_unit, spells[0].info, spells[0].instant); GrowthCooldown=30; } float val = sRand.rand(100.0f); SpellCast(val); } void SpellCast(float val) { if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget()) { float comulativeperc = 0; Unit *target = NULL; for(int i=0;iGetAIInterface()->GetNextTarget(); switch(spells[i].targettype) { case TARGET_SELF: case TARGET_VARIOUS: _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break; case TARGET_ATTACKING: _unit->CastSpell(target, spells[i].info, spells[i].instant); break; case TARGET_DESTINATION: _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break; } if (spells[i].speech != "") { _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str()); _unit->PlaySoundToSet(spells[i].soundid); } m_spellcheck[i] = false; return; } if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: uint32 GrowthCooldown; int nrspells; }; void SetupGruulsLair(ScriptMgr * mgr) { mgr->register_creature_script(CN_LAIR_BRUTE, &LairBruteAI::Create); mgr->register_creature_script(CN_GRONN_PRIEST, &GronnPriestAI::Create); mgr->register_creature_script(CN_KIGGLER_THE_CRAZED, &KigglerTheCrazedAI::Create); mgr->register_creature_script(CN_BLINDEYE_THE_SEER, &BlindeyeTheSeerAI::Create); mgr->register_creature_script(CN_OLM_THE_SUMMONER, &OlmTheSummonerAI::Create); mgr->register_creature_script(CN_KROSH_FIREHAND, &KroshFirehandAI::Create); mgr->register_creature_script(CN_HIGH_KING_MAULAGR, &HighKingMaulgarAI::Create); mgr->register_creature_script(CN_GRUUL_THE_DRAGONKILLER, &GruulsTheDragonkillerAI::Create); }