diff options
author | Gacko <gacko28@gmx.de> | 2013-01-05 18:03:11 +0100 |
---|---|---|
committer | Gacko <gacko28@gmx.de> | 2013-01-05 18:03:11 +0100 |
commit | c86230208f1ca797cc2f350fbc5f8e090816fa95 (patch) | |
tree | d38e2c832f1c31315c54c5ed79a3b9db7e226e97 | |
parent | 7dd0cd4403d7f28343a751e7b85aeb30d3968ff5 (diff) |
Script: Novos rewrite
4 files changed, 408 insertions, 280 deletions
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. + ACTION_RESET_CRYSTALS, + ACTION_ACTIVATE_CRYSTAL, + ACTION_DEACTIVATE, + EVENT_ATTACK, + EVENT_SUMMON_MINIONS, + DATA_NOVOS_ACHIEV }; -//not in db -enum Yells +enum Creatures { - SAY_AGGRO = 0, - SAY_KILL = 1, - SAY_DEATH = 2, - SAY_NECRO_ADD = 3, - SAY_REUBBLE = 4 + NPC_CRYSTAL_CHANNEL_TARGET = 26712, + NPC_FETID_TROLL_CORPSE = 27597, + NPC_RISEN_SHADOWCASTER = 27600, + NPC_HULKING_CORPSE = 27597 }; -enum Creatures +enum Spells { - CREATURE_RISEN_SHADOWCASTER = 27600, - CREATURE_FETID_TROLL_CORPSE = 27598, - CREATURE_HULKING_CORPSE = 27597, - CREATURE_CRYSTAL_HANDLER = 26627 + 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 }; -enum CombatPhase +struct SummonerInfo { - IDLE, - PHASE_1, - PHASE_2 + uint32 data, spell, timer; }; -#define ACTION_MINION_REACHED 1 -#define DATA_OH_NOVOS 2 +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 } +}; -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 }; +#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) + boss_novosAI(Creature* creature) : BossAI(creature, DATA_NOVOS_EVENT) {} + + void Reset() { - instance = creature->GetInstanceScript(); + events.Reset(); + summons.DespawnAll(); + instance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); + + _ohNovos = true; + _crystalHandlerCount = 0; + SetCrystalsStatus(false); + SetSummonerStatus(false); + SetBubbled(false); } - uint32 uiTimer; - uint32 uiCrystalHandlerTimer; - uint8 crystalHandlerAmount; + void EnterCombat(Unit* /* victim */) + { + me->setActive(true); + DoZoneInCombat(); + instance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); - bool ohNovos; + SetCrystalsStatus(true); + SetSummonerStatus(true); + SetBubbled(true); + } - SummonList lSummons; + void AttackStart(Unit* target) + { + if (!target) + return; - std::list<uint64> luiCrystals; + if (me->Attack(target, true)) + DoStartNoMovement(target); + } - CombatPhase Phase; + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || _bubbled) + return; - InstanceScript* instance; + events.Update(diff); - void Reset() - { - Phase = IDLE; - luiCrystals.clear(); - ohNovos = true; - me->CastStop(); - lSummons.DespawnAll(); - crystalHandlerAmount = 0; - - 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<uint64>::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject* temp = instance->instance->GetGameObject(*itr)) - temp->SetGoState(GO_STATE_READY); - } - } - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void EnterCombat(Unit* /*who*/) - { - Talk(SAY_AGGRO); - Phase = PHASE_1; - uiCrystalHandlerTimer = 30*IN_MILLISECONDS; - uiTimer = 1*IN_MILLISECONDS; - DoCast(SPELL_ARCANE_FIELD); - if (instance) + if (uint32 eventId = events.ExecuteEvent()) { - for (std::list<uint64>::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) + switch (eventId) { - if (GameObject* temp = instance->instance->GetGameObject(*itr)) - temp->SetGoState(GO_STATE_ACTIVE); + 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; } - 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); } - void UpdateAI(const uint32 diff) + void DoAction(int32 const action) { - 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; - } + if (action == ACTION_CRYSTAL_HANDLER_DIED) + CrystalHandlerDied(); } - void JustDied(Unit* /*killer*/) + + void MoveInLineOfSight(Unit* who) { - Talk(SAY_DEATH); - if (instance) - instance->SetData(DATA_NOVOS_EVENT, DONE); - lSummons.DespawnAll(); + 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; } - void KilledUnit(Unit* victim) + uint32 GetData(uint32 type) const { - if (victim == me) - return; - Talk(SAY_KILL); + return type == DATA_NOVOS_ACHIEV && _ohNovos ? 1 : 0; } void JustSummoned(Creature* summon) { - if (summon->GetEntry() == CREATURE_CRYSTAL_HANDLER) - crystalHandlerAmount++; - - lSummons.Summon(summon); + summons.Summon(summon); } - void DoAction(int32 const action) + private: + void SetBubbled(bool state) { - if (action == ACTION_MINION_REACHED) - ohNovos = false; + _bubbled = state; + if (!state) + { + 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(); + } + else + { + 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); + } } - uint32 GetData(uint32 type) const + void SetSummonerStatus(bool active) { - if (type == DATA_OH_NOVOS) - return ohNovos ? 1 : 0; + 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(); + } + } - return 0; + 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 RemoveCrystal() + void SetCrystalStatus(GameObject* crystal, bool active) { - if (!luiCrystals.empty()) - { - if (instance) - if (GameObject* temp = instance->instance->GetGameObject(luiCrystals.back())) - temp->SetGoState(GO_STATE_READY); - luiCrystals.pop_back(); - } - if (luiCrystals.empty()) + if (!crystal) + return; + + crystal->SetGoState(active ? GO_STATE_ACTIVE : GO_STATE_READY); + if (Creature* crystalChannelTarget = crystal->FindNearestCreature(NPC_CRYSTAL_CHANNEL_TARGET, 5.0f)) { - 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 (active) + crystalChannelTarget->AI()->DoCastAOE(SPELL_BEAM_CHANNEL); + else if (crystalChannelTarget->HasUnitState(UNIT_STATE_CASTING)) + crystalChannelTarget->CastStop(); } } - Unit* GetRandomTarget() + void CrystalHandlerDied() { - return SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + 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) + npc_crystal_channel_targetAI(Creature* creature) : ScriptedAI(creature) {} + + void Reset() { - instance = creature->GetInstanceScript(); + _spell = 0; + _timer = 0; + _temp = 0; } - uint32 uiFlashOfDarknessTimer; - - InstanceScript* instance; - - void Reset() + void UpdateAI(const uint32 diff) { - uiFlashOfDarknessTimer = 5*IN_MILLISECONDS; + if (_spell) + { + if (_temp <= diff) + { + DoCast(_spell); + _temp = _timer; + } + else + _temp -= diff; + } } - void JustDied(Unit* /*killer*/) + void SetData(uint32 id, uint32 value) { - if (Creature* pNovos = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_NOVOS) : 0)) - CAST_AI(boss_novos::boss_novosAI, pNovos->AI())->RemoveCrystal(); + _spell = id; + _timer = value; + _temp = value; } - void UpdateAI(const uint32 diff) + void JustSummoned(Creature* summon) { - if (!UpdateVictim()) - return; + if (InstanceScript* instance = me->GetInstanceScript()) + if (uint64 guid = instance->GetData64(DATA_NOVOS)) + if (Creature* novos = Creature::GetCreature(*me, guid)) + novos->AI()->JustSummoned(summon); - if (uiFlashOfDarknessTimer <= diff) - { - DoCast(me->getVictim(), DUNGEON_MODE(SPELL_FLASH_OF_DARKNESS, H_SPELL_FLASH_OF_DARKNESS)); - uiFlashOfDarknessTimer = 5*IN_MILLISECONDS; - } else uiFlashOfDarknessTimer -= diff; + if (summon) + summon->GetMotionMaster()->MovePath(summon->GetEntry() * 100, false); - DoMeleeAttackIfReady(); + if (_spell == SPELL_SUMMON_CRYSTAL_HANDLER) + Reset(); } - 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); - } + private: + uint32 _spell; + uint32 _timer; + uint32 _temp; }; CreatureAI* GetAI(Creature* creature) const { - return new mob_crystal_handlerAI(creature); + return new npc_crystal_channel_targetAI(creature); } }; -class mob_novos_minion : public CreatureScript +class achievement_oh_novos : public AchievementCriteriaScript { public: - mob_novos_minion() : CreatureScript("mob_novos_minion") { } + achievement_oh_novos() : AchievementCriteriaScript("achievement_oh_novos") {} - struct mob_novos_minionAI : public ScriptedAI + bool OnCheck(Player* /*player*/, Unit* target) { - mob_novos_minionAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } + return target && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(DATA_NOVOS_ACHIEV); + } +}; - InstanceScript* instance; +enum SummonMinions +{ + SPELL_COPY_OF_SUMMON_MINIONS = 59933 +}; - 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); - } - } - }; +class spell_summon_minions : public SpellScriptLoader +{ +public: + spell_summon_minions() : SpellScriptLoader("spell_summon_minions") { } - CreatureAI* GetAI(Creature* creature) const + class spell_summon_minions_SpellScript : public SpellScript { - return new mob_novos_minionAI(creature); - } -}; + PrepareSpellScript(spell_summon_minions_SpellScript); -class achievement_oh_novos : public AchievementCriteriaScript -{ - public: - achievement_oh_novos() : AchievementCriteriaScript("achievement_oh_novos") + 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) |