#include "StdAfx.h" #include "Setup.h" /************************************************************************/ /* Instance_TheSlavePens.cpp Script */ /************************************************************************/ // Coilfang Champion AI #define CN_COILFANG_CHAMPION 17957 #define INTIMIDATING_SHOUT 33789 // or 38945 || after it on off can go to next unfeared target (mostly healer or ranged unit) // It should also have effect on other allies of target, but somehow it affects caster too (we can use only this: 38946 as workaround // But I think it's better to leave it as it is to not change it in a future as this effect will be repaired) // In Heroid Mode is immune to Mind Control and Seduction (same for Bogstrok) class COILFANGCHAMPIONAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGCHAMPIONAI); SP_AI_Spell spells[1]; bool m_spellcheck[1]; COILFANGCHAMPIONAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 1; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Coilfang Observer AI #define CN_COILFANG_OBSERVER 17938 #define IMMOLATE 29928 // In Heroic mode, it becomes immune to Mind Control and Seduction, but can still be feared and frozen by traps. class COILFANGOBSERVERAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGOBSERVERAI); SP_AI_Spell spells[1]; bool m_spellcheck[1]; COILFANGOBSERVERAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 1; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Coilfang Defender AI #define CN_COILFANG_DEFENDER 17958 #define REFLECTIVE_SHIELD 41475 // No idea which id it should be: Reflective Damage Shield (35159), Reflective Magic Shield (35158), Reflective Shield (41475) // Cannot be trapped or feared, but can be stunned, polymorphed, cycloned and disarmed. // In Heroic, immune to mind control, seduce and sheep, but still vulnerable to stun and kiting. // Stealth Detectors, thus cannot be sapped. class COILFANGDEFENDERAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGDEFENDERAI); SP_AI_Spell spells[1]; bool m_spellcheck[1]; COILFANGDEFENDERAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 1; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); _unit->CastSpell(_unit, spells[0].info, spells[0].instant); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Coilfang Scale-Healer AI #define CN_COILFANG_SCALE_HEALER 21126 #define HOLY_NOVA 37669 // can be: 37669, 34944, 41380, 40096, 36985 #define POWER_WORD_SHIELD 36052 // can be also: 36052, 29408, 41373, 32595, 35944 #define GREATER_HEAL 35096 // all spellids are just my thoughtfulness // Priests can Mind Control these; the surrounding mobs will kill them quickly. // Note: Idk if it casts those spells, but it has them when it's mind controlled. class COILFANGSCALEHEALERAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGSCALEHEALERAI); SP_AI_Spell spells[3]; bool m_spellcheck[3]; COILFANGSCALEHEALERAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 3; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); _unit->CastSpell(_unit, spells[1].info, spells[1].instant); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Coilfang Soothsayer AI #define CN_COILFANG_SOOTHSAYER 17960 #define MIND_CONTROL 36797 // maybe: 36797 or 36798 or ... no idea to id, but // still spell doesn't work, because of lack of core support // All forms of crowd control work on it. class COILFANGSOOTHSAYERAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGSOOTHSAYERAI); SP_AI_Spell spells[1]; bool m_spellcheck[1]; COILFANGSOOTHSAYERAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 1; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Coilfang Technician AI #define CN_COILFANG_TECHNICIAN 17940 #define RAIN_OF_FIRE 34435 // can be: 34360, 34435, 37465, 38635, 39024, 31340, 33617, 39363 #define BLIZZARD 30093 // can be: 30093, 29951, 37263, 38646, 31266, 34356 // Can be seduced and mind controlled in heroic mode. // Note: Idk if it casts those spells, but it has them when it's mind controlled. class COILFANGTECHNICIANAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGTECHNICIANAI); SP_AI_Spell spells[2]; bool m_spellcheck[2]; COILFANGTECHNICIANAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 2; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Coilfang Ray AI #define CN_COILFANG_RAY 21128 #define HOWL_OF_TERROR 39048 // All forms of Beast crowd control work. class COILFANGRAYAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(COILFANGRAYAI); SP_AI_Spell spells[1]; bool m_spellcheck[1]; COILFANGRAYAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 1; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; /*****************************/ /* */ /* Boss AIs */ /* */ /*****************************/ // Mennu the BetrayerAI #define CN_MENNU_THE_BETRAYER 17941 #define MENNUS_HEALING_WARD 34980 #define TAINTED_EARTHGRAB_TOTEM 31981 //31982 //31981 #define TAINTED_STONESKIN_TOTEM 31985 #define CORRUPTED_NOVA_TOTEM 31991 #define LIGHTNING_BOLT 36152 // need to find better id // First 4 spells don't work as more core support is needed for them class MENNUTHEBETRAYERAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(MENNUTHEBETRAYERAI); SP_AI_Spell spells[5]; bool m_spellcheck[5]; MENNUTHEBETRAYERAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 5; for(int i=0;iSendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "The work must continue!"); _unit->PlaySoundToSet(10376); break; case 1: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You brought this on yourselves!"); _unit->PlaySoundToSet(10378); break; case 2: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Don't make me kill you!"); _unit->PlaySoundToSet(10379); break; } RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetHealthPct() > 0) // Hack to prevent double yelling (OnDied and OnTargetDied when creature is dying) { int RandomSpeach; sRand.randInt(1000); RandomSpeach=rand()%2; switch (RandomSpeach) { case 0: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "It had to be done!"); _unit->PlaySoundToSet(10380); break; case 1: _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You should not have come!"); _unit->PlaySoundToSet(10381); break; } } } void OnCombatStop(Unit *mTarget) { CastTime(); _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "I... Deserve this..."); _unit->PlaySoundToSet(10382); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; // Rokmar the CracklerAI #define CN_ROKMAR_THE_CRACKLER 17991 #define GRIEVOUS_WOUND 31956 #define WATER_SPIT 40086 // 35008 #define ENSNARING_MOSS 31948 #define ENRAGE 37023 // ofc not sure ;) maybe: 41305 // boss without sounds class ROKMARTHECRACKLERAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(ROKMARTHECRACKLERAI); SP_AI_Spell spells[4]; bool m_spellcheck[4]; ROKMARTHECRACKLERAI(Creature* pCreature) : CreatureAIScript(pCreature) { ENRAGE_LIMITER = 0; nrspells = 4; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); RemoveAIUpdateEvent(); ENRAGE_LIMITER = 0; } void AIUpdate() { if(_unit->GetHealthPct() <= 20 && ENRAGE_LIMITER == 0) { ENRAGE_LIMITER = 1; // Added to prevent situation when health jumps from 21 to 19 % and enrage is never activated _unit->CastSpell(_unit, spells[3].info, spells[3].instant); } else { 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int ENRAGE_LIMITER; int nrspells; }; // QuagmirranAI #define CN_QUAGMIRRAN 17942 #define ACID_GEYSER 40629 // it isn't right spell (TOO POWERFUL), but I couldn't find correct one for now (as others Idk why don't want to work) #define POISON_BOLT_VOLLEY 39340 // maybe be also: 40095, but it isn't dispelable #define CLEAVE 38474 // 31345, no idea if this is correct class QUAGMIRRANAI : public CreatureAIScript { public: ADD_CREATURE_FACTORY_FUNCTION(QUAGMIRRANAI); SP_AI_Spell spells[3]; bool m_spellcheck[3]; QUAGMIRRANAI(Creature* pCreature) : CreatureAIScript(pCreature) { nrspells = 3; for(int i=0;iGetUInt32Value(UNIT_FIELD_BASEATTACKTIME)); } void CastTime() { for(int i=0;iGetAIInterface()->setCurrentAgent(AGENT_NULL); _unit->GetAIInterface()->SetAIState(STATE_IDLE); RemoveAIUpdateEvent(); } void OnDied(Unit * mKiller) { CastTime(); 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; } 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)) || !spells[i].casttime) { _unit->setAttackTimer(spells[i].attackstoptimer, false); m_spellcheck[i] = true; } comulativeperc += spells[i].perctrigger; } } } protected: int nrspells; }; void SetupTheSlavePens(ScriptMgr * mgr) { mgr->register_creature_script(CN_COILFANG_CHAMPION, &COILFANGCHAMPIONAI::Create); mgr->register_creature_script(CN_COILFANG_OBSERVER, &COILFANGOBSERVERAI::Create); mgr->register_creature_script(CN_COILFANG_DEFENDER, &COILFANGDEFENDERAI::Create); mgr->register_creature_script(CN_COILFANG_SCALE_HEALER, &COILFANGSCALEHEALERAI::Create); mgr->register_creature_script(CN_COILFANG_SOOTHSAYER, &COILFANGSOOTHSAYERAI::Create); mgr->register_creature_script(CN_COILFANG_TECHNICIAN, &COILFANGTECHNICIANAI::Create); mgr->register_creature_script(CN_COILFANG_RAY, &COILFANGRAYAI::Create); mgr->register_creature_script(CN_MENNU_THE_BETRAYER, &MENNUTHEBETRAYERAI::Create); mgr->register_creature_script(CN_ROKMAR_THE_CRACKLER, &ROKMARTHECRACKLERAI::Create); mgr->register_creature_script(CN_QUAGMIRRAN, &QUAGMIRRANAI::Create); } // Notes: Coilfang Slavemaster was already scripted in SteamVaults, so I haven't // copied/pasted it here. // Still many NPCs left and I don't have infos if any of those use any spell :S