diff --git a/sql/world.sql b/sql/world.sql index 8663a34e60..d19bb481dc 100644 --- a/sql/world.sql +++ b/sql/world.sql @@ -515,6 +515,29 @@ LOCK TABLES `creature_equip_template` WRITE; /*!40000 ALTER TABLE `creature_equip_template` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `creature_formations` +-- + +DROP TABLE IF EXISTS `creature_formations`; +CREATE TABLE `creature_formations` ( + `leaderGUID` int(11) unsigned NOT NULL, + `memberGUID` int(11) unsigned NOT NULL, + `dist` float unsigned NOT NULL, + `angle` float unsigned NOT NULL, + `groupAI` int(11) unsigned NOT NULL, + PRIMARY KEY (`follower`)); + +-- +-- Dumping data for table `creature_formations` +-- + +LOCK TABLES `creature_formations` WRITE; +/*!40000 ALTER TABLE `creature_formations` DISABLE KEYS */; +/*!40000 ALTER TABLE `creature_formations` ENABLE KEYS */; +UNLOCK TABLES; + + -- -- Table structure for table `creature_involvedrelation` -- @@ -585,63 +608,6 @@ LOCK TABLES `creature_model_info` WRITE; /*!40000 ALTER TABLE `creature_model_info` ENABLE KEYS */; UNLOCK TABLES; --- --- Table structure for table `waypoint_data` --- - -DROP TABLE IF EXISTS `waypoint_data`; -CREATE TABLE `waypoint_data` ( - `id` int(10) unsigned NOT NULL default '0' COMMENT 'Creature GUID', - `point` mediumint(8) unsigned NOT NULL default '0', - `position_x` float NOT NULL default '0', - `position_y` float NOT NULL default '0', - `position_z` float NOT NULL default '0', - `delay` int(10) unsigned NOT NULL default '0', - `move_flag` tinyint(1) NOT NULL default '0', - `action` int(11) NOT NULL default '0', - `action_chance` smallint(3) NOT NULL default '100', - `wpguid` int(11) NOT NULL default '0' -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- --- Dumping data for table `creature_movement` --- - -LOCK TABLES `waypoint_data` WRITE; -/*!40000 ALTER TABLE `waypoint_data` DISABLE KEYS */; -/*!40000 ALTER TABLE `waypoint_data` ENABLE KEYS */; -UNLOCK TABLES; - - --- --- Table structure for table `waypoint_scripts` --- - -DROP TABLE IF EXISTS `waypoint_scripts`; -CREATE TABLE `waypoint_scripts` ( - `id` int(11) unsigned NOT NULL default '0', - `delay` int(11) unsigned NOT NULL default '0', - `command` int(11) unsigned NOT NULL default '0', - `datalong` int(11) unsigned NOT NULL default '0', - `datalong2` int(11) unsigned NOT NULL default '0', - `dataint` int(11) unsigned NOT NULL default '0', - `x` float NOT NULL default '0', - `y` float NOT NULL default '0', - `z` float NOT NULL default '0', - `o` float NOT NULL default '0', - `guid` int(11) NOT NULL default '0', - PRIMARY KEY (`guid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- --- Dumping data for table `creature_movement` --- - -LOCK TABLES `waypoint_scripts` WRITE; -/*!40000 ALTER TABLE `waypoint_scripts` DISABLE KEYS */; -/*!40000 ALTER TABLE `waypoint_scripts` ENABLE KEYS */; -UNLOCK TABLES; - -- -- Table structure for table `creature_onkill_reputation` -- @@ -843,6 +809,7 @@ CREATE TABLE `custom_texts` ( `sound` mediumint(8) unsigned NOT NULL default '0', `type` tinyint unsigned NOT NULL default '0', `language` tinyint unsigned NOT NULL default '0', + `emote` smallint(5) UNSIGNED NOT NULL default '0', `comment` text, PRIMARY KEY (`entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Custom Texts'; @@ -856,24 +823,6 @@ LOCK TABLES `custom_texts` WRITE; /*!40000 ALTER TABLE `custom_texts` ENABLE KEYS */; UNLOCK TABLES; --- --- Table structure for table `db_version` --- - -DROP TABLE IF EXISTS `db_version`; -CREATE TABLE `db_version` ( - `version` varchar(120) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; - --- --- Dumping data for table `db_version` --- - -LOCK TABLES `db_version` WRITE; -/*!40000 ALTER TABLE `db_version` DISABLE KEYS */; -/*!40000 ALTER TABLE `db_version` ENABLE KEYS */; -UNLOCK TABLES; - -- -- Table structure for table `disenchant_loot_template` -- @@ -1054,38 +1003,6 @@ LOCK TABLES `eventai_texts` WRITE; /*!40000 ALTER TABLE `eventai_texts` ENABLE KEYS */; UNLOCK TABLES; --- --- Table structure for table `script_texts` --- - -DROP TABLE IF EXISTS `script_texts`; -CREATE TABLE `script_texts` ( - `entry` mediumint(8) NOT NULL, - `content_default` text NOT NULL, - `content_loc1` text, - `content_loc2` text, - `content_loc3` text, - `content_loc4` text, - `content_loc5` text, - `content_loc6` text, - `content_loc7` text, - `content_loc8` text, - `sound` mediumint(8) unsigned NOT NULL default '0', - `type` tinyint unsigned NOT NULL default '0', - `language` tinyint unsigned NOT NULL default '0', - `comment` text, - PRIMARY KEY (`entry`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts'; - --- --- Dumping data for table `script_texts` --- - -LOCK TABLES `script_texts` WRITE; -/*!40000 ALTER TABLE `script_texts` DISABLE KEYS */; -/*!40000 ALTER TABLE `script_texts` ENABLE KEYS */; -UNLOCK TABLES; - -- -- Table structure for table `exploration_basexp` -- @@ -1230,6 +1147,26 @@ LOCK TABLES `game_event` WRITE; /*!40000 ALTER TABLE `game_event` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `game_event_battleground_holiday` +-- + +DROP TABLE IF EXISTS `game_event_battleground_holiday`; +CREATE TABLE `game_event_battleground_holiday` ( + `event` int(10) unsigned NOT NULL, + `bgflag` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`event`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `game_event_battleground_holiday` +-- + +LOCK TABLES `game_event_battleground_holiday` WRITE; +/*!40000 ALTER TABLE `game_event_battleground_holiday` DISABLE KEYS */; +/*!40000 ALTER TABLE `game_event_battleground_holiday` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `game_event_condition` -- @@ -13078,24 +13015,6 @@ LOCK TABLES `reserved_name` WRITE; /*!40000 ALTER TABLE `reserved_name` ENABLE KEYS */; UNLOCK TABLES; --- --- Table structure for table `script_db_version` --- - -DROP TABLE IF EXISTS `script_db_version`; -CREATE TABLE `script_db_version` ( - `version` varchar(255) NOT NULL default '' COMMENT 'Database version string' -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- --- Dumping data for table `script_db_version` --- - -LOCK TABLES `script_db_version` WRITE; -/*!40000 ALTER TABLE `script_db_version` DISABLE KEYS */; -/*!40000 ALTER TABLE `script_db_version` ENABLE KEYS */; -UNLOCK TABLES; - -- -- Table structure for table `script_texts` -- @@ -13112,9 +13031,10 @@ CREATE TABLE `script_texts` ( `content_loc6` text, `content_loc7` text, `content_loc8` text, - `sound` tinyint(3) unsigned NOT NULL default '0', + `sound` mediumint(8) unsigned NOT NULL default '0', `type` tinyint(3) unsigned NOT NULL default '0', - `language` tinyint(3) unsigned NOT NULL default '0', + `language` smallint(5) unsigned NOT NULL default '0', + `emote` smallint(5) UNSIGNED NOT NULL default '0', `comment` text, PRIMARY KEY (`entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts'; @@ -13242,26 +13162,24 @@ LOCK TABLES `spell_affect` WRITE; UNLOCK TABLES; -- --- Table structure for table `spell_chain` +-- Table structure for table `spell_required` -- -DROP TABLE IF EXISTS `spell_chain`; -CREATE TABLE `spell_chain` ( +DROP TABLE IF EXISTS `spell_required`; +CREATE TABLE `spell_required` ( `spell_id` mediumint(9) NOT NULL default '0', `prev_spell` mediumint(9) NOT NULL default '0', - `first_spell` mediumint(9) NOT NULL default '0', - `rank` tinyint(4) NOT NULL default '0', `req_spell` mediumint(9) NOT NULL default '0', PRIMARY KEY (`spell_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell Additinal Data'; -- --- Dumping data for table `spell_chain` +-- Dumping data for table `spell_required` -- -LOCK TABLES `spell_chain` WRITE; -/*!40000 ALTER TABLE `spell_chain` DISABLE KEYS */; -/*!40000 ALTER TABLE `spell_chain` ENABLE KEYS */; +LOCK TABLES `spell_required` WRITE; +/*!40000 ALTER TABLE `spell_required` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_required` ENABLE KEYS */; UNLOCK TABLES; -- @@ -13751,6 +13669,26 @@ LOCK TABLES `trinity_string` WRITE; /*!40000 ALTER TABLE `trinity_string` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `transport_events` +-- + +DROP TABLE IF EXISTS `transport_events`; +CREATE TABLE `transport_events` ( + `entry` int(11) unsigned NOT NULL default '0', + `waypoint_id` int(11) unsigned NOT NULL default '0', + `event_id` int(11) unsigned NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `transport_events` +-- + +LOCK TABLES `trinity_string` WRITE; +/*!40000 ALTER TABLE `transport_events` DISABLE KEYS */; +/*!40000 ALTER TABLE `transport_events` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `uptime` -- @@ -13772,6 +13710,84 @@ LOCK TABLES `uptime` WRITE; /*!40000 ALTER TABLE `uptime` DISABLE KEYS */; /*!40000 ALTER TABLE `uptime` ENABLE KEYS */; UNLOCK TABLES; + +-- +-- Table structure for table `version` +-- + +DROP TABLE IF EXISTS `version`; +CREATE TABLE `version` ( + `core_version` varchar(120) default NULL COMMENT 'Core revision dumped at startup.', + `core_revision` BIGINT UNSIGNED default '0', + `db_version` varchar(120) default NULL COMMENT 'Version of world DB.', + `script_version` varchar(120) default NULL COMMENT 'Version of scripts DB.' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Version Notes'; + +-- +-- Dumping data for table `version` +-- + +LOCK TABLES `version` WRITE; +/*!40000 ALTER TABLE `version` DISABLE KEYS */; +/*!40000 ALTER TABLE `version` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `waypoint_data` +-- + +DROP TABLE IF EXISTS `waypoint_data`; +CREATE TABLE `waypoint_data` ( + `id` int(10) unsigned NOT NULL default '0' COMMENT 'Creature GUID', + `point` mediumint(8) unsigned NOT NULL default '0', + `position_x` float NOT NULL default '0', + `position_y` float NOT NULL default '0', + `position_z` float NOT NULL default '0', + `delay` int(10) unsigned NOT NULL default '0', + `move_flag` tinyint(1) NOT NULL default '0', + `action` int(11) NOT NULL default '0', + `action_chance` smallint(3) NOT NULL default '100', + `wpguid` int(11) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `waypoint_data` +-- + +LOCK TABLES `waypoint_scripts` WRITE; +/*!40000 ALTER TABLE `waypoint_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `waypoint_scripts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `waypoint_scripts` +-- + +DROP TABLE IF EXISTS `waypoint_scripts`; +CREATE TABLE `waypoint_scripts` ( + `id` int(11) unsigned NOT NULL default '0', + `delay` int(11) unsigned NOT NULL default '0', + `command` int(11) unsigned NOT NULL default '0', + `datalong` int(11) unsigned NOT NULL default '0', + `datalong2` int(11) unsigned NOT NULL default '0', + `dataint` int(11) unsigned NOT NULL default '0', + `x` float NOT NULL default '0', + `y` float NOT NULL default '0', + `z` float NOT NULL default '0', + `o` float NOT NULL default '0', + `guid` int(11) NOT NULL default '0', + PRIMARY KEY (`guid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `waypoint_scripts` +-- + +LOCK TABLES `waypoint_scripts` WRITE; +/*!40000 ALTER TABLE `waypoint_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `waypoint_scripts` ENABLE KEYS */; +UNLOCK TABLES; + /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index db5beb64ec..efb6ef36fa 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 5639ad0f1f..03039fd709 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 53953e04d5..3b017c48a6 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 a22935d746..6592e3783f 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 ad437f2427..b0b8135396 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 962d05e6c8..9d66533972 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 32612e158f..e0ee20518b 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 b60da3d769..8fadb5192f 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 - * 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 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 PhoenixList; - - Trinity::AllCreaturesOfEntryInRange check(m_creature, PHOENIX, 50); - Trinity::CreatureListSearcher searcher(m_creature, PhoenixList, check); - TypeContainerVisitor, GridTypeMapContainer> visitor(searcher); - - CellLock cell_lock(cell, pair); - cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap())); - - if(!PhoenixList.empty()) - { - for(std::list::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::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& m_threatlist = m_creature->getThreatManager().getThreatList(); - for (std::list::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 + * 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 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 PhoenixList; + + Trinity::AllCreaturesOfEntryInRange check(m_creature, PHOENIX, 50); + Trinity::CreatureListSearcher searcher(m_creature, PhoenixList, check); + TypeContainerVisitor, GridTypeMapContainer> visitor(searcher); + + CellLock cell_lock(cell, pair); + cell_lock->Visit(cell_lock, visitor, *(m_creature->GetMap())); + + if(!PhoenixList.empty()) + { + for(std::list::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::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& m_threatlist = m_creature->getThreatManager().getThreatList(); + for (std::list::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 fe42ae53dd..70cba44e8d 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 a8542f14fe..35efe3f1da 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 590bf5608c..d000db35ed 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 bd0bcb0ba0..481fa50886 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 fe38ef9771..9a63ea4ad7 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 fd7326a0b7..2bb04ee4bb 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 3f340a9daf..b7fe7d8f31 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 f6d606490c..81bc9dc7c2 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 268c5c13b0..b2e66b1bbd 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 f72f5b5f28..8319ac8f17 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 ae3ddc5416..9244978868 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 5a26a28159..116d26f497 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 b5046a1849..aa04784fb9 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 d5e5036447..ff9c426e96 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -107,7 +107,7 @@ template<> inline void Traveller::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 CreatureTraveller; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 8bc70d365c..92bf97e9e0 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(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 f199e19070..5b54cc013a 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 9810d83dcd..5aa7666db1 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)