diff --git a/sql/updates/world/4.3.4/2020_07_15_00_world.sql b/sql/updates/world/4.3.4/2020_07_15_00_world.sql new file mode 100644 index 00000000000..e760fefbeba --- /dev/null +++ b/sql/updates/world/4.3.4/2020_07_15_00_world.sql @@ -0,0 +1,124 @@ +-- Spirit of Angerforge +UPDATE `creature_template` SET `difficulty_entry_1`= 49504 WHERE `entry`= 43119; +-- Spirit of Ironstar +UPDATE `creature_template` SET `difficulty_entry_1`= 49509 WHERE `entry`= 43127; +-- Spirit of Thaurissan +UPDATE `creature_template` SET `difficulty_entry_1`= 49508 WHERE `entry`= 43126; +-- Spirit of Burningeye +UPDATE `creature_template` SET `difficulty_entry_1`= 49512 WHERE `entry`= 43130; +-- Spirit of Moltenfist +UPDATE `creature_template` SET `difficulty_entry_1`= 49507 WHERE `entry`= 43125; +-- Spirit of Anvilrage +UPDATE `creature_template` SET `difficulty_entry_1`= 49510 WHERE `entry`= 43128; +-- Spirit of Shadowforge +UPDATE `creature_template` SET `difficulty_entry_1`= 49511 WHERE `entry`= 43129; +-- Spirit of Corehammer +UPDATE `creature_template` SET `difficulty_entry_1`= 49505 WHERE `entry`= 43122; + +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `exp`= 3, `speed_walk`= 1.2, `speed_run`= 1, `faction`= 16, `unit_class`= 2, `unit_flags`= 32832, `BaseVariance`= 0.75, `DamageModifier`= 130 WHERE `entry` IN (49504, 49509, 49508, 49512, 49507, 49510, 49511, 49505); +UPDATE `creature_template` SET `ScriptName`= 'npc_bwd_dwarven_spirit' WHERE `entry` IN (43119, 43127, 43126, 43130, 43125, 43128, 43129, 43122); + +-- Execution Sentence +UPDATE `creature_template` SET `unit_flags`=33587264, `flags_extra`= 128, `AIName`= 'NullCreatureAI' WHERE `entry`= 43210; +-- Execution Sentence Visual +UPDATE `creature_template` SET `unit_flags`=33587264, `flags_extra`= 128, `AIName`= 'NullCreatureAI' WHERE `entry`= 43206; + +DELETE FROM `creature_template_addon` WHERE `entry`= 43206; +INSERT INTO `creature_template_addon` (`entry`, `bytes1`, `bytes2`, `auras`) VALUES +(43206, 50331648, 1, '80736'); + +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (43210, 43206); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Flight`, `Rooted`) VALUES +(43210, 0, 1, 1), +(43206, 0, 1, 0); + +UPDATE `creature_template` SET `mechanic_immune_mask`= 1 | 2 | 8 | 16 | 32 | 64 | 256 | 512 | 2048 | 4096 | 8192 | 65536 | 131072 | 4194304 | 8388608 WHERE `entry` IN (49504, 43119, 49509, 43127, 49508, 43126, 49512, 43130, 49507, 43125, 49510, 43128, 49511, 43129, 49505, 43122); + +DELETE FROM `creature_template_addon` WHERE `entry` IN (49504, 43119, 49509, 43127, 49508, 43126, 49512, 43130, 49507, 43125, 49510, 43128, 49511, 43129, 49505, 43122); +INSERT INTO `creature_template_addon` (`entry`, `bytes2`, `auras`) VALUES +-- Spirit of Angerforge +(49504, 1, '80611 80762'), +(43119, 1, '80611 80762'), +-- Spirit of Ironstar +(49509, 1, '80611 80767'), +(43127, 1, '80611 80767'), +-- Spirit of Thaurissan +(49508, 1, '80611 80766'), +(43126, 1, '80611 80766'), +-- Spirit of Burningeye +(49512, 1, '80611 80770'), +(43130, 1, '80611 80770'), +-- Spirit of Moltenfist +(49507, 1, '80611 80764'), +(43125, 1, '80611 80764'), +-- Spirit of Anvilrage +(49510, 1, '80611 80768'), +(43128, 1, '80611 80768'), +-- Spirit of Shadowforge +(49511, 1, '80611 80769'), +(43129, 1, '80611 80769'), +-- Spirit of Corehammer +(49505, 1, '80611 80763'), +(43122, 1, '80611 80763'); + +DELETE FROM `spell_proc` WHERE `SpellId`= 80718; +INSERT INTO `spell_proc` (`SpellId`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`) VALUES +(80718, 3, 2, 0); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_bwd_execution_sentence_visual', +'spell_bwd_execution_sentence', +'spell_bwd_execution_sentence_dummy', +'spell_bwd_stoneblood'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(80729, 'spell_bwd_execution_sentence_visual'), +(80727, 'spell_bwd_execution_sentence'), +(85176, 'spell_bwd_execution_sentence_dummy'), +(80655, 'spell_bwd_stoneblood'); + +DELETE FROM `conditions` WHERE `SourceEntry` IN (85176, 80876, 80874, 80873, 80877, 80878, 80875, 80871, 80872) AND `SourceTypeOrReferenceId`= 13; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES +(13, 1, 85176, 0, 0, 31, 0, 3, 43210, 0, 0, 0, '', 'Execution Sentence - Target Execution Sentence'), +(13, 1, 85176, 0, 1, 31, 0, 3, 43206, 0, 0, 0, '', 'Execution Sentence - Target Execution Sentence Visual'), +(13, 1, 80876, 0, 0, 31, 0, 3, 43128, 0, 0, 0, '', 'Bestowal of Moltenfist'), +(13, 1, 80876, 0, 1, 31, 0, 3, 43129, 0, 0, 0, '', 'Bestowal of Moltenfist'), +(13, 1, 80876, 0, 2, 31, 0, 3, 43122, 0, 0, 0, '', 'Bestowal of Moltenfist'), +(13, 1, 80874, 0, 0, 31, 0, 3, 43125, 0, 0, 0, '', 'Bestowal of Anvilrage'), +(13, 1, 80874, 0, 1, 31, 0, 3, 43129, 0, 0, 0, '', 'Bestowal of Anvilrage'), +(13, 1, 80874, 0, 2, 31, 0, 3, 43122, 0, 0, 0, '', 'Bestowal of Anvilrage'), +(13, 1, 80873, 0, 0, 31, 0, 3, 43125, 0, 0, 0, '', 'Bestowal of Shadowforge'), +(13, 1, 80873, 0, 1, 31, 0, 3, 43128, 0, 0, 0, '', 'Bestowal of Shadowforge'), +(13, 1, 80873, 0, 2, 31, 0, 3, 43122, 0, 0, 0, '', 'Bestowal of Shadowforge'), +(13, 1, 80877, 0, 0, 31, 0, 3, 43125, 0, 0, 0, '', 'Bestowal of Corehammer'), +(13, 1, 80877, 0, 1, 31, 0, 3, 43128, 0, 0, 0, '', 'Bestowal of Corehammer'), +(13, 1, 80877, 0, 2, 31, 0, 3, 43129, 0, 0, 0, '', 'Bestowal of Corehammer'), +(13, 1, 80878, 0, 0, 31, 0, 3, 43127, 0, 0, 0, '', 'Bestowal of Angerforge'), +(13, 1, 80878, 0, 1, 31, 0, 3, 43126, 0, 0, 0, '', 'Bestowal of Angerforge'), +(13, 1, 80878, 0, 2, 31, 0, 3, 43130, 0, 0, 0, '', 'Bestowal of Angerforge'), +(13, 1, 80875, 0, 0, 31, 0, 3, 43119, 0, 0, 0, '', 'Bestowal of Ironstar'), +(13, 1, 80875, 0, 1, 31, 0, 3, 43126, 0, 0, 0, '', 'Bestowal of Ironstar'), +(13, 1, 80875, 0, 2, 31, 0, 3, 43130, 0, 0, 0, '', 'Bestowal of Ironstar'), +(13, 1, 80871, 0, 0, 31, 0, 3, 43119, 0, 0, 0, '', 'Bestowal of Thaurissan'), +(13, 1, 80871, 0, 1, 31, 0, 3, 43127, 0, 0, 0, '', 'Bestowal of Thaurissan'), +(13, 1, 80871, 0, 2, 31, 0, 3, 43130, 0, 0, 0, '', 'Bestowal of Thaurissan'), +(13, 1, 80872, 0, 0, 31, 0, 3, 43119, 0, 0, 0, '', 'Bestowal of Burningeye'), +(13, 1, 80872, 0, 1, 31, 0, 3, 43127, 0, 0, 0, '', 'Bestowal of Burningeye'), +(13, 1, 80872, 0, 2, 31, 0, 3, 43126, 0, 0, 0, '', 'Bestowal of Burningeye'); + +-- Spawn Groups +DELETE FROM `spawn_group_template` WHERE `groupId` IN (435, 436); +INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES +(435, 'Blackwing Descent - Dwarven Spirits Left', 4), +(436, 'Blackwing Descent - Dwarven Spirits Left', 4); + +DELETE FROM `spawn_group` WHERE `groupId` IN (435, 436); +INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES +(435, 0, 250134), +(435, 0, 250137), +(435, 0, 250138), +(435, 0, 250133), +(436, 0, 250132), +(436, 0, 250136), +(436, 0, 250135), +(436, 0, 250139); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.cpp index fe17bf88c4a..47770e413e7 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.cpp @@ -23,7 +23,9 @@ #include "Spell.h" #include "SpellScript.h" #include "SpellAuraEffects.h" +#include "TemporarySummon.h" #include "Map.h" +#include "MoveSplineInit.h" #include "PassiveAI.h" #include "Player.h" #include "InstanceScript.h" @@ -191,7 +193,7 @@ enum DrakonidChainWielder SPELL_OVERHEAD_SMASH_SUMMON = 79578, // Serverside spell SPELL_OVERHEAD_SMASH = 79580, SPELL_GRIEVOUS_WOUND = 80051, - SPELL_CONSTRICTING_CHAINS = 79589, + SPELL_CONSTRICTING_CHAINS = 79589 }; struct npc_bwd_drakonid_chainwielder : public ScriptedAI @@ -265,15 +267,261 @@ private: EventMap _events; }; +enum DwarvenSpirits +{ + // Spells + SPELL_SPIRIT_OF_ANGERFORGE = 80762, + SPELL_SPIRIT_OF_IRONSTAR = 80767, + SPELL_SPIRIT_OF_THAURISSAN = 80766, + SPELL_SPIRIT_OF_BURNINGEYE = 80770, + SPELL_SPIRIT_OF_MOLTENFIST = 80764, + SPELL_SPIRIT_OF_ANVILRAGE = 80768, + SPELL_SPIRIT_OF_SHADOWFORGE = 80769, + SPELL_SPIRIT_OF_COREHAMMER = 80763, + + SPELL_BESTOWAL_OF_THAURISSAN = 80871, + SPELL_BESTOWAL_OF_BURNINGEYE = 80872, + SPELL_BESTOWAL_OF_SHADOWFORGE = 80873, + SPELL_BESTOWAL_OF_ANVILRAGE = 80874, + SPELL_BESTOWAL_OF_IRONSTAR = 80875, + SPELL_BESTOWAL_OF_MOLTENFIST = 80876, + SPELL_BESTOWAL_OF_COREHAMMER = 80877, + SPELL_BESTOWAL_OF_ANGERFORGE = 80878, + + SPELL_BURDEN_OF_THE_CROWN = 80718, + SPELL_CHAIN_LIGHTNING = 80646, + SPELL_STORMBOLT = 80648, + SPELL_THUNDERCLAP = 80649, + SPELL_WHIRLWIND = 80652, + SPELL_AVATAR = 80645, + SPELL_STONEBLOOD = 80655, + SPELL_EXECUTION_SENTENCE_SUMMON_1 = 80738, + SPELL_EXECUTION_SENTENCE_SUMMON_2 = 80729, + SPELL_EXECUTION_SENTENCE_DUMMY = 85176, + SPELL_EXECUTION_SENTENCE = 80727, + + // Events + EVENT_BURDEN_OF_THE_CROWN = 1, + EVENT_CHAIN_LIGHTNING, + EVENT_STORMBOLT, + EVENT_THUNDERCLAP, + EVENT_WHIRLWIND, + EVENT_AVATAR, + EVENT_STONEBLOOD, + EVENT_SHIELD_OF_LIGHT, + EVENT_EXECUTION_SENTENCE +}; + +#define SPELL_SHIELD_OF_LIGHT RAID_MODE(80747, 95537) + +struct npc_bwd_dwarven_spirit : public ScriptedAI +{ + npc_bwd_dwarven_spirit(Creature* creature) : ScriptedAI(creature) { } + + void JustEngagedWith(Unit* /*who*/) override + { + uint32 initialEventId = 0; + switch (me->GetEntry()) + { + case NPC_SPIRIT_OF_COREHAMMER: initialEventId = EVENT_BURDEN_OF_THE_CROWN; break; + case NPC_SPIRIT_OF_SHADOWFORGE: initialEventId = EVENT_CHAIN_LIGHTNING; break; + case NPC_SPIRIT_OF_ANVILRAGE: initialEventId = EVENT_STORMBOLT; break; + case NPC_SPIRIT_OF_MOLTENFIST: initialEventId = EVENT_THUNDERCLAP; break; + case NPC_SPIRIT_OF_BURNINGEYE: initialEventId = EVENT_WHIRLWIND; break; + case NPC_SPIRIT_OF_THAURISSAN: initialEventId = EVENT_AVATAR; break; + case NPC_SPIRIT_OF_ANGERFORGE: initialEventId = EVENT_STONEBLOOD; break; + case NPC_SPIRIT_OF_IRONSTAR: initialEventId = EVENT_SHIELD_OF_LIGHT; break; + default: + break; + } + + if (initialEventId) + _events.ScheduleEvent(initialEventId, 11s, 18s); + } + + void EnterEvadeMode(EvadeReason why) override + { + ScriptedAI::EnterEvadeMode(why); + _events.Reset(); + + if (InstanceScript* instance = me->GetInstanceScript()) + { + switch (me->GetEntry()) + { + case NPC_SPIRIT_OF_MOLTENFIST: + case NPC_SPIRIT_OF_ANVILRAGE: + case NPC_SPIRIT_OF_SHADOWFORGE: + case NPC_SPIRIT_OF_COREHAMMER: + instance->SetData(DATA_RESET_DWARVEN_SPIRIT_GROUP, DWARVEN_SPIRIT_GROUP_LEFT); + break; + default: + instance->SetData(DATA_RESET_DWARVEN_SPIRIT_GROUP, DWARVEN_SPIRIT_GROUP_RIGHT); + break; + } + } + } + + void JustDied(Unit* /*killer*/) override + { + _events.Reset(); + uint32 bestowalSpellId = 0; + switch (me->GetEntry()) + { + case NPC_SPIRIT_OF_ANGERFORGE: bestowalSpellId = SPELL_BESTOWAL_OF_ANGERFORGE; break; + case NPC_SPIRIT_OF_ANVILRAGE: bestowalSpellId = SPELL_BESTOWAL_OF_ANVILRAGE; break; + case NPC_SPIRIT_OF_BURNINGEYE: bestowalSpellId = SPELL_BESTOWAL_OF_BURNINGEYE; break; + case NPC_SPIRIT_OF_COREHAMMER: bestowalSpellId = SPELL_BESTOWAL_OF_COREHAMMER; break; + case NPC_SPIRIT_OF_IRONSTAR: bestowalSpellId = SPELL_BESTOWAL_OF_IRONSTAR; break; + case NPC_SPIRIT_OF_MOLTENFIST: bestowalSpellId = SPELL_BESTOWAL_OF_MOLTENFIST; break; + case NPC_SPIRIT_OF_SHADOWFORGE: bestowalSpellId = SPELL_BESTOWAL_OF_SHADOWFORGE; break; + case NPC_SPIRIT_OF_THAURISSAN: bestowalSpellId = SPELL_BESTOWAL_OF_THAURISSAN; break; + default: + break; + } + + if (bestowalSpellId) + DoCastAOE(bestowalSpellId); + + if (InstanceScript* instance = me->GetInstanceScript()) + { + switch (me->GetEntry()) + { + case NPC_SPIRIT_OF_MOLTENFIST: + case NPC_SPIRIT_OF_ANVILRAGE: + case NPC_SPIRIT_OF_SHADOWFORGE: + case NPC_SPIRIT_OF_COREHAMMER: + instance->SetData(DATA_DWARVEN_SPIRIT_DIED, DWARVEN_SPIRIT_GROUP_LEFT); + break; + default: + instance->SetData(DATA_DWARVEN_SPIRIT_DIED, DWARVEN_SPIRIT_GROUP_RIGHT); + break; + } + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + uint32 triggeredEventId = 0; + switch (spell->Id) + { + case SPELL_BESTOWAL_OF_COREHAMMER: triggeredEventId = EVENT_BURDEN_OF_THE_CROWN; break; + case SPELL_BESTOWAL_OF_SHADOWFORGE: triggeredEventId = EVENT_CHAIN_LIGHTNING; break; + case SPELL_BESTOWAL_OF_ANVILRAGE: triggeredEventId = EVENT_STORMBOLT; break; + case SPELL_BESTOWAL_OF_MOLTENFIST: triggeredEventId = EVENT_THUNDERCLAP; break; + case SPELL_BESTOWAL_OF_BURNINGEYE: triggeredEventId = EVENT_WHIRLWIND; break; + case SPELL_BESTOWAL_OF_THAURISSAN: triggeredEventId = EVENT_AVATAR; break; + case SPELL_BESTOWAL_OF_ANGERFORGE: triggeredEventId = EVENT_AVATAR; break; + case SPELL_BESTOWAL_OF_IRONSTAR: triggeredEventId = EVENT_SHIELD_OF_LIGHT; break; + default: + break; + } + + if (triggeredEventId) + _events.ScheduleEvent(triggeredEventId, 1s); + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_EXECUTION_SENTENCE_VISUAL) + { + summon->m_Events.AddEventAtOffset([summon]() + { + Movement::MoveSplineInit init(summon); + init.MoveTo(summon->GetPositionX(), summon->GetPositionY(), summon->GetFloorZ(), false); + init.SetVelocity(0.54f); + init.Launch(); + }, 2s+ 500ms); + } + } + + void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override + { + if (spell->Id == SPELL_SHIELD_OF_LIGHT && reason == SPELL_FINISHED_SUCCESSFUL_CAST) + { + _events.DelayEvents(1s + 100ms); + _events.ScheduleEvent(EVENT_EXECUTION_SENTENCE, 1s); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BURDEN_OF_THE_CROWN: + DoCastVictim(SPELL_BURDEN_OF_THE_CROWN); + _events.Repeat(31s); + break; + case EVENT_CHAIN_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 90.f, true)) + DoCast(target, SPELL_CHAIN_LIGHTNING); + _events.Repeat(10s, 11s); + break; + case EVENT_STORMBOLT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.f, true)) + DoCast(target, SPELL_STORMBOLT); + _events.Repeat(19s, 23s); + break; + case EVENT_THUNDERCLAP: + if (me->GetVictim()->IsWithinMeleeRange(me)) + { + DoCastAOE(SPELL_THUNDERCLAP); + _events.Repeat(6s, 8s); + } + else + _events.Repeat(1s); + break; + case EVENT_WHIRLWIND: + DoCastSelf(SPELL_WHIRLWIND); + _events.Repeat(34s, 36s); + break; + case EVENT_AVATAR: + DoCastSelf(SPELL_AVATAR); + _events.Repeat(34s, 36s); + break; + case EVENT_STONEBLOOD: + DoCastSelf(SPELL_STONEBLOOD); + _events.Repeat(19s, 23s); + break; + case EVENT_SHIELD_OF_LIGHT: + DoCastSelf(SPELL_SHIELD_OF_LIGHT); + break; + case EVENT_EXECUTION_SENTENCE: + if (me->GetVictim() && !me->GetVictim()->HasAura(SPELL_EXECUTION_SENTENCE)) + { + DoCastVictim(SPELL_EXECUTION_SENTENCE_SUMMON_1); + DoCastVictim(SPELL_EXECUTION_SENTENCE_SUMMON_2); + DoCastVictim(SPELL_EXECUTION_SENTENCE); + } + _events.Repeat(34s, 36s); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; +}; + struct go_bwd_ancient_bell : public GameObjectAI { go_bwd_ancient_bell(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { } bool GossipHello(Player* /*player*/) override { - if (_instance->GetData(DATA_ATRAMEDES_INTRO) == DONE) - return true; - _instance->SetData(DATA_ATRAMEDES_INTRO, DONE); me->SendCustomAnim(0); me->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); @@ -341,6 +589,98 @@ class spell_bwd_grievous_wound : public AuraScript } }; +class spell_bwd_execution_sentence_visual : public SpellScript +{ + PrepareSpellScript(spell_bwd_execution_sentence_visual); + + void SetDest(SpellDestination& dest) + { + dest.RelocateOffset({ 0.0f, 0.0f, 15.0f, 0.0f }); + } + + void Register() + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_bwd_execution_sentence_visual::SetDest, EFFECT_0, TARGET_DEST_TARGET_ENEMY); + } +}; + +class spell_bwd_execution_sentence_dummy : public SpellScript +{ + PrepareSpellScript(spell_bwd_execution_sentence_dummy); + + void HandleDummyEffect(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Creature* creature = GetHitCreature(); + if (!caster || !creature) + return; + + if (TempSummon* summon = creature->ToTempSummon()) + if (summon->GetSummoner() == caster) + summon->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_bwd_execution_sentence_dummy::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_bwd_execution_sentence : public AuraScript +{ + PrepareAuraScript(spell_bwd_execution_sentence); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_EXECUTION_SENTENCE_DUMMY }); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode().HasFlag(AuraRemoveFlags::ByCancel | AuraRemoveFlags::ByDeath)) + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_EXECUTION_SENTENCE_DUMMY, true); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_bwd_execution_sentence::HandleRemove, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } +}; + +class spell_bwd_stoneblood : public SpellScript +{ + PrepareSpellScript(spell_bwd_stoneblood); + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + std::unordered_set aurasToRemove; + Unit* target = GetHitUnit(); + for (auto itr : target->GetAppliedAuras()) + { + Aura* aura = itr.second->GetBase(); + if (!aura) + continue; + + // Todo: this check should be more generic so it can detect actual hostile effects but it'll do for the dwarven spirits for the time being. + if (Unit* caster = aura->GetCaster()) + if (caster->IsPlayer() || caster->IsSummon()) + aurasToRemove.insert(aura); + } + + for (std::unordered_set::const_iterator itr = aurasToRemove.begin(); itr != aurasToRemove.end();) + { + (*itr)->Remove(AuraRemoveFlags::ByEnemySpell); + itr = aurasToRemove.erase(itr); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_bwd_stoneblood::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + class at_bwd_intro: public OnlyOnceAreaTriggerScript { public: @@ -358,8 +698,13 @@ void AddSC_blackwing_descent() { RegisterBlackwingDescentCreatureAI(npc_bwd_lord_victor_nefarius); RegisterBlackwingDescentCreatureAI(npc_bwd_drakonid_chainwielder); + RegisterBlackwingDescentCreatureAI(npc_bwd_dwarven_spirit); RegisterGameObjectAI(go_bwd_ancient_bell); RegisterSpellScript(spell_bwd_dragon_orb); RegisterAuraScript(spell_bwd_grievous_wound); + RegisterSpellScript(spell_bwd_execution_sentence_visual); + RegisterSpellScript(spell_bwd_execution_sentence_dummy); + RegisterAuraScript(spell_bwd_execution_sentence); + RegisterSpellScript(spell_bwd_stoneblood); new at_bwd_intro(); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h index 26bcd48229e..827eefb1319 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h @@ -36,7 +36,8 @@ enum BWDDataTypes DATA_NEFARIANS_END = 5, /*Events*/ - DATA_DEAD_DWARF_SPIRITS, + DATA_RESET_DWARVEN_SPIRIT_GROUP, + DATA_DWARVEN_SPIRIT_DIED, DATA_ANCIENT_BELL, DATA_COLUMN_OF_LIGHT, DATA_ATRAMEDES_INTRO, @@ -165,7 +166,8 @@ enum BWDCreatureIds // Generic Creatures NPC_DRAKONID_DRUDGE = 42362, - NPC_OVERHEAD_SMASH = 42690 + NPC_OVERHEAD_SMASH = 42690, + NPC_EXECUTION_SENTENCE_VISUAL = 43206 }; enum BWDGameObjectIds @@ -181,8 +183,13 @@ enum BWDGameObjectIds enum BWDMisc { + // Magmaw MASSIVE_CRASH_SIDE_LEFT = 0, - MASSIVE_CRASH_SIDE_RIGHT = 1 + MASSIVE_CRASH_SIDE_RIGHT = 1, + + // Dwarven Spirit Council + DWARVEN_SPIRIT_GROUP_LEFT = 0, + DWARVEN_SPIRIT_GROUP_RIGHT = 1 }; enum BWDSpells diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp index 2939a3a8916..45e91eb0668 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp @@ -86,7 +86,9 @@ enum Events EVENT_MAKE_ANCIENT_BELL_SELECTABLE = 1, EVENT_RESPAWN_ATRAMEDES, EVENT_RESPAWN_NEFARIAN, - EVENT_RAISE_ELEVATOR + EVENT_RAISE_ELEVATOR, + EVENT_RESPAWN_LEFT_DWARVEN_GROUP, + EVENT_RESPAWN_RIGHT_DWARVEN_GROUP }; enum Actions @@ -98,7 +100,9 @@ enum Actions enum SpawnGroup { SPAWN_GROUP_ANCIENT_DWARVEN_SHIELDS = 400, - SPAWN_GROUP_NEFARIANS_END = 402 + SPAWN_GROUP_NEFARIANS_END = 402, + SPAWN_GROUP_DWARVEN_SPIRITS_LEFT = 435, + SPAWN_GROUP_DWARVEN_SPIRITS_RIGHT = 436 }; enum SummonGroups @@ -124,7 +128,8 @@ class instance_blackwing_descent : public InstanceMapScript SetBossNumber(EncounterCount); LoadObjectData(creatureData, gameobjectData); LoadDoorData(doorData); - _deadDwarfSpirits = 0; + _deadDwarfSpiritsLeft = 0; + _deadDwarfSpiritsRight = 0; _atramedesIntroState = NOT_STARTED; _nefarianAchievementEligible = true; _nefariansEndIntroDone = false; @@ -133,6 +138,8 @@ class instance_blackwing_descent : public InstanceMapScript void Create() override { instance->SpawnGroupSpawn(SPAWN_GROUP_ANCIENT_DWARVEN_SHIELDS, true); + instance->SpawnGroupSpawn(SPAWN_GROUP_DWARVEN_SPIRITS_LEFT, true); + instance->SpawnGroupSpawn(SPAWN_GROUP_DWARVEN_SPIRITS_RIGHT, true); } void OnCreatureCreate(Creature* creature) override @@ -209,36 +216,6 @@ class instance_blackwing_descent : public InstanceMapScript if (GetBossState(DATA_MAGMAW) == DONE && GetBossState(DATA_OMNOTRON_DEFENSE_SYSTEM) == DONE) go->SetGoState(GO_STATE_ACTIVE); break; - case GO_ANCIENT_BELL: - if (_deadDwarfSpirits == 8 && _atramedesIntroState != DONE) - { - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - if (Creature* column = instance->SummonCreature(NPC_COLUMN_OF_LIGHT, ColumnOfLightPosition)) - column->CastSpell(column, SPELL_COLUMN_OF_LIGHT); - } - break; - default: - break; - } - } - - void OnUnitDeath(Unit* unit) override - { - if (unit->GetTypeId() != TYPEID_UNIT) - return; - - switch (unit->GetEntry()) - { - case NPC_SPIRIT_OF_MOLTENFIST: - case NPC_SPIRIT_OF_ANVILRAGE: - case NPC_SPIRIT_OF_SHADOWFORGE: - case NPC_SPIRIT_OF_COREHAMMER: - case NPC_SPIRIT_OF_ANGERFORGE: - case NPC_SPIRIT_OF_IRONSTAR: - case NPC_SPIRIT_OF_THAURISSAN: - case NPC_SPIRIT_OF_BURNINGEYE: - SetData(DATA_DEAD_DWARF_SPIRITS, DONE); - break; default: break; } @@ -318,12 +295,17 @@ class instance_blackwing_descent : public InstanceMapScript { switch (type) { - case DATA_DEAD_DWARF_SPIRITS: - _deadDwarfSpirits++; - SaveToDB(); + case DATA_DWARVEN_SPIRIT_DIED: + if (data == DWARVEN_SPIRIT_GROUP_LEFT) + ++_deadDwarfSpiritsLeft; + else + ++_deadDwarfSpiritsRight; - if (_deadDwarfSpirits == 8) + if ((_deadDwarfSpiritsLeft + _deadDwarfSpiritsRight) == 8) { + _atramedesIntroState = DONE; + SaveToDB(); + std::list summoned; instance->SummonCreatureGroup(SUMMON_GROUP_ATRAMEDES_INTRO, &summoned); for (TempSummon* summon : summoned) @@ -333,22 +315,38 @@ class instance_blackwing_descent : public InstanceMapScript _events.ScheduleEvent(EVENT_MAKE_ANCIENT_BELL_SELECTABLE, 4s + 500ms); } break; - case DATA_ATRAMEDES_INTRO: - _atramedesIntroState = data; - - if (Creature* atramedes = instance->SummonCreature(BOSS_ATRAMEDES, AtramedesIntroSummonPosition)) + case DATA_RESET_DWARVEN_SPIRIT_GROUP: + if (data == DWARVEN_SPIRIT_GROUP_LEFT) { - for (ObjectGuid guid : _atramedesIntroGUIDs) - if (Creature* intro = instance->GetCreature(guid)) - intro->DespawnOrUnsummon(); - - atramedes->SetDisableGravity(true); - atramedes->SetReactState(REACT_PASSIVE); - atramedes->SendSetPlayHoverAnim(true); - atramedes->AI()->DoAction(ACTION_START_ATRAMEDES_INTRO); + _deadDwarfSpiritsLeft = 0; + _events.RescheduleEvent(EVENT_RESPAWN_LEFT_DWARVEN_GROUP, 30s); + instance->SpawnGroupDespawn(SPAWN_GROUP_DWARVEN_SPIRITS_LEFT); + } + else + { + _deadDwarfSpiritsRight = 0; + _events.RescheduleEvent(EVENT_RESPAWN_RIGHT_DWARVEN_GROUP, 30s); + instance->SpawnGroupDespawn(SPAWN_GROUP_DWARVEN_SPIRITS_RIGHT); } - SaveToDB(); + break; + case DATA_ATRAMEDES_INTRO: + if (!GetCreature(DATA_ATRAMEDES)) + { + if (Creature* atramedes = instance->SummonCreature(BOSS_ATRAMEDES, AtramedesIntroSummonPosition)) + { + for (ObjectGuid guid : _atramedesIntroGUIDs) + if (Creature* intro = instance->GetCreature(guid)) + intro->DespawnOrUnsummon(); + + atramedes->SetDisableGravity(true); + atramedes->SetReactState(REACT_PASSIVE); + atramedes->SendSetPlayHoverAnim(true); + + if (atramedes->IsAIEnabled) + atramedes->AI()->DoAction(ACTION_START_ATRAMEDES_INTRO); + } + } break; case DATA_ENTRANCE_INTRO: { @@ -481,6 +479,12 @@ class instance_blackwing_descent : public InstanceMapScript if (Transport* transport = gameobject->ToTransport()) transport->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 1); break; + case EVENT_RESPAWN_LEFT_DWARVEN_GROUP: + instance->SpawnGroupSpawn(SPAWN_GROUP_DWARVEN_SPIRITS_LEFT, true); + break; + case EVENT_RESPAWN_RIGHT_DWARVEN_GROUP: + instance->SpawnGroupSpawn(SPAWN_GROUP_DWARVEN_SPIRITS_RIGHT, true); + break; default: break; } @@ -489,22 +493,26 @@ class instance_blackwing_descent : public InstanceMapScript void WriteSaveDataMore(std::ostringstream& data) override { - data << _deadDwarfSpirits << ' ' - << _atramedesIntroState; + data << _atramedesIntroState; } void ReadSaveDataMore(std::istringstream& data) override { - data >> _deadDwarfSpirits; data >> _atramedesIntroState; - // Atramedes' intro is done but he has not been defeated yet: spawm him at his respawn location - if (_atramedesIntroState == DONE && GetBossState(DATA_ATRAMEDES) != DONE) - instance->SummonCreature(BOSS_ATRAMEDES, AtramedesRespawnPosition); - if (GetBossState(DATA_ATRAMEDES) != DONE) + { instance->SpawnGroupSpawn(SPAWN_GROUP_ANCIENT_DWARVEN_SHIELDS, true); + if (_atramedesIntroState == DONE) + instance->SummonCreature(BOSS_ATRAMEDES, AtramedesRespawnPosition); + else + { + instance->SpawnGroupSpawn(SPAWN_GROUP_DWARVEN_SPIRITS_LEFT, true); + instance->SpawnGroupSpawn(SPAWN_GROUP_DWARVEN_SPIRITS_RIGHT, true); + } + } + if (IsNefarianAvailable()) instance->SpawnGroupSpawn(SPAWN_GROUP_NEFARIANS_END, true); } @@ -517,7 +525,8 @@ class instance_blackwing_descent : public InstanceMapScript ObjectGuid _roomStalkerTargetDummyRightGuid; GuidVector _roomStalkerGUIDs; GuidVector _atramedesIntroGUIDs; - uint8 _deadDwarfSpirits; + uint8 _deadDwarfSpiritsLeft; + uint8 _deadDwarfSpiritsRight; uint8 _atramedesIntroState; bool _nefarianAchievementEligible; bool _nefariansEndIntroDone;