diff options
author | megamage <none@none> | 2009-02-23 17:04:15 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-02-23 17:04:15 -0600 |
commit | 5fe7b48037c7892c24f5c2f9ea1d18c424ac85e9 (patch) | |
tree | 0650745d74d6b63003429de0dff65632699d71f3 /src | |
parent | befa36f8b91ab2a08719ff4d1df0433d9ac604b1 (diff) | |
parent | de947abd068ad603ca202ae53ffeeefed944681f (diff) |
*Merge.
--HG--
branch : trunk
Diffstat (limited to 'src')
25 files changed, 1716 insertions, 1677 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index db5beb64ec8..efb6ef36fa2 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -684,7 +684,7 @@ void ScriptedAI::DoZoneInCombat(Unit* pUnit) for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if (Player* i_pl = i->getSource()) - if (!i_pl->isAlive()) + if (i_pl->isAlive()) { pUnit->SetInCombatWith(i_pl); i_pl->SetInCombatWith(pUnit); @@ -726,6 +726,12 @@ void ScriptedAI::DoModifyThreatPercent(Unit *pUnit, int32 pct) m_creature->getThreatManager().modifyThreatPercent(pUnit, pct); } +void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time) +{ + m_creature->Relocate(x,y,z); + m_creature->SendMonsterMove(x, y, z, time); +} + void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o) { if(!pUnit || pUnit->GetTypeId() != TYPEID_PLAYER) diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h index 5639ad0f1ff..03039fd709e 100644 --- a/src/bindings/scripts/include/sc_creature.h +++ b/src/bindings/scripts/include/sc_creature.h @@ -150,6 +150,8 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI float DoGetThreat(Unit *u); void DoModifyThreatPercent(Unit *pUnit, int32 pct); + void DoTeleportTo(float x, float y, float z, uint32 time = 0); + //Teleports a player without dropping threat (only teleports to same map) void DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o); void DoTeleportAll(float x, float y, float z, float o); diff --git a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp index 53953e04d51..3b017c48a69 100644 --- a/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp +++ b/src/bindings/scripts/scripts/zone/aunchindoun/sethekk_halls/boss_tailonking_ikiss.cpp @@ -192,8 +192,7 @@ struct TRINITY_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI float Y = target->GetPositionY(); float Z = target->GetPositionZ(); - m_creature->Relocate(X,Y,Z); - m_creature->SendMonsterMove(X, Y, Z, 0, 0, 0); + DoTeleportTo(X,Y,Z); DoCast(target,SPELL_BLINK_TELEPORT); Blink = true; diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp index a22935d7468..6592e3783f4 100644 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp @@ -1470,8 +1470,7 @@ struct TRINITY_DLL_DECL boss_maievAI : public ScriptedAI m_creature->AttackStop(); m_creature->InterruptNonMeleeSpells(false); m_creature->GetMotionMaster()->Clear(false); - m_creature->Relocate(x, y, z); - m_creature->SendMonsterMove(x, y, z, 0, 0, 0); + DoTeleportTo(x, y, z); DoCast(m_creature, SPELL_TELEPORT_VISUAL, true); } @@ -1947,7 +1946,7 @@ void boss_illidan_stormrageAI::HandleTalkSequence() Akama->GetMotionMaster()->Clear(false); //Akama->GetMotionMaster()->MoveIdle(); Akama->Relocate(x, y, z); - Akama->SendMonsterMove(x, y, z, 0, 0, 0);//Illidan must not die until Akama arrives. + Akama->SendMonsterMove(x, y, z, 0);//Illidan must not die until Akama arrives. Akama->GetMotionMaster()->MoveChase(m_creature); } } diff --git a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp index ad437f24275..b0b8135396e 100644 --- a/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp +++ b/src/bindings/scripts/scripts/zone/blackwing_lair/boss_victor_nefarius.cpp @@ -306,8 +306,7 @@ struct TRINITY_DLL_DECL boss_victor_nefariusAI : public ScriptedAI DoCast(m_creature,8149); //Teleport self to a hiding spot (this causes errors in the Trinity 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); + DoTeleportTo(HIDE_X,HIDE_Y,HIDE_Z); m_creature->addUnitState(UNIT_STAT_FLEEING); //Spawn nef and have him attack a random target diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp index 962d05e6c87..9d66533972d 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp @@ -402,8 +402,7 @@ struct TRINITY_DLL_DECL boss_lady_vashjAI : public ScriptedAI Phase = 2; m_creature->GetMotionMaster()->Clear(); - m_creature->Relocate(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - m_creature->SendMonsterMove(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 0, 0, 0); + DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); Creature *pCreature; for(uint8 i = 0; i < 4; i++) diff --git a/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp b/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp index 32612e158f5..e0ee20518b0 100644 --- a/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp +++ b/src/bindings/scripts/scripts/zone/molten_core/boss_shazzrah.cpp @@ -95,10 +95,12 @@ struct TRINITY_DLL_DECL boss_shazzrahAI : public ScriptedAI Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0); - m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0); - m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0,true,0); + if(target) + { + DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); DoCast(target,SPELL_ARCANEEXPLOSION); DoResetThreat(); + } Blink_Timer = 45000; }else Blink_Timer -= diff; diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp index b60da3d7693..8fadb5192f9 100644 --- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp @@ -1,1610 +1,1608 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- * 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
- */
-
-/* ScriptData
-SDName: boss_Kaelthas
-SD%Complete: 60
-SDComment: Mind Control, Reset Event if Weapons despawn/reset
-SDCategory: Tempest Keep, The Eye
-EndScriptData */
-
-#include "precompiled.h"
-#include "def_the_eye.h"
-#include "WorldPacket.h"
-
- //kael'thas Speech
-#define SAY_INTRO -1550016
-#define SAY_INTRO_CAPERNIAN -1550017
-#define SAY_INTRO_TELONICUS -1550018
-#define SAY_INTRO_THALADRED -1550019
-#define SAY_INTRO_SANGUINAR -1550020
-#define SAY_PHASE2_WEAPON -1550021
-#define SAY_PHASE3_ADVANCE -1550022
-#define SAY_PHASE4_INTRO2 -1550023
-#define SAY_PHASE5_NUTS -1550024
-#define SAY_SLAY1 -1550025
-#define SAY_SLAY2 -1550026
-#define SAY_SLAY3 -1550027
-#define SAY_MINDCONTROL1 -1550028
-#define SAY_MINDCONTROL2 -1550029
-#define SAY_GRAVITYLAPSE1 -1550030
-#define SAY_GRAVITYLAPSE2 -1550031
-#define SAY_SUMMON_PHOENIX1 -1550032
-#define SAY_SUMMON_PHOENIX2 -1550033
-#define SAY_DEATH -1550034
-
-//Thaladred the Darkener speech
-#define SAY_THALADRED_AGGRO -1550035
-#define SAY_THALADRED_DEATH -1550036
-#define EMOTE_THALADRED_GAZE -1550037
-
-//Lord Sanguinar speech
-#define SAY_SANGUINAR_AGGRO -1550038
-#define SAY_SANGUINAR_DEATH -1550039
-
-//Grand Astromancer Capernian speech
-#define SAY_CAPERNIAN_AGGRO -1550040
-#define SAY_CAPERNIAN_DEATH -1550041
-
-//Master Engineer Telonicus speech
-#define SAY_TELONICUS_AGGRO -1550042
-#define SAY_TELONICUS_DEATH -1550043
-
-//Phase 2 spells (Not used)
-#define SPELL_SUMMON_WEAPONS 36976
-#define SPELL_SUMMON_WEAPONA 36958
-#define SPELL_SUMMON_WEAPONB 36959
-#define SPELL_SUMMON_WEAPONC 36960
-#define SPELL_SUMMON_WEAPOND 36961
-#define SPELL_SUMMON_WEAPONE 36962
-#define SPELL_SUMMON_WEAPONF 36963
-#define SPELL_SUMMON_WEAPONG 36964
-#define SPELL_RES_VISUAL 24171
-#define SPELL_WEAPON_SPAWN 41236
-
-//Phase 4 spells
-#define SPELL_FIREBALL 36805
-#define SPELL_PYROBLAST 36819
-#define SPELL_FLAME_STRIKE 36735
-#define SPELL_FLAME_STRIKE_VIS 36730
-#define SPELL_FLAME_STRIKE_DMG 36731
-#define SPELL_ARCANE_DISRUPTION 36834
-#define SPELL_SHOCK_BARRIER 36815
-#define SPELL_SUMMON_PHOENIX 36723
-#define SPELL_MIND_CONTROL 32830
-
-//Phase 5 spells
-#define SPELL_EXPLODE 36092
-#define SPELL_FULLPOWER 36187
-#define SPELL_KNOCKBACK 11027
-#define SPELL_GRAVITY_LAPSE 34480
-#define SPELL_GRAVITY_LAPSE_AURA 39432
-#define SPELL_NETHER_BEAM 35873
-
-//Thaladred the Darkener spells
-#define SPELL_PSYCHIC_BLOW 10689
-#define SPELL_SILENCE 30225
-
-//Lord Sanguinar spells
-#define SPELL_BELLOWING_ROAR 40636
-
-//Grand Astromancer Capernian spells
-#define CAPERNIAN_DISTANCE 20 //she casts away from the target
-#define SPELL_CAPERNIAN_FIREBALL 36971
-#define SPELL_CONFLAGRATION 37018
-#define SPELL_ARCANE_EXPLOSION 36970
-
-//Master Engineer Telonicus spells
-#define SPELL_BOMB 37036
-#define SPELL_REMOTE_TOY 37027
-
-//Nether Vapor spell
-#define SPELL_NETHER_VAPOR 35859
-
-//Phoenix spell
-#define SPELL_BURN 36720
-#define SPELL_EMBER_BLAST 34341
-#define SPELL_REBIRTH 41587
-
-//Creature IDs
-#define PHOENIX 21362
-#define PHOENIX_EGG 21364
-
-//Phoenix egg and phoenix model
-#define PHOENIX_MODEL 19682
-#define PHOENIX_EGG_MODEL 20245
-
-//weapon id + position
-float KaelthasWeapons[7][5] =
-{
- {21270, 794.38, 15, 48.72, 2.9}, //[Cosmic Infuser]
- {21269, 785.47, 12.12, 48.72, 3.14}, //[Devastation]
- {21271, 781.25, 4.39, 48.72, 3.14}, //[Infinity Blade]
- {21273, 777.38, -0.81, 48.72, 3.06}, //[Phaseshift Bulwark]
- {21274, 781.48, -6.08, 48.72, 3.9}, //[Staff of Disintegration]
- {21272, 785.42, -13.59, 48.72, 3.4}, //[Warp Slicer]
- {21268, 793.06, -16.61, 48.72, 3.10} //[Netherstrand Longbow]
-};
-
-#define GRAVITY_X 795.0f
-#define GRAVITY_Y 0.0f
-#define GRAVITY_Z 70.0f
-
-#define TIME_PHASE_2_3 120000
-#define TIME_PHASE_3_4 120000
-
-#define KAEL_VISIBLE_RANGE 50.0f
-
-//Base AI for Advisors
-struct TRINITY_DLL_DECL advisorbase_ai : public ScriptedAI
-{
- ScriptedInstance* pInstance;
- bool FakeDeath;
- uint32 DelayRes_Timer;
- uint64 DelayRes_Target;
-
- advisorbase_ai(Creature *c) : ScriptedAI(c)
- {
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
- Reset();
- }
-
- void MoveInLineOfSight(Unit *who)
- {
- if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- ScriptedAI::MoveInLineOfSight(who);
- }
-
- void AttackStart(Unit* who)
- {
- if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- ScriptedAI::AttackStart(who);
- }
-
- void Reset()
- {
- FakeDeath = false;
- DelayRes_Timer = 0;
- DelayRes_Target = 0;
-
- m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
-
- //reset encounter
- if(pInstance && (pInstance->GetData(DATA_KAELTHASEVENT) == 1 || pInstance->GetData(DATA_KAELTHASEVENT) == 3))
- {
- Creature *Kaelthas = NULL;
- Kaelthas = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KAELTHAS)));
-
- if(Kaelthas)
- Kaelthas->AI()->EnterEvadeMode();
- }
- }
-
- void Revive(Unit* Target)
- {
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->SetHealth(m_creature->GetMaxHealth());
- m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- DoCast(m_creature, SPELL_RES_VISUAL, false);
- DelayRes_Timer = 2000;
- }
-
- void DamageTaken(Unit* pKiller, uint32 &damage)
- {
- if (damage < m_creature->GetHealth())
- return;
-
- //Prevent glitch if in fake death
- if (FakeDeath)
- {
- damage = 0;
- return;
- }
- //Don't really die in phase 1 & 3, only die after that
- if(pInstance && pInstance->GetData(DATA_KAELTHASEVENT) != 0)
- {
- //prevent death
- damage = 0;
- FakeDeath = true;
-
- m_creature->InterruptNonMeleeSpells(false);
- m_creature->SetHealth(0);
- m_creature->StopMoving();
- m_creature->ClearComboPointHolders();
- m_creature->RemoveAllAurasOnDeath();
- m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
- m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->ClearAllReactives();
- m_creature->SetUInt64Value(UNIT_FIELD_TARGET,0);
- m_creature->GetMotionMaster()->Clear();
- m_creature->GetMotionMaster()->MoveIdle();
- m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD);
-
- if (pInstance->GetData(DATA_KAELTHASEVENT) == 3)
- JustDied(pKiller);
- }
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (DelayRes_Timer)
- {
- if (DelayRes_Timer <= diff)
- {
- DelayRes_Timer = 0;
- FakeDeath = false;
-
- Unit* Target = Unit::GetUnit((*m_creature), DelayRes_Target);
- if (!Target)
- Target = m_creature->getVictim();
- DoResetThreat();
- AttackStart(Target);
- m_creature->GetMotionMaster()->Clear();
- m_creature->GetMotionMaster()->MoveChase(Target);
- m_creature->AddThreat(Target, 0.0f);
- }else DelayRes_Timer -= diff;
- }
- }
-};
-
-//Kael'thas AI
-struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI
-{
- boss_kaelthasAI(Creature *c) : ScriptedAI(c)
- {
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
- AdvisorGuid[0] = 0;
- AdvisorGuid[1] = 0;
- AdvisorGuid[2] = 0;
- AdvisorGuid[3] = 0;
- Reset();
- }
-
- ScriptedInstance* pInstance;
-
- std::list<uint64> Phoenix;
-
- uint32 Fireball_Timer;
- uint32 ArcaneDisruption_Timer;
- uint32 Phoenix_Timer;
- uint32 ShockBarrier_Timer;
- uint32 GravityLapse_Timer;
- uint32 GravityLapse_Phase;
- uint32 NetherBeam_Timer;
- uint32 NetherVapor_Timer;
- uint32 FlameStrike_Timer;
- uint32 MindControl_Timer;
- uint32 Check_Timer;
- uint32 Phase;
- uint32 PhaseSubphase; //generic
- uint32 Phase_Timer; //generic timer
- uint32 PyrosCasted;
-
- bool InGravityLapse;
- bool IsCastingFireball;
- bool ChainPyros;
-
- uint64 AdvisorGuid[4];
- uint64 WeaponGuid[7];
-
- void DeleteLegs()
- {
- InstanceMap::PlayerList const &playerliste = ((InstanceMap*)m_creature->GetMap())->GetPlayers();
- InstanceMap::PlayerList::const_iterator it;
-
- Map::PlayerList const &PlayerList = ((InstanceMap*)m_creature->GetMap())->GetPlayers();
- for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- Player* i_pl = i->getSource();
- i_pl->DestroyItemCount(30312, 1, true);
- i_pl->DestroyItemCount(30311, 1, true);
- i_pl->DestroyItemCount(30317, 1, true);
- i_pl->DestroyItemCount(30316, 1, true);
- i_pl->DestroyItemCount(30313, 1, true);
- i_pl->DestroyItemCount(30314, 1, true);
- i_pl->DestroyItemCount(30318, 1, true);
- i_pl->DestroyItemCount(30319, 1, true);
- i_pl->DestroyItemCount(30320, 1, true);
- }
- if(pInstance) {
- for(uint32 i = 0; i < 7; i++) {
- Creature* weapon = (Creature*)(Unit::GetUnit((*m_creature), WeaponGuid[i]));;
- delete weapon;
- }
- }
- }
-
- void CleanPhoenix()
- {
- CellPair pair(Trinity::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
- Cell cell(pair);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- std::list<Creature*> PhoenixList;
-
- Trinity::AllCreaturesOfEntryInRange check(m_creature, PHOENIX, 50);
- Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, PhoenixList, check);
- TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> visitor(searcher);
-
- CellLock<GridReadGuard> cell_lock(cell, pair);
- cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap()));
-
- if(!PhoenixList.empty())
- {
- for(std::list<Creature*>::iterator itr = PhoenixList.begin(); itr != PhoenixList.end(); ++itr)
- {
- (*itr)->RemoveFromWorld();
- }
- }
- }
-
- void Reset()
- {
- Fireball_Timer = 5000+rand()%10000;
- ArcaneDisruption_Timer = 45000;
- MindControl_Timer = 40000;
- Phoenix_Timer = 50000;
- ShockBarrier_Timer = 60000;
- FlameStrike_Timer = 30000;
- GravityLapse_Timer = 20000;
- GravityLapse_Phase = 0;
- NetherBeam_Timer = 8000;
- NetherVapor_Timer = 10000;
- Check_Timer = 4000;
- PyrosCasted = 0;
- Phase = 0;
- InGravityLapse = false;
- IsCastingFireball = false;
- ChainPyros = false;
-
- if(InCombat)
- PrepareAdvisors();
-
- DeleteLegs();
- CleanPhoenix();
-
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
- m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
-
-
- if(pInstance)
- pInstance->SetData(DATA_KAELTHASEVENT, NOT_STARTED);
- }
-
- void PrepareAdvisors()
- {
- Creature *pCreature;
- for(uint8 i = 0; i < 4; ++i)
- {
- pCreature = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i]));
- if(pCreature)
- {
- pCreature->Respawn();
- pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- pCreature->setFaction(m_creature->getFaction());
- pCreature->AI()->EnterEvadeMode();
- }
- }
- }
-
- void StartEvent()
- {
- if(!pInstance)
- return;
-
- AdvisorGuid[0] = pInstance->GetData64(DATA_THALADREDTHEDARKENER);
- AdvisorGuid[1] = pInstance->GetData64(DATA_LORDSANGUINAR);
- AdvisorGuid[2] = pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN);
- AdvisorGuid[3] = pInstance->GetData64(DATA_MASTERENGINEERTELONICUS);
- m_creature->addUnitState(UNIT_STAT_STUNNED);
-
- if(!AdvisorGuid[0] || !AdvisorGuid[1] || !AdvisorGuid[2] || !AdvisorGuid[3])
- {
- error_log("SD2: Kael'Thas One or more advisors missing, Skipping Phases 1-3");
- DoYell("SD2: Kael'Thas One or more advisors missing, Skipping Phases 1-3", LANG_UNIVERSAL, NULL);
-
- DoScriptText(SAY_PHASE4_INTRO2, m_creature);
- Phase = 4;
-
- pInstance->SetData(DATA_KAELTHASEVENT, 4);
-
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
- Unit *target = NULL;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- if(target)
- AttackStart(target);
- }
- else
- {
- PrepareAdvisors();
-
- DoScriptText(SAY_INTRO, m_creature);
-
- pInstance->SetData(DATA_KAELTHASEVENT, IN_PROGRESS);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
- PhaseSubphase = 0;
- Phase_Timer = 23000;
- Phase = 1;
- }
- }
-
- void KilledUnit()
- {
- switch(rand()%3)
- {
- case 0: DoScriptText(SAY_SLAY1, m_creature); break;
- case 1: DoScriptText(SAY_SLAY2, m_creature); break;
- case 2: DoScriptText(SAY_SLAY3, m_creature); break;
- }
- }
-
- void JustSummoned(Creature* summoned)
- {
- if(summoned->GetEntry() == PHOENIX)
- {
- summoned->setFaction(m_creature->getFaction());
- Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- summoned->AI()->AttackStart(target);
- }
- }
-
- void JustDied(Unit* Killer)
- {
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
- DoScriptText(SAY_DEATH, m_creature);
-
- DeleteLegs();
-
- if(pInstance)
- pInstance->SetData(DATA_KAELTHASEVENT, DONE);
-
- Creature *pCreature;
- for(uint8 i = 0; i < 4; ++i)
- {
- pCreature = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i]));
- if(pCreature)
- {
- pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- }
- }
- }
-
- void Aggro(Unit *who)
- {
- if (pInstance && !pInstance->GetData(DATA_KAELTHASEVENT) && !Phase)
- StartEvent();
- }
-
- void MoveInLineOfSight(Unit *who)
- {
- if (!m_creature->getVictim() && who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who))
- {
- if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
- return;
-
- float attackRadius = m_creature->GetAttackDistance(who);
- if (Phase >= 4 && m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who))
- {
- AttackStart(who);
- }
- else if(who->isAlive())
- {
- if (pInstance && !pInstance->GetData(DATA_KAELTHASEVENT) && !Phase && m_creature->IsWithinDistInMap(who, 60.0f))
- StartEvent();
-
- //add to the threat list, so we can use SelectTarget
- m_creature->AddThreat(who,0.0f);
- }
- }
- }
-
- void UpdateAI(const uint32 diff)
- {
- //Phase 1
- switch (Phase)
- {
- case 1:
- {
- Unit *target;
- Creature* Advisor;
-
- //Subphase switch
- switch(PhaseSubphase)
- {
- //Subphase 1 - Start
- case 0:
- if(Phase_Timer < diff)
- {
- DoScriptText(SAY_INTRO_THALADRED, m_creature);
-
- //start advisor within 7 seconds
- Phase_Timer = 7000;
-
- ++PhaseSubphase;
- }else Phase_Timer -= diff;
- break;
-
- //Subphase 1 - Unlock advisor
- case 1:
- if(Phase_Timer < diff)
- {
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0]));
-
- if(Advisor)
- {
- Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- Advisor->setFaction(m_creature->getFaction());
-
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- if(target)
- Advisor->AI()->AttackStart(target);
- }
-
- ++PhaseSubphase;
- }else Phase_Timer -= diff;
- break;
-
- //Subphase 2 - Start
- case 2:
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0]));
- if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD))
- {
- DoScriptText(SAY_INTRO_SANGUINAR, m_creature);
-
- //start advisor within 12.5 seconds
- Phase_Timer = 12500;
-
- ++PhaseSubphase;
- }
- break;
-
- //Subphase 2 - Unlock advisor
- case 3:
- if(Phase_Timer < diff)
- {
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1]));
-
- if(Advisor)
- {
- Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- Advisor->setFaction(m_creature->getFaction());
-
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- if(target)
- Advisor->AI()->AttackStart(target);
- }
-
- ++PhaseSubphase;
- }else Phase_Timer -= diff;
- break;
-
- //Subphase 3 - Start
- case 4:
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1]));
- if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD))
- {
- DoScriptText(SAY_INTRO_CAPERNIAN, m_creature);
-
- //start advisor within 7 seconds
- Phase_Timer = 7000;
-
- ++PhaseSubphase;
- }
- break;
-
- //Subphase 3 - Unlock advisor
- case 5:
- if(Phase_Timer < diff)
- {
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2]));
-
- if(Advisor)
- {
- Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- Advisor->setFaction(m_creature->getFaction());
-
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- if(target)
- Advisor->AI()->AttackStart(target);
- }
-
- ++PhaseSubphase;
- }else Phase_Timer -= diff;
- break;
-
- //Subphase 4 - Start
- case 6:
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2]));
- if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD))
- {
- DoScriptText(SAY_INTRO_TELONICUS, m_creature);
-
- //start advisor within 8.4 seconds
- Phase_Timer = 8400;
-
- ++PhaseSubphase;
- }
- break;
-
- //Subphase 4 - Unlock advisor
- case 7:
- if(Phase_Timer < diff)
- {
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3]));
-
- if(Advisor)
- {
- Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- Advisor->setFaction(m_creature->getFaction());
-
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- if(target)
- Advisor->AI()->AttackStart(target);
- }
-
- Phase_Timer = 3000;
-
- ++PhaseSubphase;
- }else Phase_Timer -= diff;
- break;
-
- //End of phase 1
- case 8:
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3]));
- if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD))
- {
- Phase = 2;
- pInstance->SetData(DATA_KAELTHASEVENT, 2);
-
- DoScriptText(SAY_PHASE2_WEAPON, m_creature);
- PhaseSubphase = 0;
- Phase_Timer = 3500;
- DoCast(m_creature, SPELL_SUMMON_WEAPONS);
- }
- break;
- }
- }break;
-
- case 2:
- {
- if (PhaseSubphase == 0)
- {
- if (Phase_Timer < diff)
- {
- PhaseSubphase = 1;
- }else Phase_Timer -= diff;
- }
-
- //Spawn weapons
- if (PhaseSubphase == 1)
- {
- Creature* Weapon;
- for (uint32 i = 0; i < 7; ++i)
- {
- Unit* Target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- Weapon = m_creature->SummonCreature(((uint32)KaelthasWeapons[i][0]),KaelthasWeapons[i][1],KaelthasWeapons[i][2],KaelthasWeapons[i][3],0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);
-
- if (!Weapon)
- error_log("STSCR: Kael'thas weapon %i could not be spawned", i);
- else
- {
- Weapon->setFaction(m_creature->getFaction());
- Weapon->AI()->AttackStart(Target);
- Weapon->CastSpell(Weapon, SPELL_WEAPON_SPAWN, false);
- WeaponGuid[i] = Weapon->GetGUID();
- }
- }
-
- PhaseSubphase = 2;
- Phase_Timer = TIME_PHASE_2_3;
- }
-
- if (PhaseSubphase == 2)
- if (Phase_Timer < diff)
- {
- DoScriptText(SAY_PHASE3_ADVANCE, m_creature);
- pInstance->SetData(DATA_KAELTHASEVENT, 3);
- Phase = 3;
- PhaseSubphase = 0;
- }else Phase_Timer -= diff;
- //missing Resetcheck
- }break;
-
- case 3:
- {
- if (PhaseSubphase == 0)
- {
- //Respawn advisors
- Unit* Target = SelectUnit(SELECT_TARGET_RANDOM, 0);
-
- Creature* Advisor;
- for (uint32 i = 0; i < 4; ++i)
- {
- Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i]));
- if (!Advisor)
- error_log("TSCR: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i);
- else ((advisorbase_ai*)Advisor->AI())->Revive(Target);
- }
-
- PhaseSubphase = 1;
- Phase_Timer = TIME_PHASE_3_4;
- }
-
- if(Phase_Timer < diff)
- {
- DoScriptText(SAY_PHASE4_INTRO2, m_creature);
- Phase = 4;
-
- pInstance->SetData(DATA_KAELTHASEVENT, 4);
-
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
- {
- m_creature->clearUnitState(UNIT_STAT_STUNNED);
- AttackStart(target);
- }
- Phase_Timer = 30000;
- }else Phase_Timer -= diff;
- }
- break;
-
- case 4:
- case 5:
- case 6:
- {
- //Return since we have no target
- if (!UpdateVictim() )
- return;
-
- //Fireball_Timer
- if(!InGravityLapse && !ChainPyros && Phase != 5)
- {
- if(Fireball_Timer < diff)
- {
- if(!IsCastingFireball)
- {
- if(!m_creature->IsNonMeleeSpellCasted(false))
- {
- //interruptable
- m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
- m_creature->CastSpell(m_creature->getVictim(), SPELL_FIREBALL, false);
- IsCastingFireball = true;
- Fireball_Timer = 2500;
- }
- }
- else
- {
- //apply resistance
- m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
- IsCastingFireball = false;
- Fireball_Timer = 5000+rand()%10000;
- }
- }else Fireball_Timer -= diff;
-
- //ArcaneDisruption_Timer
- if(ArcaneDisruption_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_ARCANE_DISRUPTION, true);
-
- ArcaneDisruption_Timer = 60000;
- }else ArcaneDisruption_Timer -= diff;
-
- if (FlameStrike_Timer < diff)
- {
- if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0, 70, true))
- DoCast(pUnit, SPELL_FLAME_STRIKE);
-
- FlameStrike_Timer = 30000;
- }FlameStrike_Timer -= diff;
-
- if (MindControl_Timer < diff)
- {
- if (m_creature->getThreatManager().getThreatList().size() >= 2)
- for (uint32 i = 0; i < 3; i++)
- {
-
- Unit* target =SelectUnit(SELECT_TARGET_RANDOM, 1, 70, true);
- if(!target) target = m_creature->getVictim();
- debug_log("TSCR: Kael'Thas mind control not supported.");
- DoCast(target, SPELL_MIND_CONTROL);
- }
-
- MindControl_Timer = 60000;
- }MindControl_Timer -= diff;
- }
-
- //Phoenix_Timer
- if(Phoenix_Timer < diff)
- {
- DoCast(m_creature, SPELL_SUMMON_PHOENIX);
- switch(rand()%2)
- {
- case 0: DoScriptText(SAY_SUMMON_PHOENIX1, m_creature); break;
- case 1: DoScriptText(SAY_SUMMON_PHOENIX2, m_creature); break;
- }
-
- Phoenix_Timer = 60000;
- }else Phoenix_Timer -= diff;
-
- //Phase 4 specific spells
- if(Phase == 4)
- {
- if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50)
- {
- pInstance->SetData(DATA_KAELTHASEVENT, 4);
- Phase = 5;
- Phase_Timer = 10000;
-
- DoScriptText(SAY_PHASE5_NUTS, m_creature);
-
- m_creature->StopMoving();
- m_creature->GetMotionMaster()->Clear();
- m_creature->GetMotionMaster()->MoveIdle();
- m_creature->Relocate(GRAVITY_X, GRAVITY_Y, GRAVITY_Z, 0);
- m_creature->SendMonsterMove(GRAVITY_X, GRAVITY_Y,GRAVITY_Z, 0, 0, 0);
-
- m_creature->InterruptNonMeleeSpells(false);
- DoCast(m_creature, SPELL_FULLPOWER);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- }
-
- //ShockBarrier_Timer
- if(ShockBarrier_Timer < diff)
- {
- DoCast(m_creature, SPELL_SHOCK_BARRIER);
- ChainPyros = true;
- PyrosCasted = 0;
- Check_Timer = 0;
-
- ShockBarrier_Timer = 60000;
- }else ShockBarrier_Timer -= diff;
-
- //Chain Pyros (3 of them max)
- if (ChainPyros){
- if (PyrosCasted < 3 && Check_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_PYROBLAST);
- ++PyrosCasted;
-
- Check_Timer = 4400;
- }else Check_Timer -= diff;
- if(PyrosCasted > 3)
- {
- ChainPyros = false;
- Fireball_Timer = 2500;
- ArcaneDisruption_Timer = 60000;
- }
- }
- }else Check_Timer -= 4100;
-
- if (Phase == 5)
- {
- if(Phase_Timer < diff)
- {
- m_creature->InterruptNonMeleeSpells(false);
- m_creature->RemoveAurasDueToSpell(SPELL_FULLPOWER);
- DoCast(m_creature, SPELL_EXPLODE);
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- Phase = 6;
- DoStartMovement(m_creature->getVictim());
- AttackStart(m_creature->getVictim());
- }else Phase_Timer -= diff;
- }
-
- //Phase 5
- if(Phase == 6)
- {
-
- //GravityLapse_Timer
- if(GravityLapse_Timer < diff)
- {
- std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
- switch(GravityLapse_Phase)
- {
- case 0:
- m_creature->StopMoving();
- m_creature->GetMotionMaster()->Clear();
- m_creature->GetMotionMaster()->MoveIdle();
- m_creature->Relocate(GRAVITY_X, GRAVITY_Y, GRAVITY_Z, 0);
- m_creature->SendMonsterMove(GRAVITY_X, GRAVITY_Y, GRAVITY_Z, 0, 0, 0);
- // 1) Kael'thas will portal the whole raid right into his body
- for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i)
- {
- Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
- if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER))
- {
- //Use work around packet to prevent player from being dropped from combat
- DoTeleportPlayer(pUnit, GRAVITY_X, GRAVITY_Y, GRAVITY_Z, pUnit->GetOrientation());
- }
- }
- GravityLapse_Timer = 500;
- ++GravityLapse_Phase;
- InGravityLapse = true;
- ShockBarrier_Timer = 1000;
- NetherBeam_Timer = 5000;
- break;
-
- case 1:
- switch(rand()%2)
- {
- case 0: DoScriptText(SAY_GRAVITYLAPSE1, m_creature); break;
- case 1: DoScriptText(SAY_GRAVITYLAPSE2, m_creature); break;
- }
-
- // 2) At that point he will put a Gravity Lapse debuff on everyone
- for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();i++)
- {
- Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
- if(pUnit)
- {
- m_creature->CastSpell(pUnit, SPELL_KNOCKBACK, true);
- //Gravity lapse - needs an exception in Spell system to work
-
- pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, m_creature->GetGUID());
- pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, m_creature->GetGUID());
-
- //Using packet workaround
- WorldPacket data(12);
- data.SetOpcode(SMSG_MOVE_SET_CAN_FLY);
- data.append(pUnit->GetPackGUID());
- data << uint32(0);
- pUnit->SendMessageToSet(&data, true);
- }
- }
- GravityLapse_Timer = 10000;
- ++GravityLapse_Phase;
- break;
-
- case 2:
- //Cast nether vapor aura on self
- m_creature->InterruptNonMeleeSpells(false);
- DoCast(m_creature, SPELL_NETHER_VAPOR);
-
- GravityLapse_Timer = 20000;
- ++GravityLapse_Phase;
- break;
-
- case 3:
- //Remove flight
- for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();i++)
- {
- Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
- if(pUnit)
- {
- //Using packet workaround
- WorldPacket data(12);
- data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY);
- data.append(pUnit->GetPackGUID());
- data << uint32(0);
- pUnit->SendMessageToSet(&data, true);
- }
- }
- m_creature->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR);
- InGravityLapse = false;
- GravityLapse_Timer = 60000;
- GravityLapse_Phase = 0;
- DoStartMovement(m_creature->getVictim());
- AttackStart(m_creature->getVictim());
- DoResetThreat();
- break;
- }
- }else GravityLapse_Timer -= diff;
-
- if(InGravityLapse)
- {
- //ShockBarrier_Timer
- if(ShockBarrier_Timer < diff)
- {
- DoCast(m_creature, SPELL_SHOCK_BARRIER);
- ShockBarrier_Timer = 20000;
- }else ShockBarrier_Timer -= diff;
-
- //NetherBeam_Timer
- if(NetherBeam_Timer < diff)
- {
- if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0))
- DoCast(pUnit, SPELL_NETHER_BEAM);
-
- NetherBeam_Timer = 4000;
- }else NetherBeam_Timer -= diff;
- }
- }
-
- if (!InGravityLapse)
- DoMeleeAttackIfReady();
- }
- }
- }
-};
-
-//Thaladred the Darkener AI
-struct TRINITY_DLL_DECL boss_thaladred_the_darkenerAI : public advisorbase_ai
-{
- boss_thaladred_the_darkenerAI(Creature *c) : advisorbase_ai(c) {}
-
- uint32 Gaze_Timer;
- uint32 Silence_Timer;
- uint32 PsychicBlow_Timer;
-
- void Reset()
- {
- Gaze_Timer = 100;
- Silence_Timer = 20000;
- PsychicBlow_Timer = 10000;
-
- advisorbase_ai::Reset();
- }
-
- void JustDied(Unit* pKiller)
- {
- DoScriptText(SAY_THALADRED_DEATH, m_creature);
- }
-
- void Aggro(Unit *who)
- {
- if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- if (!who || FakeDeath)
- return;
-
- DoScriptText(SAY_THALADRED_AGGRO, m_creature);
- m_creature->AddThreat(who, 5000000.0f);
- }
-
- void UpdateAI(const uint32 diff)
- {
- advisorbase_ai::UpdateAI(diff);
-
- //Faking death, don't do anything
- if (FakeDeath)
- return;
-
- //Return since we have no target
- if (!UpdateVictim() )
- return;
-
- //Gaze_Timer
- if(Gaze_Timer < diff)
- {
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true))
- {
- DoResetThreat();
- m_creature->AddThreat(target, 5000000.0f);
- DoScriptText(EMOTE_THALADRED_GAZE, m_creature, target);
- Gaze_Timer = 8500;
- }
- }else Gaze_Timer -= diff;
-
- //Silence_Timer
- if(Silence_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_SILENCE);
- Silence_Timer = 20000;
- }else Silence_Timer -= diff;
-
- //PsychicBlow_Timer
- if(PsychicBlow_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_PSYCHIC_BLOW);
- PsychicBlow_Timer = 20000+rand()%5000;
- }else PsychicBlow_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-};
-
-//Lord Sanguinar AI
-struct TRINITY_DLL_DECL boss_lord_sanguinarAI : public advisorbase_ai
-{
- boss_lord_sanguinarAI(Creature *c) : advisorbase_ai(c){}
-
- uint32 Fear_Timer;
-
- void Reset()
- {
- Fear_Timer = 20000;
- advisorbase_ai::Reset();
- }
-
- void JustDied(Unit* Killer)
- {
- DoScriptText(SAY_SANGUINAR_DEATH, m_creature);
- }
-
- void Aggro(Unit *who)
- {
- if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- if (!who || FakeDeath)
- return;
-
- DoScriptText(SAY_SANGUINAR_AGGRO, m_creature);
- }
-
- void UpdateAI(const uint32 diff)
- {
- advisorbase_ai::UpdateAI(diff);
-
- //Faking death, don't do anything
- if (FakeDeath)
- return;
-
- //Return since we have no target
- if (!UpdateVictim() )
- return;
-
- //Fear_Timer
- if(Fear_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_BELLOWING_ROAR);
- Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds
- }else Fear_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-};
-
-//Grand Astromancer Capernian AI
-struct TRINITY_DLL_DECL boss_grand_astromancer_capernianAI : public advisorbase_ai
-{
- boss_grand_astromancer_capernianAI(Creature *c) : advisorbase_ai(c){}
-
- uint32 Fireball_Timer;
- uint32 Conflagration_Timer;
- uint32 ArcaneExplosion_Timer;
- uint32 Yell_Timer;
- bool Yell;
-
- void Reset()
- {
- Fireball_Timer = 2000;
- Conflagration_Timer = 20000;
- ArcaneExplosion_Timer = 5000;
- Yell_Timer = 2000;
- Yell = false;
-
- advisorbase_ai::Reset();
- }
-
- void JustDied(Unit* pKiller)
- {
- DoScriptText(SAY_CAPERNIAN_DEATH, m_creature);
- }
-
- void AttackStart(Unit* who)
- {
- if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- if (m_creature->Attack(who, true))
- {
- m_creature->AddThreat(who, 0.0f);
-
- if (!InCombat)
- {
- InCombat = true;
- Aggro(who);
- }
-
- DoStartMovement(who, CAPERNIAN_DISTANCE, M_PI/2);
- }
- }
-
- void Aggro(Unit *who)
- {
- if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- if (!who || FakeDeath)
- return;
- }
-
- void UpdateAI(const uint32 diff)
- {
- advisorbase_ai::UpdateAI(diff);
-
- //Faking Death, don't do anything
- if (FakeDeath)
- return;
-
- //Return since we have no target
- if (!UpdateVictim() )
- return;
-
- //Yell_Timer
- if(!Yell)
- {
- if(Yell_Timer < diff)
- {
- DoScriptText(SAY_CAPERNIAN_AGGRO, m_creature);
-
- Yell = true;
- }else Yell_Timer -= diff;
- }
-
- //Fireball_Timer
- if(Fireball_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_CAPERNIAN_FIREBALL);
- Fireball_Timer = 4000;
- }else Fireball_Timer -= diff;
-
- //Conflagration_Timer
- if(Conflagration_Timer < diff)
- {
- Unit *target = NULL;
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
-
- if(target && m_creature->IsWithinDistInMap(target, 30))
- DoCast(target, SPELL_CONFLAGRATION);
- else
- DoCast(m_creature->getVictim(), SPELL_CONFLAGRATION);
-
- Conflagration_Timer = 10000+rand()%5000;
- }else Conflagration_Timer -= diff;
-
- //ArcaneExplosion_Timer
- if(ArcaneExplosion_Timer < diff)
- {
- bool InMeleeRange = false;
- Unit *target = NULL;
- std::list<HostilReference*>& m_threatlist = m_creature->getThreatManager().getThreatList();
- for (std::list<HostilReference*>::iterator i = m_threatlist.begin(); i!= m_threatlist.end();++i)
- {
- Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
- //if in melee range
- if(pUnit && pUnit->IsWithinDistInMap(m_creature, 5))
- {
- InMeleeRange = true;
- target = pUnit;
- break;
- }
- }
-
- if(InMeleeRange)
- DoCast(target, SPELL_ARCANE_EXPLOSION);
-
- ArcaneExplosion_Timer = 4000+rand()%2000;
- }else ArcaneExplosion_Timer -= diff;
-
- //Do NOT deal any melee damage.
- }
-};
-
-//Master Engineer Telonicus AI
-struct TRINITY_DLL_DECL boss_master_engineer_telonicusAI : public advisorbase_ai
-{
- boss_master_engineer_telonicusAI(Creature *c) : advisorbase_ai(c){}
-
- uint32 Bomb_Timer;
- uint32 RemoteToy_Timer;
-
- void Reset()
- {
- Bomb_Timer = 10000;
- RemoteToy_Timer = 5000;
-
- advisorbase_ai::Reset();
- }
-
- void JustDied(Unit* pKiller)
- {
- DoScriptText(SAY_TELONICUS_DEATH, m_creature);
- }
-
- void Aggro(Unit *who)
- {
- if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- return;
-
- if (!who || FakeDeath)
- return;
-
- DoScriptText(SAY_TELONICUS_AGGRO, m_creature);
- }
-
- void UpdateAI(const uint32 diff)
- {
- advisorbase_ai::UpdateAI(diff);
-
- //Faking Death, do nothing
- if (FakeDeath)
- return;
-
- //Return since we have no target
- if (!UpdateVictim() )
- return;
-
- //Bomb_Timer
- if(Bomb_Timer < diff)
- {
- DoCast(m_creature->getVictim(), SPELL_BOMB);
- Bomb_Timer = 25000;
- }else Bomb_Timer -= diff;
-
- //RemoteToy_Timer
- if(RemoteToy_Timer < diff)
- {
- if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_REMOTE_TOY);
-
- RemoteToy_Timer = 10000+rand()%5000;
- }else RemoteToy_Timer -= diff;
-
- DoMeleeAttackIfReady();
- }
-};
-
-//Flame Strike AI
-struct TRINITY_DLL_DECL mob_kael_flamestrikeAI : public ScriptedAI
-{
- mob_kael_flamestrikeAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- uint32 Timer;
- bool Casting;
- bool KillSelf;
-
- void Reset()
- {
- Timer = 5000;
- Casting = false;
- KillSelf = false;
-
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->setFaction(14);
- }
-
- void Aggro(Unit *who)
- {
- }
-
- void MoveInLineOfSight(Unit *who)
- {
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (!Casting)
- {
- DoCast(m_creature, SPELL_FLAME_STRIKE_VIS);
- Casting = true;
- }
-
- //Timer
- if(Timer < diff)
- {
- if (!KillSelf)
- {
- m_creature->InterruptNonMeleeSpells(false);
- DoCast(m_creature, SPELL_FLAME_STRIKE_DMG);
- }else m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
-
- KillSelf = true;
- Timer = 1000;
- }else Timer -= diff;
- }
-};
-
-//Phoenix AI
-struct TRINITY_DLL_DECL mob_phoenix_tkAI : public ScriptedAI
-{
- mob_phoenix_tkAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- uint32 Cycle_Timer;
- uint8 SummonEgg;
-
- void Reset()
- {
- Cycle_Timer = 2000;
- SummonEgg = 0;
- m_creature->CastSpell(m_creature,SPELL_BURN,true);
- }
-
- void Aggro(Unit *who) { }
-
- void DamageTaken(Unit* pKiller, uint32 &damage)
- {
- if(m_creature->GetHealth() < damage && SummonEgg < 2){
- damage = 0;
- SummonEgg = 1;
- }
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (!UpdateVictim())
- return;
-
- if(SummonEgg < 2){
- if (Cycle_Timer < diff)
- {
- //spell Burn should possible do this, but it doesn't, so do this for now.
- uint32 dmg = urand(4500,5500);
- if (m_creature->GetHealth() > dmg)
- m_creature->SetHealth(uint32(m_creature->GetHealth()-dmg));
- Cycle_Timer = 2000;
- }else Cycle_Timer -= diff;
- }else {
- if(Cycle_Timer < diff){
- m_creature->SummonCreature(PHOENIX_EGG,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000);
- m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- m_creature->RemoveCorpse();
- }else Cycle_Timer -= diff;
- }
-
- if(SummonEgg == 1){ //hack die animation
- m_creature->RemoveAllAuras();
- DoStartNoMovement(m_creature->getVictim());
- m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
- SummonEgg = 2;
- Cycle_Timer = 1000;
- }
- if(SummonEgg < 2)DoMeleeAttackIfReady();
- }
-};
-
-//Phoenix Egg AI
-struct TRINITY_DLL_DECL mob_phoenix_egg_tkAI : public ScriptedAI
-{
- mob_phoenix_egg_tkAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- uint32 Rebirth_Timer;
- bool summoned;
-
- void Reset(){
- Rebirth_Timer = 15000;
- summoned = false;
- }
-
- //ignore any
- void MoveInLineOfSight(Unit* who) { return; }
-
- void AttackStart(Unit* who)
- {
- if (m_creature->Attack(who, false))
- {
- if (!InCombat)
- {
- InCombat = true;
- Aggro(who);
- }
- DoStartNoMovement(who);
- }
- }
-
- void Aggro(Unit *who) { }
-
- void JustSummoned(Creature* summoned)
- {
- summoned->AddThreat(m_creature->getVictim(), 0.0f);
- summoned->CastSpell(summoned,SPELL_REBIRTH,false);
- }
-
- void UpdateAI(const uint32 diff)
- {
- if (Rebirth_Timer < diff)
- {
- if(!summoned){
- Creature* Phoenix = m_creature->SummonCreature(PHOENIX,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000);
- summoned = true;
- }
- m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- }else Rebirth_Timer -= diff;
- }
-};
-
-CreatureAI* GetAI_boss_kaelthas(Creature *_Creature)
-{
- return new boss_kaelthasAI (_Creature);
-}
-
-CreatureAI* GetAI_boss_thaladred_the_darkener(Creature *_Creature)
-{
- return new boss_thaladred_the_darkenerAI (_Creature);
-}
-
-CreatureAI* GetAI_boss_lord_sanguinar(Creature *_Creature)
-{
- return new boss_lord_sanguinarAI (_Creature);
-}
-
-CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature *_Creature)
-{
- return new boss_grand_astromancer_capernianAI (_Creature);
-}
-
-CreatureAI* GetAI_boss_master_engineer_telonicus(Creature *_Creature)
-{
- return new boss_master_engineer_telonicusAI (_Creature);
-}
-
-CreatureAI* GetAI_mob_kael_flamestrike(Creature *_Creature)
-{
- return new mob_kael_flamestrikeAI (_Creature);
-}
-
-CreatureAI* GetAI_mob_phoenix_tk(Creature *_Creature)
-{
- return new mob_phoenix_tkAI (_Creature);
-}
-
-CreatureAI* GetAI_mob_phoenix_egg_tk(Creature *_Creature)
-{
- return new mob_phoenix_egg_tkAI (_Creature);
-}
-void AddSC_boss_kaelthas()
-{
- Script *newscript;
- newscript = new Script;
- newscript->Name="boss_kaelthas";
- newscript->GetAI = &GetAI_boss_kaelthas;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="boss_thaladred_the_darkener";
- newscript->GetAI = &GetAI_boss_thaladred_the_darkener;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="boss_lord_sanguinar";
- newscript->GetAI = &GetAI_boss_lord_sanguinar;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="boss_grand_astromancer_capernian";
- newscript->GetAI = &GetAI_boss_grand_astromancer_capernian;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="boss_master_engineer_telonicus";
- newscript->GetAI = &GetAI_boss_master_engineer_telonicus;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name= "mob_kael_flamestrike";
- newscript->GetAI = &GetAI_mob_kael_flamestrike;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="mob_phoenix_tk";
- newscript->GetAI = &GetAI_mob_phoenix_tk;
- newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name = "mob_phoenix_egg_tk";
- newscript->GetAI = &GetAI_mob_phoenix_egg_tk;
- newscript->RegisterSelf();
-}
-
+/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * 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 + */ + +/* ScriptData +SDName: boss_Kaelthas +SD%Complete: 60 +SDComment: Mind Control, Reset Event if Weapons despawn/reset +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "precompiled.h" +#include "def_the_eye.h" +#include "WorldPacket.h" + + //kael'thas Speech +#define SAY_INTRO -1550016 +#define SAY_INTRO_CAPERNIAN -1550017 +#define SAY_INTRO_TELONICUS -1550018 +#define SAY_INTRO_THALADRED -1550019 +#define SAY_INTRO_SANGUINAR -1550020 +#define SAY_PHASE2_WEAPON -1550021 +#define SAY_PHASE3_ADVANCE -1550022 +#define SAY_PHASE4_INTRO2 -1550023 +#define SAY_PHASE5_NUTS -1550024 +#define SAY_SLAY1 -1550025 +#define SAY_SLAY2 -1550026 +#define SAY_SLAY3 -1550027 +#define SAY_MINDCONTROL1 -1550028 +#define SAY_MINDCONTROL2 -1550029 +#define SAY_GRAVITYLAPSE1 -1550030 +#define SAY_GRAVITYLAPSE2 -1550031 +#define SAY_SUMMON_PHOENIX1 -1550032 +#define SAY_SUMMON_PHOENIX2 -1550033 +#define SAY_DEATH -1550034 + +//Thaladred the Darkener speech +#define SAY_THALADRED_AGGRO -1550035 +#define SAY_THALADRED_DEATH -1550036 +#define EMOTE_THALADRED_GAZE -1550037 + +//Lord Sanguinar speech +#define SAY_SANGUINAR_AGGRO -1550038 +#define SAY_SANGUINAR_DEATH -1550039 + +//Grand Astromancer Capernian speech +#define SAY_CAPERNIAN_AGGRO -1550040 +#define SAY_CAPERNIAN_DEATH -1550041 + +//Master Engineer Telonicus speech +#define SAY_TELONICUS_AGGRO -1550042 +#define SAY_TELONICUS_DEATH -1550043 + +//Phase 2 spells (Not used) +#define SPELL_SUMMON_WEAPONS 36976 +#define SPELL_SUMMON_WEAPONA 36958 +#define SPELL_SUMMON_WEAPONB 36959 +#define SPELL_SUMMON_WEAPONC 36960 +#define SPELL_SUMMON_WEAPOND 36961 +#define SPELL_SUMMON_WEAPONE 36962 +#define SPELL_SUMMON_WEAPONF 36963 +#define SPELL_SUMMON_WEAPONG 36964 +#define SPELL_RES_VISUAL 24171 +#define SPELL_WEAPON_SPAWN 41236 + +//Phase 4 spells +#define SPELL_FIREBALL 36805 +#define SPELL_PYROBLAST 36819 +#define SPELL_FLAME_STRIKE 36735 +#define SPELL_FLAME_STRIKE_VIS 36730 +#define SPELL_FLAME_STRIKE_DMG 36731 +#define SPELL_ARCANE_DISRUPTION 36834 +#define SPELL_SHOCK_BARRIER 36815 +#define SPELL_SUMMON_PHOENIX 36723 +#define SPELL_MIND_CONTROL 32830 + +//Phase 5 spells +#define SPELL_EXPLODE 36092 +#define SPELL_FULLPOWER 36187 +#define SPELL_KNOCKBACK 11027 +#define SPELL_GRAVITY_LAPSE 34480 +#define SPELL_GRAVITY_LAPSE_AURA 39432 +#define SPELL_NETHER_BEAM 35873 + +//Thaladred the Darkener spells +#define SPELL_PSYCHIC_BLOW 10689 +#define SPELL_SILENCE 30225 + +//Lord Sanguinar spells +#define SPELL_BELLOWING_ROAR 40636 + +//Grand Astromancer Capernian spells +#define CAPERNIAN_DISTANCE 20 //she casts away from the target +#define SPELL_CAPERNIAN_FIREBALL 36971 +#define SPELL_CONFLAGRATION 37018 +#define SPELL_ARCANE_EXPLOSION 36970 + +//Master Engineer Telonicus spells +#define SPELL_BOMB 37036 +#define SPELL_REMOTE_TOY 37027 + +//Nether Vapor spell +#define SPELL_NETHER_VAPOR 35859 + +//Phoenix spell +#define SPELL_BURN 36720 +#define SPELL_EMBER_BLAST 34341 +#define SPELL_REBIRTH 41587 + +//Creature IDs +#define PHOENIX 21362 +#define PHOENIX_EGG 21364 + +//Phoenix egg and phoenix model +#define PHOENIX_MODEL 19682 +#define PHOENIX_EGG_MODEL 20245 + +//weapon id + position +float KaelthasWeapons[7][5] = +{ + {21270, 794.38, 15, 48.72, 2.9}, //[Cosmic Infuser] + {21269, 785.47, 12.12, 48.72, 3.14}, //[Devastation] + {21271, 781.25, 4.39, 48.72, 3.14}, //[Infinity Blade] + {21273, 777.38, -0.81, 48.72, 3.06}, //[Phaseshift Bulwark] + {21274, 781.48, -6.08, 48.72, 3.9}, //[Staff of Disintegration] + {21272, 785.42, -13.59, 48.72, 3.4}, //[Warp Slicer] + {21268, 793.06, -16.61, 48.72, 3.10} //[Netherstrand Longbow] +}; + +#define GRAVITY_X 795.0f +#define GRAVITY_Y 0.0f +#define GRAVITY_Z 70.0f + +#define TIME_PHASE_2_3 120000 +#define TIME_PHASE_3_4 120000 + +#define KAEL_VISIBLE_RANGE 50.0f + +//Base AI for Advisors +struct TRINITY_DLL_DECL advisorbase_ai : public ScriptedAI +{ + ScriptedInstance* pInstance; + bool FakeDeath; + uint32 DelayRes_Timer; + uint64 DelayRes_Target; + + advisorbase_ai(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void Reset() + { + FakeDeath = false; + DelayRes_Timer = 0; + DelayRes_Target = 0; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //reset encounter + if(pInstance && (pInstance->GetData(DATA_KAELTHASEVENT) == 1 || pInstance->GetData(DATA_KAELTHASEVENT) == 3)) + { + Creature *Kaelthas = NULL; + Kaelthas = (Creature*)(Unit::GetUnit((*m_creature), pInstance->GetData64(DATA_KAELTHAS))); + + if(Kaelthas) + Kaelthas->AI()->EnterEvadeMode(); + } + } + + void Revive(Unit* Target) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + DoCast(m_creature, SPELL_RES_VISUAL, false); + DelayRes_Timer = 2000; + } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage < m_creature->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath) + { + damage = 0; + return; + } + //Don't really die in phase 1 & 3, only die after that + if(pInstance && pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(0); + m_creature->StopMoving(); + m_creature->ClearComboPointHolders(); + m_creature->RemoveAllAurasOnDeath(); + m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->ClearAllReactives(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET,0); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + + if (pInstance->GetData(DATA_KAELTHASEVENT) == 3) + JustDied(pKiller); + } + } + + void UpdateAI(const uint32 diff) + { + if (DelayRes_Timer) + { + if (DelayRes_Timer <= diff) + { + DelayRes_Timer = 0; + FakeDeath = false; + + Unit* Target = Unit::GetUnit((*m_creature), DelayRes_Target); + if (!Target) + Target = m_creature->getVictim(); + DoResetThreat(); + AttackStart(Target); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(Target); + m_creature->AddThreat(Target, 0.0f); + }else DelayRes_Timer -= diff; + } + } +}; + +//Kael'thas AI +struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI +{ + boss_kaelthasAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + AdvisorGuid[0] = 0; + AdvisorGuid[1] = 0; + AdvisorGuid[2] = 0; + AdvisorGuid[3] = 0; + Reset(); + } + + ScriptedInstance* pInstance; + + std::list<uint64> Phoenix; + + uint32 Fireball_Timer; + uint32 ArcaneDisruption_Timer; + uint32 Phoenix_Timer; + uint32 ShockBarrier_Timer; + uint32 GravityLapse_Timer; + uint32 GravityLapse_Phase; + uint32 NetherBeam_Timer; + uint32 NetherVapor_Timer; + uint32 FlameStrike_Timer; + uint32 MindControl_Timer; + uint32 Check_Timer; + uint32 Phase; + uint32 PhaseSubphase; //generic + uint32 Phase_Timer; //generic timer + uint32 PyrosCasted; + + bool InGravityLapse; + bool IsCastingFireball; + bool ChainPyros; + + uint64 AdvisorGuid[4]; + uint64 WeaponGuid[7]; + + void DeleteLegs() + { + InstanceMap::PlayerList const &playerliste = ((InstanceMap*)m_creature->GetMap())->GetPlayers(); + InstanceMap::PlayerList::const_iterator it; + + Map::PlayerList const &PlayerList = ((InstanceMap*)m_creature->GetMap())->GetPlayers(); + for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + Player* i_pl = i->getSource(); + i_pl->DestroyItemCount(30312, 1, true); + i_pl->DestroyItemCount(30311, 1, true); + i_pl->DestroyItemCount(30317, 1, true); + i_pl->DestroyItemCount(30316, 1, true); + i_pl->DestroyItemCount(30313, 1, true); + i_pl->DestroyItemCount(30314, 1, true); + i_pl->DestroyItemCount(30318, 1, true); + i_pl->DestroyItemCount(30319, 1, true); + i_pl->DestroyItemCount(30320, 1, true); + } + if(pInstance) { + for(uint32 i = 0; i < 7; i++) { + Creature* weapon = (Creature*)(Unit::GetUnit((*m_creature), WeaponGuid[i]));; + delete weapon; + } + } + } + + void CleanPhoenix() + { + CellPair pair(Trinity::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list<Creature*> PhoenixList; + + Trinity::AllCreaturesOfEntryInRange check(m_creature, PHOENIX, 50); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, PhoenixList, check); + TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> visitor(searcher); + + CellLock<GridReadGuard> cell_lock(cell, pair); + cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap())); + + if(!PhoenixList.empty()) + { + for(std::list<Creature*>::iterator itr = PhoenixList.begin(); itr != PhoenixList.end(); ++itr) + { + (*itr)->RemoveFromWorld(); + } + } + } + + void Reset() + { + Fireball_Timer = 5000+rand()%10000; + ArcaneDisruption_Timer = 45000; + MindControl_Timer = 40000; + Phoenix_Timer = 50000; + ShockBarrier_Timer = 60000; + FlameStrike_Timer = 30000; + GravityLapse_Timer = 20000; + GravityLapse_Phase = 0; + NetherBeam_Timer = 8000; + NetherVapor_Timer = 10000; + Check_Timer = 4000; + PyrosCasted = 0; + Phase = 0; + InGravityLapse = false; + IsCastingFireball = false; + ChainPyros = false; + + if(InCombat) + PrepareAdvisors(); + + DeleteLegs(); + CleanPhoenix(); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + + + if(pInstance) + pInstance->SetData(DATA_KAELTHASEVENT, NOT_STARTED); + } + + void PrepareAdvisors() + { + Creature *pCreature; + for(uint8 i = 0; i < 4; ++i) + { + pCreature = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i])); + if(pCreature) + { + pCreature->Respawn(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->setFaction(m_creature->getFaction()); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + void StartEvent() + { + if(!pInstance) + return; + + AdvisorGuid[0] = pInstance->GetData64(DATA_THALADREDTHEDARKENER); + AdvisorGuid[1] = pInstance->GetData64(DATA_LORDSANGUINAR); + AdvisorGuid[2] = pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); + AdvisorGuid[3] = pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); + m_creature->addUnitState(UNIT_STAT_STUNNED); + + if(!AdvisorGuid[0] || !AdvisorGuid[1] || !AdvisorGuid[2] || !AdvisorGuid[3]) + { + error_log("SD2: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); + DoYell("SD2: Kael'Thas One or more advisors missing, Skipping Phases 1-3", LANG_UNIVERSAL, NULL); + + DoScriptText(SAY_PHASE4_INTRO2, m_creature); + Phase = 4; + + pInstance->SetData(DATA_KAELTHASEVENT, 4); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + AttackStart(target); + } + else + { + PrepareAdvisors(); + + DoScriptText(SAY_INTRO, m_creature); + + pInstance->SetData(DATA_KAELTHASEVENT, IN_PROGRESS); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + PhaseSubphase = 0; + Phase_Timer = 23000; + Phase = 1; + } + } + + void KilledUnit() + { + switch(rand()%3) + { + case 0: DoScriptText(SAY_SLAY1, m_creature); break; + case 1: DoScriptText(SAY_SLAY2, m_creature); break; + case 2: DoScriptText(SAY_SLAY3, m_creature); break; + } + } + + void JustSummoned(Creature* summoned) + { + if(summoned->GetEntry() == PHOENIX) + { + summoned->setFaction(m_creature->getFaction()); + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0); + summoned->AI()->AttackStart(target); + } + } + + void JustDied(Unit* Killer) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoScriptText(SAY_DEATH, m_creature); + + DeleteLegs(); + + if(pInstance) + pInstance->SetData(DATA_KAELTHASEVENT, DONE); + + Creature *pCreature; + for(uint8 i = 0; i < 4; ++i) + { + pCreature = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i])); + if(pCreature) + { + pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + + void Aggro(Unit *who) + { + if (pInstance && !pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!m_creature->getVictim() && who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who)) + { + if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(who); + if (Phase >= 4 && m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who)) + { + AttackStart(who); + } + else if(who->isAlive()) + { + if (pInstance && !pInstance->GetData(DATA_KAELTHASEVENT) && !Phase && m_creature->IsWithinDistInMap(who, 60.0f)) + StartEvent(); + + //add to the threat list, so we can use SelectTarget + m_creature->AddThreat(who,0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Phase 1 + switch (Phase) + { + case 1: + { + Unit *target; + Creature* Advisor; + + //Subphase switch + switch(PhaseSubphase) + { + //Subphase 1 - Start + case 0: + if(Phase_Timer < diff) + { + DoScriptText(SAY_INTRO_THALADRED, m_creature); + + //start advisor within 7 seconds + Phase_Timer = 7000; + + ++PhaseSubphase; + }else Phase_Timer -= diff; + break; + + //Subphase 1 - Unlock advisor + case 1: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + ++PhaseSubphase; + }else Phase_Timer -= diff; + break; + + //Subphase 2 - Start + case 2: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_SANGUINAR, m_creature); + + //start advisor within 12.5 seconds + Phase_Timer = 12500; + + ++PhaseSubphase; + } + break; + + //Subphase 2 - Unlock advisor + case 3: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + ++PhaseSubphase; + }else Phase_Timer -= diff; + break; + + //Subphase 3 - Start + case 4: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_CAPERNIAN, m_creature); + + //start advisor within 7 seconds + Phase_Timer = 7000; + + ++PhaseSubphase; + } + break; + + //Subphase 3 - Unlock advisor + case 5: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + ++PhaseSubphase; + }else Phase_Timer -= diff; + break; + + //Subphase 4 - Start + case 6: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_TELONICUS, m_creature); + + //start advisor within 8.4 seconds + Phase_Timer = 8400; + + ++PhaseSubphase; + } + break; + + //Subphase 4 - Unlock advisor + case 7: + if(Phase_Timer < diff) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3])); + + if(Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(m_creature->getFaction()); + + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + if(target) + Advisor->AI()->AttackStart(target); + } + + Phase_Timer = 3000; + + ++PhaseSubphase; + }else Phase_Timer -= diff; + break; + + //End of phase 1 + case 8: + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3])); + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) + { + Phase = 2; + pInstance->SetData(DATA_KAELTHASEVENT, 2); + + DoScriptText(SAY_PHASE2_WEAPON, m_creature); + PhaseSubphase = 0; + Phase_Timer = 3500; + DoCast(m_creature, SPELL_SUMMON_WEAPONS); + } + break; + } + }break; + + case 2: + { + if (PhaseSubphase == 0) + { + if (Phase_Timer < diff) + { + PhaseSubphase = 1; + }else Phase_Timer -= diff; + } + + //Spawn weapons + if (PhaseSubphase == 1) + { + Creature* Weapon; + for (uint32 i = 0; i < 7; ++i) + { + Unit* Target = SelectUnit(SELECT_TARGET_RANDOM, 0); + Weapon = m_creature->SummonCreature(((uint32)KaelthasWeapons[i][0]),KaelthasWeapons[i][1],KaelthasWeapons[i][2],KaelthasWeapons[i][3],0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + + if (!Weapon) + error_log("STSCR: Kael'thas weapon %i could not be spawned", i); + else + { + Weapon->setFaction(m_creature->getFaction()); + Weapon->AI()->AttackStart(Target); + Weapon->CastSpell(Weapon, SPELL_WEAPON_SPAWN, false); + WeaponGuid[i] = Weapon->GetGUID(); + } + } + + PhaseSubphase = 2; + Phase_Timer = TIME_PHASE_2_3; + } + + if (PhaseSubphase == 2) + if (Phase_Timer < diff) + { + DoScriptText(SAY_PHASE3_ADVANCE, m_creature); + pInstance->SetData(DATA_KAELTHASEVENT, 3); + Phase = 3; + PhaseSubphase = 0; + }else Phase_Timer -= diff; + //missing Resetcheck + }break; + + case 3: + { + if (PhaseSubphase == 0) + { + //Respawn advisors + Unit* Target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature* Advisor; + for (uint32 i = 0; i < 4; ++i) + { + Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[i])); + if (!Advisor) + error_log("TSCR: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); + else ((advisorbase_ai*)Advisor->AI())->Revive(Target); + } + + PhaseSubphase = 1; + Phase_Timer = TIME_PHASE_3_4; + } + + if(Phase_Timer < diff) + { + DoScriptText(SAY_PHASE4_INTRO2, m_creature); + Phase = 4; + + pInstance->SetData(DATA_KAELTHASEVENT, 4); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + m_creature->clearUnitState(UNIT_STAT_STUNNED); + AttackStart(target); + } + Phase_Timer = 30000; + }else Phase_Timer -= diff; + } + break; + + case 4: + case 5: + case 6: + { + //Return since we have no target + if (!UpdateVictim() ) + return; + + //Fireball_Timer + if(!InGravityLapse && !ChainPyros && Phase != 5) + { + if(Fireball_Timer < diff) + { + if(!IsCastingFireball) + { + if(!m_creature->IsNonMeleeSpellCasted(false)) + { + //interruptable + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); + m_creature->CastSpell(m_creature->getVictim(), SPELL_FIREBALL, false); + IsCastingFireball = true; + Fireball_Timer = 2500; + } + } + else + { + //apply resistance + m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + IsCastingFireball = false; + Fireball_Timer = 5000+rand()%10000; + } + }else Fireball_Timer -= diff; + + //ArcaneDisruption_Timer + if(ArcaneDisruption_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ARCANE_DISRUPTION, true); + + ArcaneDisruption_Timer = 60000; + }else ArcaneDisruption_Timer -= diff; + + if (FlameStrike_Timer < diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0, 70, true)) + DoCast(pUnit, SPELL_FLAME_STRIKE); + + FlameStrike_Timer = 30000; + }FlameStrike_Timer -= diff; + + if (MindControl_Timer < diff) + { + if (m_creature->getThreatManager().getThreatList().size() >= 2) + for (uint32 i = 0; i < 3; i++) + { + + Unit* target =SelectUnit(SELECT_TARGET_RANDOM, 1, 70, true); + if(!target) target = m_creature->getVictim(); + debug_log("TSCR: Kael'Thas mind control not supported."); + DoCast(target, SPELL_MIND_CONTROL); + } + + MindControl_Timer = 60000; + }MindControl_Timer -= diff; + } + + //Phoenix_Timer + if(Phoenix_Timer < diff) + { + DoCast(m_creature, SPELL_SUMMON_PHOENIX); + switch(rand()%2) + { + case 0: DoScriptText(SAY_SUMMON_PHOENIX1, m_creature); break; + case 1: DoScriptText(SAY_SUMMON_PHOENIX2, m_creature); break; + } + + Phoenix_Timer = 60000; + }else Phoenix_Timer -= diff; + + //Phase 4 specific spells + if(Phase == 4) + { + if (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 50) + { + pInstance->SetData(DATA_KAELTHASEVENT, 4); + Phase = 5; + Phase_Timer = 10000; + + DoScriptText(SAY_PHASE5_NUTS, m_creature); + + m_creature->StopMoving(); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + DoTeleportTo(GRAVITY_X, GRAVITY_Y, GRAVITY_Z); + + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_FULLPOWER); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + //ShockBarrier_Timer + if(ShockBarrier_Timer < diff) + { + DoCast(m_creature, SPELL_SHOCK_BARRIER); + ChainPyros = true; + PyrosCasted = 0; + Check_Timer = 0; + + ShockBarrier_Timer = 60000; + }else ShockBarrier_Timer -= diff; + + //Chain Pyros (3 of them max) + if (ChainPyros){ + if (PyrosCasted < 3 && Check_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_PYROBLAST); + ++PyrosCasted; + + Check_Timer = 4400; + }else Check_Timer -= diff; + if(PyrosCasted > 3) + { + ChainPyros = false; + Fireball_Timer = 2500; + ArcaneDisruption_Timer = 60000; + } + } + }else Check_Timer -= 4100; + + if (Phase == 5) + { + if(Phase_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + m_creature->RemoveAurasDueToSpell(SPELL_FULLPOWER); + DoCast(m_creature, SPELL_EXPLODE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Phase = 6; + DoStartMovement(m_creature->getVictim()); + AttackStart(m_creature->getVictim()); + }else Phase_Timer -= diff; + } + + //Phase 5 + if(Phase == 6) + { + + //GravityLapse_Timer + if(GravityLapse_Timer < diff) + { + std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin(); + switch(GravityLapse_Phase) + { + case 0: + m_creature->StopMoving(); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + DoTeleportTo(GRAVITY_X, GRAVITY_Y, GRAVITY_Z); + // 1) Kael'thas will portal the whole raid right into his body + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + //Use work around packet to prevent player from being dropped from combat + DoTeleportPlayer(pUnit, GRAVITY_X, GRAVITY_Y, GRAVITY_Z, pUnit->GetOrientation()); + } + } + GravityLapse_Timer = 500; + ++GravityLapse_Phase; + InGravityLapse = true; + ShockBarrier_Timer = 1000; + NetherBeam_Timer = 5000; + break; + + case 1: + switch(rand()%2) + { + case 0: DoScriptText(SAY_GRAVITYLAPSE1, m_creature); break; + case 1: DoScriptText(SAY_GRAVITYLAPSE2, m_creature); break; + } + + // 2) At that point he will put a Gravity Lapse debuff on everyone + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();i++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit) + { + m_creature->CastSpell(pUnit, SPELL_KNOCKBACK, true); + //Gravity lapse - needs an exception in Spell system to work + + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, m_creature->GetGUID()); + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, m_creature->GetGUID()); + + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + GravityLapse_Timer = 10000; + ++GravityLapse_Phase; + break; + + case 2: + //Cast nether vapor aura on self + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_NETHER_VAPOR); + + GravityLapse_Timer = 20000; + ++GravityLapse_Phase; + break; + + case 3: + //Remove flight + for (i = m_creature->getThreatManager().getThreatList().begin(); i!= m_creature->getThreatManager().getThreatList().end();i++) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + if(pUnit) + { + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + m_creature->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); + InGravityLapse = false; + GravityLapse_Timer = 60000; + GravityLapse_Phase = 0; + DoStartMovement(m_creature->getVictim()); + AttackStart(m_creature->getVictim()); + DoResetThreat(); + break; + } + }else GravityLapse_Timer -= diff; + + if(InGravityLapse) + { + //ShockBarrier_Timer + if(ShockBarrier_Timer < diff) + { + DoCast(m_creature, SPELL_SHOCK_BARRIER); + ShockBarrier_Timer = 20000; + }else ShockBarrier_Timer -= diff; + + //NetherBeam_Timer + if(NetherBeam_Timer < diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_NETHER_BEAM); + + NetherBeam_Timer = 4000; + }else NetherBeam_Timer -= diff; + } + } + + if (!InGravityLapse) + DoMeleeAttackIfReady(); + } + } + } +}; + +//Thaladred the Darkener AI +struct TRINITY_DLL_DECL boss_thaladred_the_darkenerAI : public advisorbase_ai +{ + boss_thaladred_the_darkenerAI(Creature *c) : advisorbase_ai(c) {} + + uint32 Gaze_Timer; + uint32 Silence_Timer; + uint32 PsychicBlow_Timer; + + void Reset() + { + Gaze_Timer = 100; + Silence_Timer = 20000; + PsychicBlow_Timer = 10000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_THALADRED_DEATH, m_creature); + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_THALADRED_AGGRO, m_creature); + m_creature->AddThreat(who, 5000000.0f); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim() ) + return; + + //Gaze_Timer + if(Gaze_Timer < diff) + { + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoResetThreat(); + m_creature->AddThreat(target, 5000000.0f); + DoScriptText(EMOTE_THALADRED_GAZE, m_creature, target); + Gaze_Timer = 8500; + } + }else Gaze_Timer -= diff; + + //Silence_Timer + if(Silence_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000; + }else Silence_Timer -= diff; + + //PsychicBlow_Timer + if(PsychicBlow_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_PSYCHIC_BLOW); + PsychicBlow_Timer = 20000+rand()%5000; + }else PsychicBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Lord Sanguinar AI +struct TRINITY_DLL_DECL boss_lord_sanguinarAI : public advisorbase_ai +{ + boss_lord_sanguinarAI(Creature *c) : advisorbase_ai(c){} + + uint32 Fear_Timer; + + void Reset() + { + Fear_Timer = 20000; + advisorbase_ai::Reset(); + } + + void JustDied(Unit* Killer) + { + DoScriptText(SAY_SANGUINAR_DEATH, m_creature); + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_SANGUINAR_AGGRO, m_creature); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim() ) + return; + + //Fear_Timer + if(Fear_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BELLOWING_ROAR); + Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds + }else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Grand Astromancer Capernian AI +struct TRINITY_DLL_DECL boss_grand_astromancer_capernianAI : public advisorbase_ai +{ + boss_grand_astromancer_capernianAI(Creature *c) : advisorbase_ai(c){} + + uint32 Fireball_Timer; + uint32 Conflagration_Timer; + uint32 ArcaneExplosion_Timer; + uint32 Yell_Timer; + bool Yell; + + void Reset() + { + Fireball_Timer = 2000; + Conflagration_Timer = 20000; + ArcaneExplosion_Timer = 5000; + Yell_Timer = 2000; + Yell = false; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_CAPERNIAN_DEATH, m_creature); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (m_creature->Attack(who, true)) + { + m_creature->AddThreat(who, 0.0f); + + if (!InCombat) + { + InCombat = true; + Aggro(who); + } + + DoStartMovement(who, CAPERNIAN_DISTANCE, M_PI/2); + } + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim() ) + return; + + //Yell_Timer + if(!Yell) + { + if(Yell_Timer < diff) + { + DoScriptText(SAY_CAPERNIAN_AGGRO, m_creature); + + Yell = true; + }else Yell_Timer -= diff; + } + + //Fireball_Timer + if(Fireball_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_CAPERNIAN_FIREBALL); + Fireball_Timer = 4000; + }else Fireball_Timer -= diff; + + //Conflagration_Timer + if(Conflagration_Timer < diff) + { + Unit *target = NULL; + target = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if(target && m_creature->IsWithinDistInMap(target, 30)) + DoCast(target, SPELL_CONFLAGRATION); + else + DoCast(m_creature->getVictim(), SPELL_CONFLAGRATION); + + Conflagration_Timer = 10000+rand()%5000; + }else Conflagration_Timer -= diff; + + //ArcaneExplosion_Timer + if(ArcaneExplosion_Timer < diff) + { + bool InMeleeRange = false; + Unit *target = NULL; + std::list<HostilReference*>& m_threatlist = m_creature->getThreatManager().getThreatList(); + for (std::list<HostilReference*>::iterator i = m_threatlist.begin(); i!= m_threatlist.end();++i) + { + Unit* pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid()); + //if in melee range + if(pUnit && pUnit->IsWithinDistInMap(m_creature, 5)) + { + InMeleeRange = true; + target = pUnit; + break; + } + } + + if(InMeleeRange) + DoCast(target, SPELL_ARCANE_EXPLOSION); + + ArcaneExplosion_Timer = 4000+rand()%2000; + }else ArcaneExplosion_Timer -= diff; + + //Do NOT deal any melee damage. + } +}; + +//Master Engineer Telonicus AI +struct TRINITY_DLL_DECL boss_master_engineer_telonicusAI : public advisorbase_ai +{ + boss_master_engineer_telonicusAI(Creature *c) : advisorbase_ai(c){} + + uint32 Bomb_Timer; + uint32 RemoteToy_Timer; + + void Reset() + { + Bomb_Timer = 10000; + RemoteToy_Timer = 5000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_TELONICUS_DEATH, m_creature); + } + + void Aggro(Unit *who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_TELONICUS_AGGRO, m_creature); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, do nothing + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim() ) + return; + + //Bomb_Timer + if(Bomb_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_BOMB); + Bomb_Timer = 25000; + }else Bomb_Timer -= diff; + + //RemoteToy_Timer + if(RemoteToy_Timer < diff) + { + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_REMOTE_TOY); + + RemoteToy_Timer = 10000+rand()%5000; + }else RemoteToy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Flame Strike AI +struct TRINITY_DLL_DECL mob_kael_flamestrikeAI : public ScriptedAI +{ + mob_kael_flamestrikeAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Timer; + bool Casting; + bool KillSelf; + + void Reset() + { + Timer = 5000; + Casting = false; + KillSelf = false; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->setFaction(14); + } + + void Aggro(Unit *who) + { + } + + void MoveInLineOfSight(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + if (!Casting) + { + DoCast(m_creature, SPELL_FLAME_STRIKE_VIS); + Casting = true; + } + + //Timer + if(Timer < diff) + { + if (!KillSelf) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_FLAME_STRIKE_DMG); + }else m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + KillSelf = true; + Timer = 1000; + }else Timer -= diff; + } +}; + +//Phoenix AI +struct TRINITY_DLL_DECL mob_phoenix_tkAI : public ScriptedAI +{ + mob_phoenix_tkAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Cycle_Timer; + uint8 SummonEgg; + + void Reset() + { + Cycle_Timer = 2000; + SummonEgg = 0; + m_creature->CastSpell(m_creature,SPELL_BURN,true); + } + + void Aggro(Unit *who) { } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if(m_creature->GetHealth() < damage && SummonEgg < 2){ + damage = 0; + SummonEgg = 1; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if(SummonEgg < 2){ + if (Cycle_Timer < diff) + { + //spell Burn should possible do this, but it doesn't, so do this for now. + uint32 dmg = urand(4500,5500); + if (m_creature->GetHealth() > dmg) + m_creature->SetHealth(uint32(m_creature->GetHealth()-dmg)); + Cycle_Timer = 2000; + }else Cycle_Timer -= diff; + }else { + if(Cycle_Timer < diff){ + m_creature->SummonCreature(PHOENIX_EGG,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + }else Cycle_Timer -= diff; + } + + if(SummonEgg == 1){ //hack die animation + m_creature->RemoveAllAuras(); + DoStartNoMovement(m_creature->getVictim()); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + SummonEgg = 2; + Cycle_Timer = 1000; + } + if(SummonEgg < 2)DoMeleeAttackIfReady(); + } +}; + +//Phoenix Egg AI +struct TRINITY_DLL_DECL mob_phoenix_egg_tkAI : public ScriptedAI +{ + mob_phoenix_egg_tkAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 Rebirth_Timer; + bool summoned; + + void Reset(){ + Rebirth_Timer = 15000; + summoned = false; + } + + //ignore any + void MoveInLineOfSight(Unit* who) { return; } + + void AttackStart(Unit* who) + { + if (m_creature->Attack(who, false)) + { + if (!InCombat) + { + InCombat = true; + Aggro(who); + } + DoStartNoMovement(who); + } + } + + void Aggro(Unit *who) { } + + void JustSummoned(Creature* summoned) + { + summoned->AddThreat(m_creature->getVictim(), 0.0f); + summoned->CastSpell(summoned,SPELL_REBIRTH,false); + } + + void UpdateAI(const uint32 diff) + { + if (Rebirth_Timer < diff) + { + if(!summoned){ + Creature* Phoenix = m_creature->SummonCreature(PHOENIX,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); + summoned = true; + } + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else Rebirth_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_kaelthas(Creature *_Creature) +{ + return new boss_kaelthasAI (_Creature); +} + +CreatureAI* GetAI_boss_thaladred_the_darkener(Creature *_Creature) +{ + return new boss_thaladred_the_darkenerAI (_Creature); +} + +CreatureAI* GetAI_boss_lord_sanguinar(Creature *_Creature) +{ + return new boss_lord_sanguinarAI (_Creature); +} + +CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature *_Creature) +{ + return new boss_grand_astromancer_capernianAI (_Creature); +} + +CreatureAI* GetAI_boss_master_engineer_telonicus(Creature *_Creature) +{ + return new boss_master_engineer_telonicusAI (_Creature); +} + +CreatureAI* GetAI_mob_kael_flamestrike(Creature *_Creature) +{ + return new mob_kael_flamestrikeAI (_Creature); +} + +CreatureAI* GetAI_mob_phoenix_tk(Creature *_Creature) +{ + return new mob_phoenix_tkAI (_Creature); +} + +CreatureAI* GetAI_mob_phoenix_egg_tk(Creature *_Creature) +{ + return new mob_phoenix_egg_tkAI (_Creature); +} +void AddSC_boss_kaelthas() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_kaelthas"; + newscript->GetAI = &GetAI_boss_kaelthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_thaladred_the_darkener"; + newscript->GetAI = &GetAI_boss_thaladred_the_darkener; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_lord_sanguinar"; + newscript->GetAI = &GetAI_boss_lord_sanguinar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_grand_astromancer_capernian"; + newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_master_engineer_telonicus"; + newscript->GetAI = &GetAI_boss_master_engineer_telonicus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name= "mob_kael_flamestrike"; + newscript->GetAI = &GetAI_mob_kael_flamestrike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_phoenix_tk"; + newscript->GetAI = &GetAI_mob_phoenix_tk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_egg_tk"; + newscript->GetAI = &GetAI_mob_phoenix_egg_tk; + newscript->RegisterSelf(); +} + diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp index fe42ae53dd7..70cba44e8d6 100644 --- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_bug_trio.cpp @@ -176,7 +176,7 @@ struct TRINITY_DLL_DECL boss_vemAI : public ScriptedAI if(target) { DoCast(target, SPELL_CHARGE); - m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + //m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); AttackStart(target); } diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp index a8542f14fe6..35efe3f1dab 100644 --- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_ouro.cpp @@ -103,8 +103,7 @@ struct TRINITY_DLL_DECL boss_ouroAI : public ScriptedAI Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0); - m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); - m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); ChangeTarget_Timer = 10000 + rand()%10000; }else ChangeTarget_Timer -= diff; diff --git a/src/bindings/scripts/scripts/zone/undercity/undercity.cpp b/src/bindings/scripts/scripts/zone/undercity/undercity.cpp index 590bf5608c0..d000db35ed2 100644 --- a/src/bindings/scripts/scripts/zone/undercity/undercity.cpp +++ b/src/bindings/scripts/scripts/zone/undercity/undercity.cpp @@ -86,7 +86,7 @@ struct TRINITY_DLL_DECL npc_lady_sylvanas_windrunnerAI : public ScriptedAI { if( Unit* target = Unit::GetUnit(*summoned,targetGUID) ) { - target->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), myZ+15.0,0,0,0); + target->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), myZ+15.0,0); target->Relocate(target->GetPositionX(), target->GetPositionY(), myZ+15.0); summoned->CastSpell(target, SPELL_RIBBON_OF_SOULS, false); } diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp index bd0bcb0ba0f..481fa508864 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp @@ -311,7 +311,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI if (target) { target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0,0,0); + target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0); } Unit *Cloud = m_creature->SummonTrigger(x, y, m_creature->GetPositionZ()+16, 0, 15000); if(Cloud) diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp index fe38ef9771a..9a63ea4ad70 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp @@ -365,8 +365,7 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI m_creature->AttackStop(); m_creature->GetMotionMaster()->Clear(); - m_creature->Relocate(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2],0); - m_creature->SendMonsterMove(JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2],0,0,0); + DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); m_creature->StopMoving(); m_creature->CastSpell(m_creature, SPELL_FIRE_BOMB_CHANNEL, false); //DoTeleportPlayer(m_creature, JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2], 0); @@ -399,8 +398,7 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI m_creature->AttackStop(); m_creature->GetMotionMaster()->Clear(); - m_creature->Relocate(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2],0); - m_creature->SendMonsterMove(JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2],0,0,0); + DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); m_creature->StopMoving(); m_creature->CastSpell(m_creature, SPELL_HATCH_ALL, false); HatchAllEggs(2); diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp index fd7326a0b7d..2bb04ee4bb9 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp @@ -338,8 +338,7 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI case 2: case 3: case 4: - m_creature->Relocate(CENTER_X, CENTER_Y, CENTER_Z,0); - m_creature->SendMonsterMove(CENTER_X, CENTER_Y, CENTER_Z,0,0,100); + DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100); DoResetThreat(); m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); m_creature->RemoveAurasDueToSpell(Transform[Phase].unaura); diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp index 3f340a9daf3..b7fe7d8f31e 100644 --- a/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_jeklik.cpp @@ -106,9 +106,6 @@ struct TRINITY_DLL_DECL boss_jeklikAI : public ScriptedAI if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) { DoCast(target,SPELL_CHARGE); - - m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); - m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); AttackStart(target); } diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp index f6d606490c8..81bc9dc7c25 100644 --- a/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_mandokir.cpp @@ -165,7 +165,7 @@ struct TRINITY_DLL_DECL boss_mandokirAI : public ScriptedAI else { DoCast(pUnit,SPELL_CHARGE); - m_creature->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); + //m_creature->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); AttackStart(pUnit); } } diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp index 268c5c13b00..b2e66b1bbdb 100644 --- a/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp @@ -83,8 +83,7 @@ struct TRINITY_DLL_DECL boss_renatakiAI : public ScriptedAI target = SelectUnit(SELECT_TARGET_RANDOM,0); if (target) { - m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); - m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); + DoTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); DoCast(target,SPELL_AMBUSH); } diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp index f72f5b5f28a..8319ac8f174 100644 --- a/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_thekal.cpp @@ -194,7 +194,6 @@ struct TRINITY_DLL_DECL boss_thekalAI : public ScriptedAI if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) { DoCast(target,SPELL_CHARGE); - m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); DoResetThreat(); AttackStart(target); } diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index ae3ddc54165..9244978868e 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1151,7 +1151,7 @@ void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint3 m_startMove = getMSTime(); m_moveTime = time;*/ - SendMonsterMove(x, y, z, type, MovementFlags, time); + SendMonsterMove(x, y, z, time); } Player *Creature::GetLootRecipient() const diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 5a26a28159f..116d26f4975 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -148,7 +148,13 @@ Map* MapInstanced::GetInstance(const WorldObject* obj) // instantiate or find existing bg map for player // the instance id is set in battlegroundid NewInstanceId = player->GetBattleGroundId(); - assert(NewInstanceId); + if(!NewInstanceId) + { + if(player->GetSession()->PlayerLoading()) + return NULL; + else + assert(NewInstanceId); + } map = _FindMap(NewInstanceId); if(!map) map = CreateBattleGround(NewInstanceId); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b5046a18491..aa04784fb97 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2111,25 +2111,6 @@ void Spell::cancel() finish(false); - // Unsummon summon as possessed creatures on spell cancel - if(m_caster->GetTypeId() == TYPEID_PLAYER) - { - for(int i = 0; i < 3; ++i) - { - if(m_spellInfo->Effect[i] == SPELL_EFFECT_SUMMON && - (m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED || - m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED2 || - m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED3)) - { - ((Player*)m_caster)->StopCastingCharm(); - break; - // Possession is removed in the UnSummon function - //if (m_caster->GetCharm()) - // ((TemporarySummon*)m_caster->GetCharm())->UnSummon(); - } - } - } - m_caster->RemoveDynObject(m_spellInfo->Id); m_caster->RemoveGameObject(m_spellInfo->Id,true); } diff --git a/src/game/Traveller.h b/src/game/Traveller.h index d5e5036447f..ff9c426e967 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -107,7 +107,7 @@ template<> inline void Traveller<Player>::MoveTo(float x, float y, float z, uint32 t) { //Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags - i_traveller.SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, t); + i_traveller.SendMonsterMove(x, y, z, t); } typedef Traveller<Creature> CreatureTraveller; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 8bc70d365cd..92bf97e9e02 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -300,10 +300,41 @@ void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFl transitTime = static_cast<uint32>(dist / speed + 0.5); } //float orientation = (float)atan2((double)dy, (double)dx); - SendMonsterMove(x, y, z, 0, MovementFlags, transitTime, player); + SendMonsterMove(x, y, z, transitTime, player); } -void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player) +void Unit::SendMonsterStop() +{ + WorldPacket data( SMSG_MONSTER_MOVE, (17 + GetPackGUID().size()) ); + data.append(GetPackGUID()); + data << GetPositionX() << GetPositionY() << GetPositionZ(); + data << getMSTime(); + data << uint8(1); + SendMessageToSet(&data, true); +} + +void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player) +{ + WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) ); + data.append(GetPackGUID()); + + data << GetPositionX() << GetPositionY() << GetPositionZ(); + data << getMSTime(); + + data << uint8(0); + data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? MOVEFLAG_FLY : MOVEFLAG_WALK); + + data << Time; // Time in between points + data << uint32(1); // 1 single waypoint + data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B + + if(player) + player->GetSession()->SendPacket(&data); + else + SendMessageToSet( &data, true ); +} + +/*void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player) { WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) ); data.append(GetPackGUID()); @@ -337,7 +368,7 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 ty } //Movement Flags (0x0 = walk, 0x100 = run, 0x200 = fly/swim) - data << uint32(GetTypeId() == TYPEID_PLAYER ? MOVEMENTFLAG_WALK_MODE : MovementFlags); + data << uint32((MovementFlags & MOVEMENTFLAG_LEVITATING) ? MOVEFLAG_FLY : MOVEFLAG_WALK); data << Time; // Time in between points data << uint32(1); // 1 single waypoint @@ -347,9 +378,9 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 ty player->GetSession()->SendPacket(&data); else SendMessageToSet( &data, true ); -} +}*/ -void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags) +void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end) { uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32); @@ -361,13 +392,10 @@ void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uin data << GetPositionY(); data << GetPositionZ(); - // unknown field - unrelated to orientation - // seems to increment about 1000 for every 1.7 seconds - // for now, we'll just use mstime data << getMSTime(); data << uint8( 0 ); - data << uint32( MovementFlags ); + data << uint32(((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) || isInFlight())? MOVEFLAG_FLY : MOVEFLAG_WALK); data << uint32( traveltime ); data << uint32( pathSize ); data.append( (char*)path.GetNodes(start), pathSize * 4 * 3 ); @@ -4150,6 +4178,22 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) } } } + + // Unsummon summon as possessed creatures on spell cancel + if(caster->GetTypeId() == TYPEID_PLAYER) + { + for(int i = 0; i < 3; ++i) + { + if(AurSpellInfo->Effect[i] == SPELL_EFFECT_SUMMON && + (AurSpellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED || + AurSpellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED2 || + AurSpellInfo->EffectMiscValueB[i] == SUMMON_TYPE_POSESSED3)) + { + ((Player*)caster)->StopCastingCharm(); + break; + } + } + } } } @@ -11425,7 +11469,7 @@ void Unit::StopMoving() // Relocate(GetPositionX(), GetPositionY(), z); Relocate(GetPositionX(), GetPositionY(),GetPositionZ()); - SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), 0, true, 0); + SendMonsterStop(); // update position and orientation; WorldPacket data; diff --git a/src/game/Unit.h b/src/game/Unit.h index f199e19070b..5b54cc013a4 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -582,6 +582,17 @@ enum NPCFlags UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures }; +enum MoveFlags +{ + MOVEFLAG_NONE = 0x00000000, + MOVEFLAG_SLIDE = 0x00000002, + MOVEFLAG_MARCH_ON_SPOT = 0x00000004, + MOVEFLAG_JUMP = 0x00000008, + MOVEFLAG_WALK = 0x00000100, + MOVEFLAG_FLY = 0x00000200, //For dragon (+walk = glide) + MOVEFLAG_ORIENTATION = 0x00000400, //Fix orientation +}; + enum MovementFlags { MOVEMENTFLAG_NONE = 0x00000000, @@ -593,8 +604,8 @@ enum MovementFlags MOVEMENTFLAG_RIGHT = 0x00000020, MOVEMENTFLAG_PITCH_UP = 0x00000040, MOVEMENTFLAG_PITCH_DOWN = 0x00000080, - MOVEMENTFLAG_WALK_MODE = 0x00000100, // Walking - MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures + MOVEMENTFLAG_WALK_MODE = 0x00000100, + MOVEMENTFLAG_ONTRANSPORT = 0x00000200, MOVEMENTFLAG_LEVITATING = 0x00000400, MOVEMENTFLAG_FLY_UNK1 = 0x00000800, MOVEMENTFLAG_JUMPING = 0x00001000, @@ -1124,8 +1135,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); - void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); - void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags); + void SendMonsterStop(); + void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL); + //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); + void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end); void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime = 0, Player* player = NULL); void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL); diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 9810d83dcd1..5aa7666db10 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -249,7 +249,7 @@ FlightPathMovementGenerator::Initialize(Player &player) // do not send movement, it was sent already i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false); - player.SendMonsterMoveByPath(GetPath(),GetCurrentNode(),GetPathAtMapEnd(),MOVEMENTFLAG_WALK_MODE|MOVEMENTFLAG_ONTRANSPORT); + player.SendMonsterMoveByPath(GetPath(),GetCurrentNode(),GetPathAtMapEnd()); } void FlightPathMovementGenerator::Finalize(Player & player) |