| 1 | | /* Copyright ? 2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> |
| 2 | | * This program is free software; you can redistribute it and/or modify |
| 3 | | * it under the terms of the GNU General Public License as published by |
| 4 | | * the Free Software Foundation; either version 2 of the License, or |
| 5 | | * (at your option) any later version. |
| 6 | | * |
| 7 | | * This program is distributed in the hope that it will be useful, |
| 8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | | * GNU General Public License for more details. |
| 11 | | * |
| 12 | | * You should have received a copy of the GNU General Public License |
| 13 | | * along with this program; if not, write to the Free Software |
| 14 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 15 | | */ |
| | 1 | /* Copyright ?2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> |
| | 2 | * This program is free software; you can redistribute it and/or modify |
| | 3 | * it under the terms of the GNU General Public License as published by |
| | 4 | * the Free Software Foundation; either version 2 of the License, or |
| | 5 | * (at your option) any later version. |
| | 6 | * |
| | 7 | * This program is distributed in the hope that it will be useful, |
| | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| | 10 | * GNU General Public License for more details. |
| | 11 | * |
| | 12 | * You should have received a copy of the GNU General Public License |
| | 13 | * along with this program; if not, write to the Free Software |
| | 14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| | 15 | */ |
| 28 | | #define SAY_KALECGOS_AGGRO "Aggh! No longer will I be a slave to Malygos! Challenge me and you will be destroyed!" |
| 29 | | #define SOUND_KALECGOS_AGGRO 12422 |
| 30 | | #define SAY_KALECGOS_SPELL1 "I will purge you!" |
| 31 | | #define SOUND_KALECGOS_SPELL1 12423 |
| 32 | | #define SAY_KALECGOS_SPELL2 "Your pain has only begun!" |
| 33 | | #define SOUND_KALECGOS_SPELL2 12424 |
| 34 | | #define SAY_KALECGOS_SLAY1 "In the name of Kil'jaeden!" |
| 35 | | #define SOUND_KALECGOS_SLAY1 12425 |
| 36 | | #define SAY_KALECGOS_SLAY2 "You were warned!" |
| 37 | | #define SOUND_KALECGOS_SLAY2 12426 |
| 38 | | #define SAY_KALECGOS_ENRAGE "My awakening is complete! You shall all perish!" |
| 39 | | #define SOUND_KALECGOS_ENRAGE 12427 |
| 40 | | |
| 41 | | #define SAY_SATH_AGGRO "There will be no reprieve. My work here is nearly finished." |
| 42 | | #define SOUND_SATH_AGGRO 12451 |
| 43 | | #define SAY_SATH_DEATH "I'm... never on... the losing... side..." |
| 44 | | #define SOUND_SATH_DEATH 12452 |
| 45 | | #define SAY_SATH_SPELL1 "Your misery is my delight!" |
| 46 | | #define SOUND_SATH_SPELL1 12453 |
| 47 | | #define SAY_SATH_SPELL2 "I will watch you bleed!" |
| 48 | | #define SOUND_SATH_SPELL2 12454 |
| 49 | | #define SAY_SATH_SLAY1 "Pitious mortal!" |
| 50 | | #define SOUND_SATH_SLAY1 12455 |
| 51 | | #define SAY_SATH_SLAY2 "Haven't you heard? I always win!" |
| 52 | | #define SOUND_SATH_SLAY2 12456 |
| 53 | | #define SAY_SATH_ENRAGE "I have toyed with you long enough!" |
| 54 | | #define SOUND_SATH_ENRAGE 12457 |
| 55 | | |
| 56 | | #define SAY_KALEC_AGGRO "I need... your help... Cannot... resist him... much longer..." |
| 57 | | #define SOUND_KALEC_AGGRO 12428 |
| 58 | | #define SAY_KALEC_NEAR_DEATH "Aaahhh! Help me, before I lose my mind!" |
| 59 | | #define SOUND_KALEC_NEAR_DEATH 12429 |
| 60 | | //??? |
| 61 | | #define SAY_KALEC_NEAR_DEATH2 "Hurry! There is not much of me left!" |
| 62 | | #define SOUND_KALEC_NEAR_DEATH2 12430 |
| 63 | | #define SAY_KALEC_PLRWIN "I am forever in your debt. Once we have triumphed over Kil'jaeden, this entire world will be in your debt as well." |
| 64 | | #define SOUND_KALEC_PLRWIN 12431 |
| 65 | | |
| 66 | | #define SPELL_SPECTRAL_EXHAUSTION 44867 |
| 67 | | #define SPELL_TELEPORT_SPECTRAL_REALM 46019 |
| 68 | | #define SPELL_SPECTRAL_REALM 46021 |
| 69 | | |
| 70 | | #define NOTIFY_SPECTRALLY_EXHAUSTED "Your body is too exhausted to travel to the Spectral Realm." |
| 71 | | #define ERROR_INST_DATA "SD2: Instance Data not set properly for Sunwell Plateau. Kalecgos Encounter will be buggy." |
| 72 | | #define ERROR_INST_DATA_PLR "SD2 ERROR: Instance Data not set properly for Sunwell Plateau. Please report this to your administrator." |
| 73 | | #define ERROR_UNABLE_TO_TELEPORT "SD2: Unable to select target for Spectral Blast. Threatlist has too few players." |
| 74 | | #define ERROR_MISSING_TELEPORT_GUID "SD2: [Kalecgos] Invalid TeleportTargetGUID. Unable to teleport player." |
| 75 | | #define ERROR_KALECGOS_NOT_FOUND "SD2: Unable to create pointer to Kalecgos from Sathrovarr." |
| 76 | | |
| 77 | | #define KALECGOS_ARENA_X 1704.34 |
| 78 | | #define KALECGOS_ARENA_Y 928.17 |
| 79 | | #define KALECGOS_ARENA_Z 53.08 |
| 80 | | |
| 81 | | /*** Kalecgos ****/ |
| 82 | | #define SPELL_SPECTRAL_BLAST 44866 |
| | 26 | #define KALECGOS_SAY_AGGRO "No longer will I be a slave to Malygos! Challenge me and you will be destroyed!" |
| | 27 | #define KALECGOS_SOUND_AGGRO 12422 |
| | 28 | #define KALECGOS_SAY_SPELL_1 "I will purge you!" |
| | 29 | #define KALECGOS_SOUND_SPELL_1 12423 |
| | 30 | #define KALECGOS_SAY_SPELL_2 "Your pain has only begun!" |
| | 31 | #define KALECGOS_SOUND_SPELL_2 12424 |
| | 32 | #define KALECGOS_SAY_KILL_1 "In the name of Kil'jaeden!" |
| | 33 | #define KALECGOS_SOUND_KILL_1 12425 |
| | 34 | #define KALECGOS_SAY_KILL_2 "You were warned!" |
| | 35 | #define KALECGOS_SOUND_KILL_2 12426 |
| | 36 | #define KALECGOS_SAY_FLY_AWAY "My awakening is complete! You shall all perish!" |
| | 37 | #define KALECGOS_SOUND_FLY_AWAY 12427 |
| | 38 | #define KALECGOS_SAY_WIN "I am forever in your debt. Once we have triumphed over Kil'jaeden, this entire world will be in your debt as well." |
| | 39 | #define KALECGOS_SOUND_WIN 12431 |
| | 40 | |
| | 41 | #define SATH_SAY_AGGRO "Gyahaha... There will be no reprieve. My work here is nearly finished." |
| | 42 | #define SATH_SOUND_AGGRO 12451 |
| | 43 | #define SATH_SAY_DIE "I'm... never on... the losing... side..." |
| | 44 | #define SATH_SOUND_DIE 12452 |
| | 45 | #define SATH_SAY_SPELL_1 "Your misery is my delight!" |
| | 46 | #define SATH_SOUND_SPELL_1 12453 |
| | 47 | #define SATH_SAY_SPELL_2 "I will watch you bleed!" |
| | 48 | #define SATH_SOUND_SPELL_2 12454 |
| | 49 | #define SATH_SAY_KILL_1 "Pitious mortal!" |
| | 50 | #define SATH_SOUND_KILL_1 12455 |
| | 51 | #define SATH_SAY_KILL_2 "Haven't you heard? I always win!" |
| | 52 | #define SATH_SOUND_KILL_2 12456 |
| | 53 | #define SATH_SAY_ENRAGE "I have toyed with you long enough!" |
| | 54 | #define SATH_SOUND_ENRAGE 12457 |
| | 55 | |
| | 56 | #define KALEC_SAY_AGGRO "I need... your help... Cannot... resist him... much longer..." |
| | 57 | #define KALEC_SOUND_AGGRO 12428 |
| | 58 | #define KALEC_SAY_LOSING1 "Aaahhh! Help me, before I lose my mind!" |
| | 59 | #define KALEC_SOUND_LOSING1 12429 |
| | 60 | #define KALEC_SAY_LOSING2 "Hurry! There is not much of me left!" //??? |
| | 61 | #define KALEC_SOUND_LOSING2 12430 |
| | 62 | |
| | 63 | #define GO_FAILED "You are unable to use this currently." |
| | 64 | |
| | 65 | #define FLY_X 1679 |
| | 66 | #define FLY_Y 900 |
| | 67 | #define FLY_Z 82 |
| | 68 | |
| | 69 | #define CENTER_X 1705 |
| | 70 | #define CENTER_Y 930 |
| | 71 | #define RADIUS 30 |
| | 72 | |
| | 73 | #define AURA_SUNWELL_RADIANCE 45769 |
| | 74 | #define AURA_SPECTRAL_EXHAUSTION 44867 |
| | 75 | #define AURA_SPECTRAL_REALM 46021 |
| | 76 | #define AURA_SPECTRAL_INVISIBILITY 44801 |
| | 77 | #define AURA_DEMONIC_VISUAL 44800 |
| | 78 | |
| | 79 | #define SPELL_SPECTRAL_BLAST 44869 |
| | 80 | #define SPELL_TELEPORT_SPECTRAL 46019 |
| 92 | | /*** Sathrovarr ***/ |
| 93 | | #define SPELL_CORRUPTING_STRIKE 45029 |
| 94 | | #define SPELL_CURSE_OF_BOUNDLESS_AGONY 45032 |
| 95 | | #define SPELL_SHADOW_BOLT_VOLLEY 45031 |
| 96 | | |
| 97 | | /*** Misc ***/ |
| 98 | | #define SPELL_BANISH 44836 |
| 99 | | |
| 100 | | void TeleportToInnerVeil(Player* plr) |
| 101 | | { |
| 102 | | if(plr->HasAura(SPELL_SPECTRAL_EXHAUSTION, 0)) |
| 103 | | { |
| 104 | | plr->GetSession()->SendNotification(NOTIFY_SPECTRALLY_EXHAUSTED); |
| 105 | | return; |
| 106 | | } |
| 107 | | |
| 108 | | ScriptedInstance* pInstance = ((ScriptedInstance*)plr->GetInstanceData()); |
| 109 | | if(!pInstance) |
| 110 | | { |
| 111 | | error_log(ERROR_INST_DATA); |
| 112 | | plr->GetSession()->SendNotification(ERROR_INST_DATA_PLR); |
| 113 | | return; |
| 114 | | } |
| 115 | | |
| 116 | | pInstance->SetData64(DATA_PLAYER_SPECTRAL_REALM, plr->GetGUID()); |
| 117 | | // Remove the player from Kalecgos' Threat List |
| 118 | | Creature* Kalecgos = ((Creature*)Unit::GetUnit(*plr, pInstance->GetData64(DATA_KALECGOS_DRAGON))); |
| 119 | | if(Kalecgos) |
| 120 | | { |
| 121 | | HostilReference* ref = Kalecgos->getThreatManager().getOnlineContainer().getReferenceByTarget(plr); |
| 122 | | if(ref) |
| 123 | | ref->removeReference(); |
| 124 | | } |
| 125 | | |
| 126 | | // Add the player to Sathrovarr's Threat List |
| 127 | | Creature* Sathrovarr = ((Creature*)Unit::GetUnit(*plr, pInstance->GetData64(DATA_SATHROVARR))); |
| 128 | | if(Sathrovarr) |
| 129 | | Sathrovarr->AddThreat(plr, 1.0f); |
| 130 | | |
| 131 | | // Make them able to see Sathrovarr (he's invisible for some reason). Also, when this buff wears off, they get teleported back to Normal Realm (this is handled by Instance Script) |
| 132 | | plr->CastSpell(plr, SPELL_SPECTRAL_REALM, true); |
| 133 | | plr->CastSpell(plr, SPELL_TELEPORT_SPECTRAL_REALM, true); |
| 134 | | } |
| 135 | | |
| 136 | | bool GOHello_GO_Spectral_Portal(Player* plr, GameObject* go) |
| 137 | | { |
| 138 | | TeleportToInnerVeil(plr); |
| 139 | | |
| 140 | | return true; |
| 141 | | } |
| 191 | | if(Creature* Sath = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SATHROVARR)))) |
| 192 | | Sath->AI()->EnterEvadeMode(); |
| | 137 | { |
| | 138 | uint64 SathGUID = pInstance->GetData64(DATA_SATHROVARR); |
| | 139 | uint64 DoorGUID = pInstance->GetData64(DATA_GO_FORCEFIELD); |
| | 140 | } |
| | 141 | |
| | 142 | Unit *Sath = Unit::GetUnit(*m_creature,SathGUID); |
| | 143 | if(Sath) ((Creature*)Sath)->AI()->EnterEvadeMode(); |
| | 144 | |
| | 145 | GameObject *Door = GameObject::GetGameObject(*m_creature, DoorGUID); |
| | 146 | if(Door) Door->SetLootState(GO_JUST_DEACTIVATED); |
| | 147 | |
| | 148 | m_creature->setFaction(14); |
| | 149 | m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); |
| | 150 | m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); |
| | 151 | m_creature->SetVisibility(VISIBILITY_ON); |
| | 152 | m_creature->SetStandState(PLAYER_STATE_SLEEP); |
| | 153 | |
| | 154 | ArcaneBuffetTimer = 8000; |
| | 155 | FrostBreathTimer = 15000; |
| | 156 | WildMagicTimer = 10000; |
| | 157 | TailLashTimer = 25000; |
| | 158 | SpectralBlastTimer = 20000+(rand()%5000); |
| | 159 | CheckTimer = SpectralBlastTimer+20000; //after spectral blast |
| | 160 | |
| | 161 | TalkTimer = 0; |
| | 162 | TalkSequence = 0; |
| | 163 | isFriendly = false; |
| | 164 | isEnraged = false; |
| | 165 | isBanished = false; |
| | 166 | //m_creature->CastSpell(m_creature, AURA_SUNWELL_RADIANCE, true); |
| | 167 | } |
| | 168 | |
| | 169 | void DamageTaken(Unit *done_by, uint32 &damage) |
| | 170 | { |
| | 171 | if(damage >= m_creature->GetHealth() && done_by != m_creature) |
| | 172 | damage = 0; |
| 197 | | DoYell(SAY_KALECGOS_AGGRO, LANG_UNIVERSAL, NULL); |
| 198 | | DoPlaySoundToSet(m_creature, SOUND_KALECGOS_AGGRO); |
| 199 | | |
| | 177 | m_creature->SetStandState(PLAYER_STATE_NONE); |
| | 178 | DoYell(KALECGOS_SAY_AGGRO, LANG_UNIVERSAL,NULL); |
| | 179 | DoPlaySoundToSet(m_creature, KALECGOS_SOUND_AGGRO); |
| | 180 | GameObject *Door = GameObject::GetGameObject(*m_creature, DoorGUID); |
| | 181 | if(Door) Door->SetLootState(GO_ACTIVATED); |
| | 182 | DoZoneInCombat(); |
| | 183 | } |
| | 184 | |
| | 185 | void KilledUnit(Unit *victim) |
| | 186 | { |
| | 187 | switch(rand()%2) |
| | 188 | { |
| | 189 | case 0: |
| | 190 | DoYell(KALECGOS_SAY_KILL_1,LANG_UNIVERSAL,NULL); |
| | 191 | DoPlaySoundToSet(m_creature,KALECGOS_SOUND_KILL_1); |
| | 192 | break; |
| | 193 | case 1: |
| | 194 | DoYell(KALECGOS_SAY_KILL_2,LANG_UNIVERSAL,NULL); |
| | 195 | DoPlaySoundToSet(m_creature,KALECGOS_SOUND_KILL_2); |
| | 196 | break; |
| | 197 | } |
| | 198 | } |
| | 199 | |
| | 200 | void MovementInform(uint32 type,uint32 id) |
| | 201 | { |
| | 202 | m_creature->SetVisibility(VISIBILITY_OFF); |
| | 203 | if(isFriendly) |
| | 204 | m_creature->setDeathState(JUST_DIED); |
| | 205 | else |
| | 206 | { |
| | 207 | m_creature->GetMotionMaster()->MoveTargetedHome(); |
| | 208 | TalkTimer = 30000; |
| | 209 | } |
| | 210 | } |
| | 211 | |
| | 212 | void GoodEnding() |
| | 213 | { |
| | 214 | switch(TalkSequence) |
| | 215 | { |
| | 216 | case 1: |
| | 217 | m_creature->setFaction(35); |
| | 218 | DoCast(m_creature, SPELL_TRANSFORM_KALEC); |
| | 219 | TalkTimer = 1000; |
| | 220 | break; |
| | 221 | case 2: |
| | 222 | DoSay(KALECGOS_SAY_WIN, LANG_UNIVERSAL,NULL); |
| | 223 | DoPlaySoundToSet(m_creature, KALECGOS_SOUND_WIN); |
| | 224 | TalkTimer = 10000; |
| | 225 | break; |
| | 226 | case 3: |
| | 227 | m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); |
| | 228 | m_creature->GetMotionMaster()->Clear(); |
| | 229 | m_creature->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); |
| | 230 | TalkTimer = 600000; |
| | 231 | break; |
| | 232 | default: |
| | 233 | break; |
| | 234 | } |
| | 235 | } |
| | 236 | |
| | 237 | void BadEnding() |
| | 238 | { |
| | 239 | switch(TalkSequence) |
| | 240 | { |
| | 241 | case 1: |
| | 242 | DoYell(KALECGOS_SAY_FLY_AWAY,LANG_UNIVERSAL,NULL); |
| | 243 | DoPlaySoundToSet(m_creature,KALECGOS_SOUND_FLY_AWAY); |
| | 244 | TalkTimer = 3000; |
| | 245 | break; |
| | 246 | case 2: |
| | 247 | m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); |
| | 248 | m_creature->GetMotionMaster()->Clear(); |
| | 249 | m_creature->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); |
| | 250 | TalkTimer = 600000; |
| | 251 | break; |
| | 252 | case 3: |
| | 253 | EnterEvadeMode(); |
| | 254 | break; |
| | 255 | default: |
| | 256 | break; |
| | 257 | } |
| | 258 | } |
| | 259 | |
| | 260 | void UpdateAI(const uint32 diff); |
| | 261 | }; |
| | 262 | |
| | 263 | struct TRINITY_DLL_DECL boss_sathrovarrAI : public ScriptedAI |
| | 264 | { |
| | 265 | boss_sathrovarrAI(Creature *c) : ScriptedAI(c) |
| | 266 | { |
| | 267 | pInstance = ((ScriptedInstance*)c->GetInstanceData()); |
| | 268 | KalecGUID = 0; |
| | 269 | KalecgosGUID = 0; |
| | 270 | Reset(); |
| | 271 | } |
| | 272 | |
| | 273 | ScriptedInstance *pInstance; |
| | 274 | |
| | 275 | uint32 CorruptionStrikeTimer; |
| | 276 | uint32 AgonyCurseTimer; |
| | 277 | uint32 ShadowBoltTimer; |
| | 278 | uint32 CheckTimer; |
| | 279 | |
| | 280 | uint64 KalecGUID; |
| | 281 | uint64 KalecgosGUID; |
| | 282 | |
| | 283 | bool isEnraged; |
| | 284 | bool isBanished; |
| | 285 | |
| | 286 | void Reset() |
| | 287 | { |
| 201 | | pInstance->SetData(DATA_KALECGOS_EVENT, IN_PROGRESS); |
| 202 | | } |
| 203 | | |
| 204 | | void DamageTaken(Unit* done_by, uint32 &damage) |
| 205 | | { |
| 206 | | if(damage > m_creature->GetHealth() && done_by != m_creature) |
| 207 | | { |
| 208 | | if(!Uncorrupted) |
| | 289 | KalecgosGUID = pInstance->GetData64(DATA_KALECGOS_DRAGON); |
| | 290 | |
| | 291 | if(KalecGUID) |
| | 292 | { |
| | 293 | if(Unit* Kalec = Unit::GetUnit(*m_creature, KalecGUID)) |
| | 294 | Kalec->setDeathState(JUST_DIED); |
| | 295 | KalecGUID = 0; |
| | 296 | } |
| | 297 | |
| | 298 | ShadowBoltTimer = 7000 + rand()%3 * 1000; |
| | 299 | AgonyCurseTimer = 20000; |
| | 300 | CorruptionStrikeTimer = 13000; |
| | 301 | CheckTimer = 1000; |
| | 302 | isEnraged = false; |
| | 303 | isBanished = false; |
| | 304 | //m_creature->CastSpell(m_creature, AURA_SPECTRAL_INVISIBILITY, true); |
| | 305 | //m_creature->CastSpell(m_creature, AURA_SUNWELL_RADIANCE, true); |
| | 306 | //m_creature->CastSpell(m_creature, AURA_DEMONIC_VISUAL, true); |
| | 307 | } |
| | 308 | |
| | 309 | void Aggro(Unit* who) |
| | 310 | { |
| | 311 | Creature *Kalec = m_creature->SummonCreature(MOB_KALEC, m_creature->GetPositionX() + 10, m_creature->GetPositionY() + 5, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); |
| | 312 | if(Kalec) |
| | 313 | { |
| | 314 | KalecGUID = Kalec->GetGUID(); |
| | 315 | m_creature->CombatStart(Kalec); |
| | 316 | m_creature->AddThreat(Kalec, 100.0f); |
| | 317 | } |
| | 318 | DoYell(SATH_SAY_AGGRO, LANG_UNIVERSAL, NULL); |
| | 319 | DoPlaySoundToSet(m_creature, SATH_SOUND_AGGRO); |
| | 320 | } |
| | 321 | |
| | 322 | void DamageTaken(Unit *done_by, uint32 &damage) |
| | 323 | { |
| | 324 | if(damage >= m_creature->GetHealth() && done_by != m_creature) |
| | 325 | damage = 0; |
| | 326 | } |
| | 327 | |
| | 328 | void KilledUnit(Unit *target) |
| | 329 | { |
| | 330 | if(target->GetGUID() == KalecGUID) |
| | 331 | { |
| | 332 | TeleportAllPlayersBack(); |
| | 333 | if(Unit *Kalecgos = Unit::GetUnit(*m_creature, KalecgosGUID)) |
| 215 | | else |
| | 338 | EnterEvadeMode(); |
| | 339 | return; |
| | 340 | } |
| | 341 | switch(rand()%2) |
| | 342 | { |
| | 343 | case 0: |
| | 344 | DoYell(SATH_SAY_KILL_1,LANG_UNIVERSAL,NULL); |
| | 345 | DoPlaySoundToSet(m_creature,SATH_SOUND_KILL_1); |
| | 346 | break; |
| | 347 | case 1: |
| | 348 | DoYell(SATH_SAY_KILL_2,LANG_UNIVERSAL,NULL); |
| | 349 | DoPlaySoundToSet(m_creature,SATH_SOUND_KILL_2); |
| | 350 | break; |
| | 351 | } |
| | 352 | } |
| | 353 | |
| | 354 | void JustDied(Unit *victim) |
| | 355 | { |
| | 356 | DoYell(SATH_SAY_DIE, LANG_UNIVERSAL, NULL); |
| | 357 | DoPlaySoundToSet(m_creature, SATH_SOUND_DIE); |
| | 358 | m_creature->Relocate(m_creature->GetPositionX(), m_creature->GetPositionY(), DRAGON_REALM_Z, m_creature->GetOrientation()); |
| | 359 | TeleportAllPlayersBack(); |
| | 360 | if(Unit *Kalecgos = Unit::GetUnit(*m_creature, KalecgosGUID)) |
| | 361 | { |
| | 362 | ((boss_kalecgosAI*)((Creature*)Kalecgos)->AI())->TalkTimer = 1; |
| | 363 | ((boss_kalecgosAI*)((Creature*)Kalecgos)->AI())->isFriendly = true; |
| | 364 | } |
| | 365 | } |
| | 366 | |
| | 367 | void TeleportAllPlayersBack() |
| | 368 | { |
| | 369 | Map *map = m_creature->GetMap(); |
| | 370 | if(!map->IsDungeon()) return; |
| | 371 | InstanceMap::PlayerList const &PlayerList = ((InstanceMap*)map)->GetPlayers(); |
| | 372 | InstanceMap::PlayerList::const_iterator i; |
| | 373 | for (i = PlayerList.begin(); i != PlayerList.end(); ++i) |
| | 374 | { |
| | 375 | if((*i)->HasAura(AURA_SPECTRAL_REALM,0)) |
| | 376 | (*i)->RemoveAurasDueToSpell(AURA_SPECTRAL_REALM); |
| | 377 | } |
| | 378 | } |
| | 379 | |
| | 380 | void Enrage(); // demon and dragon should enrage at the same time |
| | 381 | |
| | 382 | void UpdateAI(const uint32 diff) |
| | 383 | { |
| | 384 | if (!m_creature->SelectHostilTarget() && !m_creature->getVictim()) |
| | 385 | return; |
| | 386 | |
| | 387 | if(CheckTimer < diff) |
| | 388 | { |
| | 389 | if(!isEnraged && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 10) |
| | 390 | Enrage(); |
| | 391 | |
| | 392 | if(!isBanished && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 1) |
| 220 | | } |
| 221 | | } |
| 222 | | |
| 223 | | void KilledUnit(Unit* victim) |
| 224 | | { |
| 225 | | switch(rand()%2) |
| 226 | | { |
| | 413 | CheckTimer = 1000; |
| | 414 | }else CheckTimer -= diff; |
| | 415 | |
| | 416 | if(ShadowBoltTimer < diff) |
| | 417 | { |
| | 418 | DoCast(m_creature, SPELL_SHADOW_BOLT); |
| | 419 | ShadowBoltTimer = 7000+(rand()%3000); |
| | 420 | }else ShadowBoltTimer -= diff; |
| | 421 | |
| | 422 | if(AgonyCurseTimer < diff) |
| | 423 | { |
| | 424 | Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); |
| | 425 | if(!target) target = m_creature->getVictim(); |
| | 426 | DoCast(target, SPELL_AGONY_CURSE); |
| | 427 | AgonyCurseTimer = 20000; |
| | 428 | }else AgonyCurseTimer -= diff; |
| | 429 | |
| | 430 | if(CorruptionStrikeTimer < diff) |
| | 431 | { |
| | 432 | DoCast(m_creature->getVictim(), SPELL_CORRUPTION_STRIKE); |
| | 433 | CorruptionStrikeTimer = 13000; |
| | 434 | }else CorruptionStrikeTimer -= diff; |
| | 435 | |
| | 436 | DoMeleeAttackIfReady(); |
| | 437 | } |
| | 438 | }; |
| | 439 | |
| | 440 | struct TRINITY_DLL_DECL boss_kalecAI : public ScriptedAI |
| | 441 | { |
| | 442 | ScriptedInstance *pInstance; |
| | 443 | |
| | 444 | uint32 RevitalizeTimer; |
| | 445 | uint32 HeroicStrikeTimer; |
| | 446 | uint32 YellTimer; |
| | 447 | uint32 YellSequence; |
| | 448 | |
| | 449 | uint64 SathGUID; |
| | 450 | |
| | 451 | bool isEnraged; // if demon is enraged |
| | 452 | |
| | 453 | boss_kalecAI(Creature *c) : ScriptedAI(c) |
| | 454 | { |
| | 455 | pInstance = ((ScriptedInstance*)c->GetInstanceData()); |
| | 456 | Reset(); |
| | 457 | } |
| | 458 | |
| | 459 | void Reset() |
| | 460 | { |
| | 461 | if(pInstance) |
| | 462 | SathGUID = pInstance->GetData64(DATA_SATHROVARR); |
| | 463 | |
| | 464 | RevitalizeTimer = 5000; |
| | 465 | HeroicStrikeTimer = 3000; |
| | 466 | YellTimer = 5000; |
| | 467 | YellSequence = 0; |
| | 468 | |
| | 469 | isEnraged = false; |
| | 470 | |
| | 471 | //m_creature->CastSpell(m_creature, AURA_SPECTRAL_INVISIBILITY, true); |
| | 472 | //m_creature->CastSpell(m_creature, AURA_SUNWELL_RADIANCE, true); |
| | 473 | } |
| | 474 | |
| | 475 | void Aggro(Unit* who) {} |
| | 476 | |
| | 477 | void DamageTaken(Unit *done_by, uint32 &damage) |
| | 478 | { |
| | 479 | if(done_by->GetGUID() != SathGUID) |
| | 480 | damage = 0; |
| | 481 | else if(isEnraged) |
| | 482 | damage *= 3; |
| | 483 | } |
| | 484 | |
| | 485 | void UpdateAI(const uint32 diff) |
| | 486 | { |
| | 487 | if(!m_creature->getVictim()) // only victim is Sath |
| | 488 | { |
| | 489 | EnterEvadeMode(); |
| | 490 | return; |
| | 491 | } |
| | 492 | |
| | 493 | if(YellTimer < diff) |
| | 494 | { |
| | 495 | switch(YellSequence) |
| | 496 | { |
| 235 | | } |
| 236 | | } |
| 237 | | |
| 238 | | void BeginOutro() |
| 239 | | { |
| 240 | | debug_log("SD2: KALEC: Beginning Outro"); |
| 241 | | |
| 242 | | if(!pInstance) |
| 243 | | { |
| 244 | | error_log(ERROR_INST_DATA); |
| | 510 | case 2: |
| | 511 | if((m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 10) |
| | 512 | { |
| | 513 | DoYell(KALEC_SAY_LOSING2, LANG_UNIVERSAL, NULL); |
| | 514 | DoPlaySoundToSet(m_creature, KALEC_SOUND_LOSING2); |
| | 515 | YellSequence++; |
| | 516 | } |
| | 517 | break; |
| | 518 | default: |
| | 519 | break; |
| | 520 | } |
| | 521 | YellTimer = 5000; |
| | 522 | } |
| | 523 | |
| | 524 | if(RevitalizeTimer < diff) |
| | 525 | { |
| | 526 | DoCast(m_creature, SPELL_REVITALIZE); |
| | 527 | RevitalizeTimer = 5000; |
| | 528 | }else RevitalizeTimer -= diff; |
| | 529 | |
| | 530 | if(HeroicStrikeTimer < diff) |
| | 531 | { |
| | 532 | DoCast(m_creature->getVictim(), SPELL_HEROIC_STRIKE); |
| | 533 | HeroicStrikeTimer = 2000; |
| | 534 | }else HeroicStrikeTimer -= diff; |
| | 535 | |
| | 536 | DoMeleeAttackIfReady(); |
| | 537 | } |
| | 538 | }; |
| | 539 | |
| | 540 | void boss_kalecgosAI::UpdateAI(const uint32 diff) |
| | 541 | { |
| | 542 | if(TalkTimer) |
| | 543 | { |
| | 544 | if(!TalkSequence) |
| | 545 | { |
| | 546 | m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); |
| | 547 | m_creature->InterruptNonMeleeSpells(true); |
| | 548 | m_creature->RemoveAllAuras(); |
| | 549 | m_creature->DeleteThreatList(); |
| | 550 | m_creature->CombatStop(); |
| | 551 | GameObject *Door = GameObject::GetGameObject(*m_creature, DoorGUID); |
| | 552 | if(Door) Door->SetLootState(GO_JUST_DEACTIVATED); |
| | 553 | TalkSequence++; |
| | 554 | } |
| | 555 | if(TalkTimer <= diff) |
| | 556 | { |
| | 557 | if(isFriendly) |
| | 558 | GoodEnding(); |
| | 559 | else |
| | 560 | BadEnding(); |
| | 561 | TalkSequence++; |
| | 562 | }else TalkTimer -= diff; |
| | 563 | } |
| | 564 | else |
| | 565 | { |
| | 566 | if (!m_creature->SelectHostilTarget() && !m_creature->getVictim()) |
| 246 | | } |
| 247 | | |
| 248 | | Unit* Sathrovarr = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_SATHROVARR)); |
| 249 | | if(Sathrovarr) |
| 250 | | { |
| 251 | | Sathrovarr->DealDamage(Sathrovarr, Sathrovarr->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); |
| 252 | | |
| 253 | | Sathrovarr->Relocate(KALECGOS_ARENA_X, KALECGOS_ARENA_Y, KALECGOS_ARENA_Z); |
| 254 | | Sathrovarr->SendMonsterMove(KALECGOS_ARENA_X, KALECGOS_ARENA_Y, KALECGOS_ARENA_Z, 0, 0, 0); |
| 255 | | } |
| 256 | | |
| 257 | | Creature* Kalec = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KALECGOS_HUMAN))); |
| 258 | | if(Kalec) |
| 259 | | { |
| 260 | | Kalec->DeleteThreatList(); |
| 261 | | Kalec->SetVisibility(VISIBILITY_OFF); |
| 262 | | } |
| 263 | | |
| 264 | | m_creature->GetMotionMaster()->MoveIdle(); |
| 265 | | m_creature->setFaction(35); |
| 266 | | } |
| 267 | | |
| 268 | | void MovementInform(uint32 type, uint32 id) |
| 269 | | { |
| 270 | | if(type != POINT_MOTION_TYPE) |
| 271 | | return; |
| 272 | | |
| 273 | | if(id) |
| 274 | | { |
| 275 | | if(pInstance) |
| | 568 | |
| | 569 | if(CheckTimer < diff) |
| | 570 | { |
| | 571 | if(!isEnraged && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 10) |
| 314 | | else |
| 315 | | BeginOutro(); |
| 316 | | } |
| 317 | | |
| 318 | | if(ExitTimer) |
| 319 | | if(ExitTimer <= diff) |
| 320 | | { |
| 321 | | debug_log("SD2: KALEC: Exiting the arena"); |
| 322 | | DoYell(SAY_KALEC_PLRWIN, LANG_UNIVERSAL, NULL); |
| 323 | | DoPlaySoundToSet(m_creature, SOUND_KALEC_PLRWIN); |
| 324 | | m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); |
| 325 | | float x, y, z; |
| 326 | | float iniX, iniY, iniZ; |
| 327 | | m_creature->GetPosition(iniX, iniY, iniZ); |
| 328 | | m_creature->GetRandomPoint(iniX, iniY, iniZ, 30, x, y, z); |
| 329 | | z = 70; |
| 330 | | m_creature->GetMotionMaster()->MovePoint(1, x, y, z); |
| 331 | | }else ExitTimer -= diff; |
| 332 | | |
| 333 | | if(!LockedArena) |
| 334 | | if(ForceFieldTimer < diff) |
| 335 | | { |
| 336 | | if(pInstance) |
| 337 | | { |
| 338 | | GameObject* ForceField = GameObject::GetGameObject((*m_creature), pInstance->GetData64(DATA_GO_FORCEFIELD)); |
| 339 | | if(ForceField) |
| 340 | | ForceField->SetUInt32Value(GAMEOBJECT_STATE, 0); |
| 341 | | |
| 342 | | LockedArena = true; |
| 343 | | }else error_log(ERROR_INST_DATA); |
| 344 | | }else ForceFieldTimer -= diff; |
| | 595 | CheckTimer = 1000; //every 1 sec we check this |
| | 596 | }else CheckTimer -= diff; |
| 385 | | if(SpectralTeleportTimer < diff) |
| 386 | | { |
| 387 | | if(TeleportTargetGUID) |
| 388 | | { |
| 389 | | Unit* pUnit = Unit::GetUnit((*m_creature), TeleportTargetGUID); |
| 390 | | if(pUnit) |
| 391 | | { |
| 392 | | pUnit->CastSpell(pUnit, SPELL_SPECTRAL_BLAST, true); |
| 393 | | TeleportToInnerVeil((Player*)pUnit); |
| 394 | | } |
| 395 | | else error_log(ERROR_MISSING_TELEPORT_GUID); |
| 396 | | } |
| 397 | | else error_log(ERROR_MISSING_TELEPORT_GUID); |
| 398 | | |
| 399 | | m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID()); |
| 400 | | TeleportTargetGUID = 0; |
| 401 | | SpectralTeleportTimer = SpectralBlastTimer + 2000; |
| 402 | | |
| 403 | | }else SpectralTeleportTimer -= diff; |
| 404 | | |
| 405 | | if(!Banished) DoMeleeAttackIfReady(); |
| 406 | | } |
| 407 | | }; |
| 408 | | |
| 409 | | struct TRINITY_DLL_DECL boss_sathrovarrAI : public ScriptedAI |
| 410 | | { |
| 411 | | boss_sathrovarrAI(Creature* c) : ScriptedAI(c) |
| 412 | | { |
| 413 | | pInstance = ((ScriptedInstance*)c->GetInstanceData()); |
| 414 | | Reset(); |
| 415 | | } |
| 416 | | |
| 417 | | ScriptedInstance* pInstance; |
| 418 | | |
| 419 | | uint32 CorruptingStrikeTimer; |
| 420 | | uint32 CurseOfBoundlessAgonyTimer; |
| 421 | | uint32 ShadowBoltVolleyTimer; |
| 422 | | bool Banished; |
| 423 | | bool Enraged; |
| 424 | | |
| 425 | | void Reset() |
| 426 | | { |
| 427 | | // FIXME: Timers |
| 428 | | CorruptingStrikeTimer = 5000; |
| 429 | | CurseOfBoundlessAgonyTimer = 15000; |
| 430 | | ShadowBoltVolleyTimer = 10000; |
| 431 | | |
| 432 | | Banished = false; |
| 433 | | Enraged = false; |
| 434 | | |
| 435 | | DoCast(m_creature, SPELL_SPECTRAL_REALM, true); |
| 436 | | } |
| 437 | | |
| 438 | | void Aggro(Unit* who) |
| 439 | | { |
| 440 | | DoYell(SAY_SATH_AGGRO, LANG_UNIVERSAL, NULL); |
| 441 | | DoPlaySoundToSet(m_creature, SOUND_SATH_AGGRO); |
| 442 | | |
| 443 | | Creature* Kalec = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KALECGOS_HUMAN))); |
| 444 | | if(Kalec) |
| 445 | | { |
| 446 | | m_creature->AddThreat(Kalec, 10000000.0f); |
| 447 | | Kalec->AddThreat(m_creature, 10000000.0f); |
| 448 | | } |
| 449 | | } |
| 450 | | |
| 451 | | void DamageTaken(Unit* done_by, uint32 &damage) |
| 452 | | { |
| 453 | | if(damage > m_creature->GetHealth()) |
| 454 | | { |
| 455 | | damage = 0; |
| 456 | | DoCast(m_creature, SPELL_BANISH, true); |
| 457 | | Banished = true; |
| 458 | | |
| 459 | | DoYell(SAY_SATH_DEATH, LANG_UNIVERSAL, NULL); |
| 460 | | DoPlaySoundToSet(m_creature, SOUND_SATH_DEATH); |
| 461 | | |
| 462 | | if(!pInstance) |
| 463 | | { |
| 464 | | error_log(ERROR_INST_DATA); |
| 465 | | return; |
| 466 | | } |
| 467 | | |
| 468 | | pInstance->SetData(DATA_SET_SPECTRAL_CHECK, 5000); |
| 469 | | |
| 470 | | Creature* Kalecgos = ((Creature*)Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KALECGOS_DRAGON))); |
| 471 | | if(Kalecgos) |
| 472 | | { |
| 473 | | ((boss_kalecgosAI*)Kalecgos->AI())->Checked = false; |
| 474 | | ((boss_kalecgosAI*)Kalecgos->AI())->Uncorrupted = true; |
| 475 | | } |
| 476 | | else error_log(ERROR_KALECGOS_NOT_FOUND); |
| 477 | | } |
| 478 | | } |
| 479 | | |
| 480 | | void KilledUnit(Unit* victim) |
| 481 | | { |
| 482 | | switch(rand()%2) |
| 483 | | { |
| 484 | | case 0: |
| 485 | | DoYell(SAY_SATH_SLAY1,LANG_UNIVERSAL,NULL); |
| 486 | | DoPlaySoundToSet(m_creature,SOUND_SATH_SLAY1); |
| 487 | | break; |
| 488 | | case 1: |
| 489 | | DoYell(SAY_SATH_SLAY2,LANG_UNIVERSAL,NULL); |
| 490 | | DoPlaySoundToSet(m_creature,SOUND_SATH_SLAY2); |
| 491 | | break; |
| 492 | | } |
| 493 | | } |
| 494 | | |
| 495 | | void UpdateAI(const uint32 diff) |
| 496 | | { |
| 497 | | if(!m_creature->getVictim() || !m_creature->SelectHostilTarget() || Banished) |
| 498 | | return; |
| 499 | | |
| 500 | | if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !Enraged) |
| 501 | | { |
| 502 | | Unit* Kalecgos = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_KALECGOS_DRAGON)); |
| 503 | | if(Kalecgos) |
| 504 | | Kalecgos->CastSpell(Kalecgos, SPELL_CRAZED_RAGE, true); |
| 505 | | DoCast(m_creature, SPELL_CRAZED_RAGE, true); |
| 506 | | Enraged = true; |
| 507 | | } |
| 508 | | |
| 509 | | if(CorruptingStrikeTimer < diff) |
| 510 | | { |
| 511 | | if(rand()%2 == 0) |
| 512 | | { |
| 513 | | DoYell(SAY_SATH_SPELL2, LANG_UNIVERSAL, NULL); |
| 514 | | DoPlaySoundToSet(m_creature, SOUND_SATH_SPELL2); |
| 515 | | } |
| 516 | | DoCast(m_creature->getVictim(), SPELL_CORRUPTING_STRIKE); |
| 517 | | CorruptingStrikeTimer = 13000; |
| 518 | | }else CorruptingStrikeTimer -= diff; |
| 519 | | |
| 520 | | if(CurseOfBoundlessAgonyTimer < diff) |
| 521 | | { |
| 522 | | DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_CURSE_OF_BOUNDLESS_AGONY); |
| 523 | | CurseOfBoundlessAgonyTimer = 35000; |
| 524 | | DoCast(m_creature, SPELL_SPECTRAL_REALM, true); |
| 525 | | }else CurseOfBoundlessAgonyTimer -= diff; |
| 526 | | |
| 527 | | if(ShadowBoltVolleyTimer < diff) |
| 528 | | { |
| 529 | | if(rand()%2 == 0) |
| 530 | | { |
| 531 | | DoYell(SAY_SATH_SPELL1, LANG_UNIVERSAL, NULL); |
| 532 | | DoPlaySoundToSet(m_creature, SOUND_SATH_SPELL1); |
| 533 | | } |
| 534 | | DoCast(m_creature->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); |
| 535 | | ShadowBoltVolleyTimer = 15000; |
| 536 | | }else ShadowBoltVolleyTimer -= diff; |
| 537 | | |
| 540 | | }; |
| 541 | | |
| 542 | | struct TRINITY_DLL_DECL boss_kalecAI : public ScriptedAI |
| 543 | | { |
| 544 | | boss_kalecAI(Creature* c) : ScriptedAI(c) |
| 545 | | { |
| 546 | | pInstance = ((ScriptedInstance*)c->GetInstanceData()); |
| 547 | | Reset(); |
| 548 | | } |
| 549 | | |
| 550 | | ScriptedInstance *pInstance; |
| 551 | | |
| 552 | | uint32 RevitalizeTimer; |
| 553 | | uint32 HeroicStrikeTimer; |
| 554 | | |
| 555 | | bool HasYelled10Percent; |
| 556 | | bool HasYelled20Percent; |
| 557 | | |
| 558 | | void Reset() |
| 559 | | { |
| 560 | | //TODO: Times! |
| 561 | | RevitalizeTimer = 30000; |
| 562 | | HeroicStrikeTimer = 8000; |
| 563 | | |
| 564 | | HasYelled10Percent = false; |
| 565 | | HasYelled20Percent = false; |
| 566 | | |
| 567 | | DoCast(m_creature, SPELL_SPECTRAL_REALM, true); |
| 568 | | } |
| 569 | | |
| 570 | | void Aggro(Unit* who) |
| 571 | | { |
| 572 | | DoYell(SAY_KALEC_AGGRO, LANG_UNIVERSAL, NULL); |
| 573 | | DoPlaySoundToSet(m_creature, SOUND_KALEC_AGGRO); |
| 574 | | } |
| 575 | | |
| 576 | | void JustDied(Unit* killer) |
| 577 | | { |
| 578 | | // Whatever happens when Kalec (Half-elf) dies |
| 579 | | } |
| 580 | | |
| 581 | | void UpdateAI(const uint32 diff) |
| 582 | | { |
| 583 | | if(!m_creature->getVictim() || !m_creature->SelectHostilTarget()) |
| 584 | | return; |
| 585 | | |
| 586 | | if(RevitalizeTimer < diff) |
| 587 | | { |
| 588 | | if(pInstance) |
| 589 | | { |
| 590 | | Unit* pUnit = Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_RANDOM_SPECTRAL_PLAYER)); |
| 591 | | if(pUnit) |
| 592 | | DoCast(pUnit, SPELL_REVITALIZE); |
| 593 | | RevitalizeTimer = 30000; |
| 594 | | } |
| 595 | | }else RevitalizeTimer -= diff; |
| 596 | | |
| 597 | | if(HeroicStrikeTimer < diff) |
| 598 | | { |
| 599 | | DoCast(m_creature->getVictim(), SPELL_HEROIC_STRIKE); |
| 600 | | HeroicStrikeTimer = 30000; |
| 601 | | }else HeroicStrikeTimer -= diff; |
| 602 | | |
| 603 | | if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 20) && !HasYelled20Percent) |
| 604 | | { |
| 605 | | DoYell(SAY_KALEC_NEAR_DEATH, LANG_UNIVERSAL, NULL); |
| 606 | | DoPlaySoundToSet(m_creature, SOUND_KALEC_NEAR_DEATH); |
| 607 | | HasYelled20Percent = true; |
| 608 | | } |
| 609 | | |
| 610 | | if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 10) && !HasYelled10Percent) |
| 611 | | { |
| 612 | | DoYell(SAY_KALEC_NEAR_DEATH2, LANG_UNIVERSAL, NULL); |
| 613 | | DoPlaySoundToSet(m_creature, SOUND_KALEC_NEAR_DEATH2); |
| 614 | | HasYelled10Percent = true; |
| 615 | | } |
| 616 | | } |
| 617 | | }; |
| 618 | | |
| 619 | | CreatureAI* GetAI_boss_kalecgos(Creature* c) |
| 620 | | { |
| 621 | | return new boss_kalecgosAI(c); |