From c86230208f1ca797cc2f350fbc5f8e090816fa95 Mon Sep 17 00:00:00 2001 From: Gacko Date: Sat, 5 Jan 2013 18:03:11 +0100 Subject: [PATCH] Script: Novos rewrite --- ...2013_01_04_02_world_novos_the_summoner.sql | 63 +++ .../Northrend/DraktharonKeep/boss_novos.cpp | 518 +++++++++--------- .../DraktharonKeep/drak_tharon_keep.h | 9 +- .../instance_drak_tharon_keep.cpp | 142 +++-- 4 files changed, 430 insertions(+), 302 deletions(-) create mode 100644 sql/updates/world/2013_01_04_02_world_novos_the_summoner.sql diff --git a/sql/updates/world/2013_01_04_02_world_novos_the_summoner.sql b/sql/updates/world/2013_01_04_02_world_novos_the_summoner.sql new file mode 100644 index 00000000000..49f8b21e3a7 --- /dev/null +++ b/sql/updates/world/2013_01_04_02_world_novos_the_summoner.sql @@ -0,0 +1,63 @@ +-- Summon minions +DELETE FROM `spell_script_names` WHERE `spell_id`=59910; +INSERT INTO `spell_script_names`(`spell_id`,`ScriptName`) VALUE +(59910,'spell_summon_minions'); + +-- Heroic spells +DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (49198,49034,49037,50089,49668,51363) OR `spellid0` IN (49198,49034,49037,50089,49668,51363); +INSERT INTO `spelldifficulty_dbc`(`id`,`spellid0`,`spellid1`) VALUES +(49198,49198,59909), -- Arcance Blast +(49034,49034,59854), -- Blizzard +(49037,49037,59855), -- Frostbolt +(50089,50089,59856), -- Wrath of Misery +(49668,49668,59004), -- Flash of Darkness +(51363,51363,59016); -- Shadow Bolt + +-- Script assignment for summoners +UPDATE `creature_template` SET `ScriptName`='npc_crystal_channel_target',`AIName`='' WHERE `entry`=26712; + +-- Spawn summoner for Crystal Handlers +SET @GUID = 40153; +DELETE FROM `creature` WHERE `guid`=@GUID; +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `modelid`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `curhealth`) VALUE +(@GUID,26712,600,3,17188,-341.31,-724.4,28.57,3.78,3600,8982); + +-- Check instance script for achievement Oh Novos +DELETE FROM `achievement_criteria_data` WHERE `criteria_id`=7361; +INSERT INTO `achievement_criteria_data`(`criteria_id`,`type`,`ScriptName`) VALUE +(7361,11,'achievement_oh_novos'); + +-- Waypoints for summoned adds +DELETE FROM `waypoint_data` WHERE `id` IN(2759700,2759800,2760000,2662700); +INSERT INTO `waypoint_data`(`id`,`point`,`position_x`,`position_y`,`position_z`) VALUES +(2759700,1,-379.473,-810.974,59.7612), +(2759700,2,-379.449,-791.535,44.1756), +(2759700,3,-379.448,-790.328,44.1756), +(2759700,4,-379.426,-772.338,28.5884), +(2759700,5,-379.415,-763.518,28.5884), +(2760000,1,-376.571,-810.681,59.6673), +(2760000,2,-375.627,-791.874,44.1756), +(2760000,3,-375.629,-790.273,44.1434), +(2760000,4,-375.402,-771.145,28.5895), +(2760000,5,-375.337,-765.027,28.5895), +(2759800,1,-382.303,-810.815,59.7628), +(2759800,2,-382.324,-791.595,44.1756), +(2759800,3,-382.326,-790.331,44.1746), +(2759800,4,-383.037,-770.382,28.5884), +(2759800,5,-383.140,-765.399,28.5884), +(2662700,1,-346.977,-733.319,28.5838), +(2662700,2,-363.009,-765.202,28.5907), +(2662700,3,-378.269,-765.701,28.5893); + +-- SAI for Crystal Handlers and Risen Shadowcasters +UPDATE `creature_template` SET `AIName`='SmartAI',`ScriptName`='' WHERE `entry` IN (26627,27600); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (26627,27600) AND `source_type`=0; +INSERT INTO `smart_scripts`(`entryorguid`,`event_type`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`target_type`,`comment`) VALUES +(26627,0,1000,1000,5000,5000,11,49668,2,'Crystal Handler - In fight - After 1s then every 5s - Cast Flash of Darkness - On victim'), +(27600,0,1000,1000,5000,5000,11,51363,2,'Risen Shadowcaster - In fight - After 1s then every 5s - Cast Shadow Bolt - On victim'); + +-- Conditions for beam spell +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=52106; +INSERT INTO `conditions`(`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`Comment`) VALUES +(13,1,52106,31,0,3,26712,0,'Beam Channel target has to be Crystal Channel Target'), +(13,1,52106,35,1,0, 18,1,'Beam Channel target must not be self'); diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index 6d33efb4515..8a858d4d5eb 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -19,226 +19,240 @@ #include "ScriptedCreature.h" #include "drak_tharon_keep.h" -enum Spells +enum Misc { - SPELL_ARCANE_BLAST = 49198, - H_SPELL_ARCANE_BLAST = 59909, - SPELL_ARCANE_FIELD = 47346, - SPELL_BLIZZARD = 49034, - H_SPELL_BLIZZARD = 59854, - SPELL_FROSTBOLT = 49037, - H_SPELL_FROSTBOLT = 59855, - SPELL_WRATH_OF_MISERY = 50089, - H_SPELL_WRATH_OF_MISERY = 59856, - SPELL_SUMMON_MINIONS = 59910 //Summons an army of Fetid Troll Corpses to assist the caster. -}; - -//not in db -enum Yells -{ - SAY_AGGRO = 0, - SAY_KILL = 1, - SAY_DEATH = 2, - SAY_NECRO_ADD = 3, - SAY_REUBBLE = 4 + ACTION_RESET_CRYSTALS, + ACTION_ACTIVATE_CRYSTAL, + ACTION_DEACTIVATE, + EVENT_ATTACK, + EVENT_SUMMON_MINIONS, + DATA_NOVOS_ACHIEV }; enum Creatures { - CREATURE_RISEN_SHADOWCASTER = 27600, - CREATURE_FETID_TROLL_CORPSE = 27598, - CREATURE_HULKING_CORPSE = 27597, - CREATURE_CRYSTAL_HANDLER = 26627 + NPC_CRYSTAL_CHANNEL_TARGET = 26712, + NPC_FETID_TROLL_CORPSE = 27597, + NPC_RISEN_SHADOWCASTER = 27600, + NPC_HULKING_CORPSE = 27597 }; -enum CombatPhase +enum Spells { - IDLE, - PHASE_1, - PHASE_2 + SPELL_BEAM_CHANNEL = 52106, + SPELL_ARCANE_FIELD = 47346, + + SPELL_SUMMON_RISEN_SHADOWCASTER = 49105, + SPELL_SUMMON_FETID_TROLL_CORPSE = 49103, + SPELL_SUMMON_HULKING_CORPSE = 49104, + SPELL_SUMMON_CRYSTAL_HANDLER = 49179, + + SPELL_ARCANE_BLAST = 49198, + SPELL_BLIZZARD = 49034, + SPELL_FROSTBOLT = 49037, + SPELL_WRATH_OF_MISERY = 50089, + SPELL_SUMMON_MINIONS = 59910 }; -#define ACTION_MINION_REACHED 1 -#define DATA_OH_NOVOS 2 +struct SummonerInfo +{ + uint32 data, spell, timer; +}; -static Position AddSpawnPoint = { -379.20f, -816.76f, 59.70f, 0.0f }; -static Position CrystalHandlerSpawnPoint = { -326.626343f, -709.956604f, 27.813314f, 0.0f }; -static Position AddDestinyPoint = { -379.314545f, -772.577637f, 28.58837f, 0.0f }; +const SummonerInfo summoners[] = { + { DATA_NOVOS_SUMMONER_1, SPELL_SUMMON_RISEN_SHADOWCASTER, 15000 }, + { DATA_NOVOS_SUMMONER_2, SPELL_SUMMON_FETID_TROLL_CORPSE, 5000 }, + { DATA_NOVOS_SUMMONER_3, SPELL_SUMMON_HULKING_CORPSE, 30000 }, + { DATA_NOVOS_SUMMONER_4, SPELL_SUMMON_CRYSTAL_HANDLER, 30000 } +}; + +#define MAX_Y_COORD_OH_NOVOS -771.95f class boss_novos : public CreatureScript { public: boss_novos() : CreatureScript("boss_novos") { } - struct boss_novosAI : public Scripted_NoMovementAI + struct boss_novosAI : public BossAI { - boss_novosAI(Creature* creature) : Scripted_NoMovementAI(creature), lSummons(me) - { - instance = creature->GetInstanceScript(); - } - - uint32 uiTimer; - uint32 uiCrystalHandlerTimer; - uint8 crystalHandlerAmount; - - bool ohNovos; - - SummonList lSummons; - - std::list luiCrystals; - - CombatPhase Phase; - - InstanceScript* instance; + boss_novosAI(Creature* creature) : BossAI(creature, DATA_NOVOS_EVENT) {} void Reset() { - Phase = IDLE; - luiCrystals.clear(); - ohNovos = true; - me->CastStop(); - lSummons.DespawnAll(); - crystalHandlerAmount = 0; + events.Reset(); + summons.DespawnAll(); + instance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (instance) - { - instance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); - for (uint8 n = 0; n < 4; ++n) - luiCrystals.push_back(instance->GetData64(DATA_NOVOS_CRYSTAL_1 + n)); - for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject* temp = instance->instance->GetGameObject(*itr)) - temp->SetGoState(GO_STATE_READY); - } - } + _ohNovos = true; + _crystalHandlerCount = 0; + SetCrystalsStatus(false); + SetSummonerStatus(false); + SetBubbled(false); } - void EnterCombat(Unit* /*who*/) + void EnterCombat(Unit* /* victim */) { - Talk(SAY_AGGRO); - Phase = PHASE_1; - uiCrystalHandlerTimer = 30*IN_MILLISECONDS; - uiTimer = 1*IN_MILLISECONDS; - DoCast(SPELL_ARCANE_FIELD); - if (instance) - { - for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject* temp = instance->instance->GetGameObject(*itr)) - temp->SetGoState(GO_STATE_ACTIVE); - } - instance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); - } - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setActive(true); + DoZoneInCombat(); + instance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); + + SetCrystalsStatus(true); + SetSummonerStatus(true); + SetBubbled(true); + } + + void AttackStart(Unit* target) + { + if (!target) + return; + + if (me->Attack(target, true)) + DoStartNoMovement(target); } void UpdateAI(const uint32 diff) { - switch (Phase) - { - case PHASE_1: - if (uiTimer <= diff) - { - Creature* summon = me->SummonCreature(RAND(CREATURE_FETID_TROLL_CORPSE, CREATURE_HULKING_CORPSE, CREATURE_RISEN_SHADOWCASTER), AddSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20*IN_MILLISECONDS); - summon->GetMotionMaster()->MovePoint(0, AddDestinyPoint); - //If spell is casted stops casting arcane field so no spell casting - //DoCast(me, SPELL_SUMMON_MINIONS); - uiTimer = 3*IN_MILLISECONDS; - } else uiTimer -= diff; - if (crystalHandlerAmount < 4) - { - if (uiCrystalHandlerTimer <= diff) - { - Talk(SAY_NECRO_ADD); - Creature* pCrystalHandler = me->SummonCreature(CREATURE_CRYSTAL_HANDLER, CrystalHandlerSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20*IN_MILLISECONDS); - pCrystalHandler->GetMotionMaster()->MovePoint(0, AddDestinyPoint); - uiCrystalHandlerTimer = urand(20*IN_MILLISECONDS, 30*IN_MILLISECONDS); - } else uiCrystalHandlerTimer -= diff; - } - break; - case PHASE_2: - if (uiTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, DUNGEON_MODE(RAND(SPELL_ARCANE_BLAST, SPELL_BLIZZARD, SPELL_FROSTBOLT, SPELL_WRATH_OF_MISERY), - RAND(H_SPELL_ARCANE_BLAST, H_SPELL_BLIZZARD, H_SPELL_FROSTBOLT, H_SPELL_WRATH_OF_MISERY))); - uiTimer = urand(1*IN_MILLISECONDS, 3*IN_MILLISECONDS); - } else uiTimer -= diff; - break; - default: - break; - } - } - void JustDied(Unit* /*killer*/) - { - Talk(SAY_DEATH); - if (instance) - instance->SetData(DATA_NOVOS_EVENT, DONE); - lSummons.DespawnAll(); - } - - void KilledUnit(Unit* victim) - { - if (victim == me) + if (!UpdateVictim() || _bubbled) return; - Talk(SAY_KILL); - } - void JustSummoned(Creature* summon) - { - if (summon->GetEntry() == CREATURE_CRYSTAL_HANDLER) - crystalHandlerAmount++; + events.Update(diff); - lSummons.Summon(summon); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + if (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SUMMON_MINIONS: + DoCast(SPELL_SUMMON_MINIONS); + events.ScheduleEvent(EVENT_SUMMON_MINIONS, 15000); + break; + case EVENT_ATTACK: + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(victim, RAND(SPELL_ARCANE_BLAST, SPELL_BLIZZARD, SPELL_FROSTBOLT, SPELL_WRATH_OF_MISERY)); + events.ScheduleEvent(EVENT_ATTACK, 3000); + break; + default: + break; + } + } } void DoAction(int32 const action) { - if (action == ACTION_MINION_REACHED) - ohNovos = false; + if (action == ACTION_CRYSTAL_HANDLER_DIED) + CrystalHandlerDied(); + } + + void MoveInLineOfSight(Unit* who) + { + BossAI::MoveInLineOfSight(who); + + if (!_ohNovos || !who || who->GetTypeId() != TYPEID_UNIT || who->GetPositionY() > MAX_Y_COORD_OH_NOVOS) + return; + + uint32 entry = who->GetEntry(); + if (entry == NPC_HULKING_CORPSE || entry == NPC_RISEN_SHADOWCASTER || entry == NPC_FETID_TROLL_CORPSE) + _ohNovos = false; } uint32 GetData(uint32 type) const { - if (type == DATA_OH_NOVOS) - return ohNovos ? 1 : 0; - - return 0; + return type == DATA_NOVOS_ACHIEV && _ohNovos ? 1 : 0; } - void RemoveCrystal() + void JustSummoned(Creature* summon) { - if (!luiCrystals.empty()) + summons.Summon(summon); + } + + private: + void SetBubbled(bool state) + { + _bubbled = state; + if (!state) { - if (instance) - if (GameObject* temp = instance->instance->GetGameObject(luiCrystals.back())) - temp->SetGoState(GO_STATE_READY); - luiCrystals.pop_back(); + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + if (me->HasUnitState(UNIT_STATE_CASTING)) + me->CastStop(); } - if (luiCrystals.empty()) + else { - me->CastStop(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Phase = PHASE_2; - uiTimer = 1*IN_MILLISECONDS; + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + DoCast(SPELL_ARCANE_FIELD); } } - Unit* GetRandomTarget() + void SetSummonerStatus(bool active) { - return SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + for (uint8 i = 0; i < 4; i++) + if (uint64 guid = instance->GetData64(summoners[i].data)) + if (Creature* crystalChannelTarget = instance->instance->GetCreature(guid)) + { + if (active) + crystalChannelTarget->AI()->SetData(summoners[i].spell, summoners[i].timer); + else + crystalChannelTarget->AI()->Reset(); + } } + + void SetCrystalsStatus(bool active) + { + for (uint8 i = 0; i < 4; i++) + if (uint64 guid = instance->GetData64(DATA_NOVOS_CRYSTAL_1 + i)) + if (GameObject* crystal = instance->instance->GetGameObject(guid)) + SetCrystalStatus(crystal, active); + } + + void SetCrystalStatus(GameObject* crystal, bool active) + { + if (!crystal) + return; + + crystal->SetGoState(active ? GO_STATE_ACTIVE : GO_STATE_READY); + if (Creature* crystalChannelTarget = crystal->FindNearestCreature(NPC_CRYSTAL_CHANNEL_TARGET, 5.0f)) + { + if (active) + crystalChannelTarget->AI()->DoCastAOE(SPELL_BEAM_CHANNEL); + else if (crystalChannelTarget->HasUnitState(UNIT_STATE_CASTING)) + crystalChannelTarget->CastStop(); + } + } + + void CrystalHandlerDied() + { + for (uint8 i = 0; i < 4; i++) + if (uint64 guid = instance->GetData64(DATA_NOVOS_CRYSTAL_1 + i)) + if (GameObject* crystal = instance->instance->GetGameObject(guid)) + if (crystal->GetGoState() == GO_STATE_ACTIVE) + { + SetCrystalStatus(crystal, false); + break; + } + + if (++_crystalHandlerCount >= 4) + { + SetSummonerStatus(false); + SetBubbled(false); + events.ScheduleEvent(EVENT_ATTACK, 3000); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_MINIONS, 15000); + } + else if (uint64 guid = instance->GetData64(DATA_NOVOS_SUMMONER_4)) + if (Creature* crystalChannelTarget = instance->instance->GetCreature(guid)) + crystalChannelTarget->AI()->SetData(SPELL_SUMMON_CRYSTAL_HANDLER, 15000); + } + + uint8 _crystalHandlerCount; + bool _ohNovos; + bool _bubbled; }; CreatureAI* GetAI(Creature* creature) const @@ -247,126 +261,116 @@ public: } }; -enum CrystalHandlerSpells -{ - SPELL_FLASH_OF_DARKNESS = 49668, - H_SPELL_FLASH_OF_DARKNESS = 59004 -}; - -class mob_crystal_handler : public CreatureScript +class npc_crystal_channel_target : public CreatureScript { public: - mob_crystal_handler() : CreatureScript("mob_crystal_handler") { } + npc_crystal_channel_target() : CreatureScript("npc_crystal_channel_target") {} - struct mob_crystal_handlerAI : public ScriptedAI + struct npc_crystal_channel_targetAI : public ScriptedAI { - mob_crystal_handlerAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - uint32 uiFlashOfDarknessTimer; - - InstanceScript* instance; + npc_crystal_channel_targetAI(Creature* creature) : ScriptedAI(creature) {} void Reset() { - uiFlashOfDarknessTimer = 5*IN_MILLISECONDS; - } - - void JustDied(Unit* /*killer*/) - { - if (Creature* pNovos = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_NOVOS) : 0)) - CAST_AI(boss_novos::boss_novosAI, pNovos->AI())->RemoveCrystal(); + _spell = 0; + _timer = 0; + _temp = 0; } void UpdateAI(const uint32 diff) { - if (!UpdateVictim()) - return; - - if (uiFlashOfDarknessTimer <= diff) + if (_spell) { - DoCast(me->getVictim(), DUNGEON_MODE(SPELL_FLASH_OF_DARKNESS, H_SPELL_FLASH_OF_DARKNESS)); - uiFlashOfDarknessTimer = 5*IN_MILLISECONDS; - } else uiFlashOfDarknessTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE || id != 0) - return; - if (Creature* pNovos = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_NOVOS) : 0)) - if (Unit* target = CAST_AI(boss_novos::boss_novosAI, pNovos->AI())->GetRandomTarget()) - AttackStart(target); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_crystal_handlerAI(creature); - } -}; - -class mob_novos_minion : public CreatureScript -{ -public: - mob_novos_minion() : CreatureScript("mob_novos_minion") { } - - struct mob_novos_minionAI : public ScriptedAI - { - mob_novos_minionAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE || id !=0) - return; - if (Creature* Novos = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_NOVOS) : 0)) - { - Novos->AI()->DoAction(ACTION_MINION_REACHED); - if (Unit* target = CAST_AI(boss_novos::boss_novosAI, Novos->AI())->GetRandomTarget()) - AttackStart(target); + if (_temp <= diff) + { + DoCast(_spell); + _temp = _timer; + } + else + _temp -= diff; } } + + void SetData(uint32 id, uint32 value) + { + _spell = id; + _timer = value; + _temp = value; + } + + void JustSummoned(Creature* summon) + { + if (InstanceScript* instance = me->GetInstanceScript()) + if (uint64 guid = instance->GetData64(DATA_NOVOS)) + if (Creature* novos = Creature::GetCreature(*me, guid)) + novos->AI()->JustSummoned(summon); + + if (summon) + summon->GetMotionMaster()->MovePath(summon->GetEntry() * 100, false); + + if (_spell == SPELL_SUMMON_CRYSTAL_HANDLER) + Reset(); + } + + private: + uint32 _spell; + uint32 _timer; + uint32 _temp; }; CreatureAI* GetAI(Creature* creature) const { - return new mob_novos_minionAI(creature); + return new npc_crystal_channel_targetAI(creature); } }; class achievement_oh_novos : public AchievementCriteriaScript { - public: - achievement_oh_novos() : AchievementCriteriaScript("achievement_oh_novos") +public: + achievement_oh_novos() : AchievementCriteriaScript("achievement_oh_novos") {} + + bool OnCheck(Player* /*player*/, Unit* target) + { + return target && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(DATA_NOVOS_ACHIEV); + } +}; + +enum SummonMinions +{ + SPELL_COPY_OF_SUMMON_MINIONS = 59933 +}; + +class spell_summon_minions : public SpellScriptLoader +{ +public: + spell_summon_minions() : SpellScriptLoader("spell_summon_minions") { } + + class spell_summon_minions_SpellScript : public SpellScript + { + PrepareSpellScript(spell_summon_minions_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) { + GetCaster()->CastSpell((Unit*)NULL, SPELL_COPY_OF_SUMMON_MINIONS, true); + GetCaster()->CastSpell((Unit*)NULL, SPELL_COPY_OF_SUMMON_MINIONS, true); } - bool OnCheck(Player* /*player*/, Unit* target) + void Register() { - if (!target) - return false; - - if (Creature* Novos = target->ToCreature()) - if (Novos->AI()->GetData(DATA_OH_NOVOS)) - return true; - - return false; + OnEffectHitTarget += SpellEffectFn(spell_summon_minions_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } + }; + + SpellScript* GetSpellScript() const + { + return new spell_summon_minions_SpellScript(); + } }; void AddSC_boss_novos() { new boss_novos(); - new mob_crystal_handler(); - new mob_novos_minion(); + new npc_crystal_channel_target(); + new spell_summon_minions(); new achievement_oh_novos(); } diff --git a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h index dc8428f9104..e17cba4bccd 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h +++ b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h @@ -31,9 +31,16 @@ enum Data64 DATA_NOVOS, DATA_DRED, DATA_THARON_JA, + DATA_NOVOS_CRYSTAL_1, DATA_NOVOS_CRYSTAL_2, DATA_NOVOS_CRYSTAL_3, - DATA_NOVOS_CRYSTAL_4 + DATA_NOVOS_CRYSTAL_4, + DATA_NOVOS_SUMMONER_1, + DATA_NOVOS_SUMMONER_2, + DATA_NOVOS_SUMMONER_3, + DATA_NOVOS_SUMMONER_4, + + ACTION_CRYSTAL_HANDLER_DIED }; #endif diff --git a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp index 52c5c9eab8e..1d7c537d97a 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp @@ -30,17 +30,23 @@ enum Creatures { - NPC_TROLLGORE = 26630, - NPC_NOVOS = 26631, - NPC_KING_DRED = 27483, - NPC_THARON_JA = 26632 + NPC_TROLLGORE = 26630, + NPC_NOVOS = 26631, + NPC_KING_DRED = 27483, + NPC_THARON_JA = 26632, + NPC_CRYSTAL_CHANNEL_TARGET = 26712, + NPC_CRYSTAL_HANDLER = 26627 }; enum GameObjects { - GO_NOVOS_CRYSTAL_1 = 189299, - GO_NOVOS_CRYSTAL_2 = 189300, - GO_NOVOS_CRYSTAL_3 = 189301, - GO_NOVOS_CRYSTAL_4 = 189302 + GO_NOVOS_CRYSTAL_1 = 189299, + GO_NOVOS_CRYSTAL_2 = 189300, + GO_NOVOS_CRYSTAL_3 = 189301, + GO_NOVOS_CRYSTAL_4 = 189302 +}; +enum Achievements +{ + ACM_CRITERIA_OH_NOVOS = 7361 }; class instance_drak_tharon : public InstanceMapScript @@ -52,17 +58,22 @@ public: { instance_drak_tharon_InstanceScript(Map* map) : InstanceScript(map) {} - uint8 uiDredAchievCounter; + uint8 dredAchievCounter; - uint64 uiTrollgore; - uint64 uiNovos; - uint64 uiDred; - uint64 uiTharonJa; + uint64 trollgoreGUID; + uint64 novosGUID; + uint64 dredGUID; + uint64 tharonJaGUID; - uint64 uiNovosCrystal1; - uint64 uiNovosCrystal2; - uint64 uiNovosCrystal3; - uint64 uiNovosCrystal4; + uint64 novosCrystalGUID1; + uint64 novosCrystalGUID2; + uint64 novosCrystalGUID3; + uint64 novosCrystalGUID4; + + uint64 novosSummonerGUID1; + uint64 novosSummonerGUID2; + uint64 novosSummonerGUID3; + uint64 novosSummonerGUID4; uint16 m_auiEncounter[MAX_ENCOUNTER]; @@ -71,15 +82,23 @@ public: void Initialize() { memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - uiTrollgore = 0; - uiNovos = 0; - uiDred = 0; - uiTharonJa = 0; - uiNovosCrystal1 = 0; - uiNovosCrystal2 = 0; - uiNovosCrystal3 = 0; - uiNovosCrystal4 = 0; - uiDredAchievCounter = 0; + + dredAchievCounter = 0; + + trollgoreGUID = 0; + novosGUID = 0; + dredGUID = 0; + tharonJaGUID = 0; + + novosCrystalGUID1 = 0; + novosCrystalGUID2 = 0; + novosCrystalGUID3 = 0; + novosCrystalGUID4 = 0; + + novosSummonerGUID1 = 0; + novosSummonerGUID2 = 0; + novosSummonerGUID3 = 0; + novosSummonerGUID4 = 0; } bool IsEncounterInProgress() const @@ -96,16 +115,20 @@ public: switch (go->GetEntry()) { case GO_NOVOS_CRYSTAL_1: - uiNovosCrystal1 = go->GetGUID(); + novosCrystalGUID1 = go->GetGUID(); + go->SetGoState(GO_STATE_READY); break; case GO_NOVOS_CRYSTAL_2: - uiNovosCrystal2 = go->GetGUID(); + novosCrystalGUID2 = go->GetGUID(); + go->SetGoState(GO_STATE_READY); break; case GO_NOVOS_CRYSTAL_3: - uiNovosCrystal3 = go->GetGUID(); + novosCrystalGUID3 = go->GetGUID(); + go->SetGoState(GO_STATE_READY); break; case GO_NOVOS_CRYSTAL_4: - uiNovosCrystal4 = go->GetGUID(); + novosCrystalGUID4 = go->GetGUID(); + go->SetGoState(GO_STATE_READY); break; } } @@ -115,32 +138,55 @@ public: switch (creature->GetEntry()) { case NPC_TROLLGORE: - uiTrollgore = creature->GetGUID(); + trollgoreGUID = creature->GetGUID(); break; case NPC_NOVOS: - uiNovos = creature->GetGUID(); + novosGUID = creature->GetGUID(); break; case NPC_KING_DRED: - uiDred = creature->GetGUID(); + dredGUID = creature->GetGUID(); break; case NPC_THARON_JA: - uiTharonJa = creature->GetGUID(); + tharonJaGUID = creature->GetGUID(); + break; + case NPC_CRYSTAL_CHANNEL_TARGET: + InitializeNovosSummoner(creature); break; } } + void InitializeNovosSummoner(Creature* creature) + { + float x = creature->GetPositionX(); + float y = creature->GetPositionY(); + float z = creature->GetPositionZ(); + + if (x < -374.0f && x > -379.0f && y > -820.0f && y < -815.0f && z < 60.0f && z > 58.0f) + novosSummonerGUID1 = creature->GetGUID(); + else if (x < -379.0f && x > -385.0f && y > -820.0f && y < -815.0f && z < 60.0f && z > 58.0f) + novosSummonerGUID2 = creature->GetGUID(); + else if (x < -374.0f && x > -385.0f && y > -827.0f && y < -820.0f && z < 60.0f && z > 58.0f) + novosSummonerGUID3 = creature->GetGUID(); + else if (x < -338.0f && x > -344.0f && y > -727.0f && y < 721.0f && z < 30.0f && z > 26.0f) + novosSummonerGUID4 = creature->GetGUID(); + } + uint64 GetData64(uint32 identifier) const { switch (identifier) { - case DATA_TROLLGORE: return uiTrollgore; - case DATA_NOVOS: return uiNovos; - case DATA_DRED: return uiDred; - case DATA_THARON_JA: return uiTharonJa; - case DATA_NOVOS_CRYSTAL_1: return uiNovosCrystal1; - case DATA_NOVOS_CRYSTAL_2: return uiNovosCrystal2; - case DATA_NOVOS_CRYSTAL_3: return uiNovosCrystal3; - case DATA_NOVOS_CRYSTAL_4: return uiNovosCrystal4; + case DATA_TROLLGORE: return trollgoreGUID; + case DATA_NOVOS: return novosGUID; + case DATA_DRED: return dredGUID; + case DATA_THARON_JA: return tharonJaGUID; + case DATA_NOVOS_CRYSTAL_1: return novosCrystalGUID1; + case DATA_NOVOS_CRYSTAL_2: return novosCrystalGUID2; + case DATA_NOVOS_CRYSTAL_3: return novosCrystalGUID3; + case DATA_NOVOS_CRYSTAL_4: return novosCrystalGUID4; + case DATA_NOVOS_SUMMONER_1: return novosSummonerGUID1; + case DATA_NOVOS_SUMMONER_2: return novosSummonerGUID2; + case DATA_NOVOS_SUMMONER_3: return novosSummonerGUID3; + case DATA_NOVOS_SUMMONER_4: return novosSummonerGUID4; } return 0; @@ -164,7 +210,7 @@ public: break; case DATA_KING_DRED_ACHIEV: - uiDredAchievCounter = data; + dredAchievCounter = data; break; } @@ -182,7 +228,7 @@ public: case DATA_NOVOS_EVENT: return m_auiEncounter[1]; case DATA_DRED_EVENT: return m_auiEncounter[2]; case DATA_THARON_JA_EVENT: return m_auiEncounter[3]; - case DATA_KING_DRED_ACHIEV: return uiDredAchievCounter; + case DATA_KING_DRED_ACHIEV: return dredAchievCounter; } return 0; } @@ -199,6 +245,14 @@ public: return saveStream.str(); } + void OnUnitDeath(Unit* unit) + { + if (unit->GetEntry() == NPC_CRYSTAL_HANDLER) + if (novosGUID) + if (Creature* novos = instance->GetCreature(novosGUID)) + novos->AI()->DoAction(ACTION_CRYSTAL_HANDLER_DIED); + } + void Load(const char* in) { if (!in)