From ac6592ae3fd1599962a125e1170d7022dd6bb9fd Mon Sep 17 00:00:00 2001 From: EricksOliveira Date: Fri, 24 Jul 2026 19:03:44 +0000 Subject: [PATCH] fix(Scripts/IcecrownCitadel): Fixed Blood Orb Game Object (#24340) Co-authored-by: Lucas Nascimento --- .../rev_1767742001111707700.sql | 31 + .../game/Spells/SpellInfoCorrections.cpp | 6 - .../boss_blood_prince_council.cpp | 4 + .../boss_blood_queen_lana_thel.cpp | 4 + .../IcecrownCitadel/icecrown_citadel.cpp | 677 ++++++++++++++++++ .../IcecrownCitadel/icecrown_citadel.h | 11 + 6 files changed, 727 insertions(+), 6 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1767742001111707700.sql diff --git a/data/sql/updates/pending_db_world/rev_1767742001111707700.sql b/data/sql/updates/pending_db_world/rev_1767742001111707700.sql new file mode 100644 index 000000000..3bc12c5f2 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1767742001111707700.sql @@ -0,0 +1,31 @@ +-- +UPDATE `creature_template` SET `unit_flags`=33554432 WHERE `entry`=38463; +UPDATE `creature_template` SET `ScriptName`='npc_icc_orb_controller' WHERE `entry`=38463; +UPDATE `creature_template` SET `ScriptName`='npc_darkfallen_blood_knight' WHERE `entry`=37595; +UPDATE `creature_template` SET `ScriptName`='npc_darkfallen_noble' WHERE `entry`=37663; +UPDATE `creature_template` SET `ScriptName`='npc_vampiric_fiend' WHERE `entry`=37901; +UPDATE `creature_template` SET `ScriptName`='npc_darkfallen_archmage' WHERE `entry`=37664; +UPDATE `creature_template` SET `ScriptName`='npc_darkfallen_advisor' WHERE `entry`=37571; +UPDATE `creature_template` SET `ScriptName`='npc_darkfallen_tactician' WHERE `entry`=37666; +UPDATE `gameobject_template` SET `ScriptName`='go_empowering_blood_orb' WHERE `entry`=201741; + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (70227,70304,70299,70450,72131,70939); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(70227,'spell_icc_empowered_blood'), +(70304,'spell_icc_empowered_blood_3'), +(70299,'spell_icc_siphon_essence'), +(70450,'spell_darkfallen_blood_mirror'), +(72131,'spell_generic_remove_empowered_blood'), +(70939,'spell_generic_remove_empowered_blood'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (72099,70299,70293); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,72099,0,0,31,0,3,36934,0,0,0,0,'','Effect_0 hits Empowering Orb Controller'), +(13,1,70299,0,0,31,0,3,36934,0,0,0,0,'','Effect_0 hits Empowering Orb Controller'), +(13,1,70293,0,0,31,0,3,38463,0,0,0,0,'','Effect_0 hits Empowering Orb Controller'); + +DELETE FROM `creature_template_movement` WHERE `CreatureId`=36934; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`) VALUES +(36934,0,0,1,1,0,0); + +DELETE FROM `creature` WHERE `guid` IN (201220,201473,201559) AND `id`=38463; diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 0c44900dc..eab2da490 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -3300,12 +3300,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].MiscValue = 100; }); - // Empowered Blood - ApplySpellFix({ 70227, 70232 }, [](SpellInfo* spellInfo) - { - spellInfo->AreaGroupId = 2452; // Whole icc instead of Crimson Halls only, remove when area calculation is fixed - }); - ApplySpellFix({ 74509 }, [](SpellInfo* spellInfo) { spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_20_YARDS); // 20yd diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index a686b46a3..c4ba87933 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -101,6 +101,8 @@ enum Spells SPELL_KINETIC_BOMB = 72080, SPELL_SHOCK_VORTEX = 72037, SPELL_EMPOWERED_SHOCK_VORTEX = 72039, + SPELL_REMOVE_EMPOWERED_BLOOD = 72131, + SPELL_CLEAR_ALL_STATUS_AILMENTS = 70939, // Kinetic Bomb SPELL_UNSTABLE = 72059, @@ -233,6 +235,7 @@ public: _isEmpowered = false; _evading = false; me->SetHealth(me->GetMaxHealth()); + me->CastSpell(me, SPELL_REMOVE_EMPOWERED_BLOOD, true); me->SetReactState(REACT_AGGRESSIVE); } @@ -261,6 +264,7 @@ public: me->SetLootRecipient(who); me->LowerPlayerDamageReq(me->GetMaxHealth()); me->SetReactState(REACT_AGGRESSIVE); + DoCastSelf(SPELL_CLEAR_ALL_STATUS_AILMENTS, true); instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); if (Creature* taldaram = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID))) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 3456652ca..0b8b0bb68 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -71,6 +71,7 @@ enum Spells SPELL_INCITE_TERROR = 73070, SPELL_BLOODBOLT_WHIRL = 71772, SPELL_ANNIHILATE = 71322, + SPELL_CLEAR_ALL_STATUS_AILMENTS = 70939, }; enum Shadowmourne @@ -224,8 +225,11 @@ public: me->setActive(true); DoZoneInCombat(); Talk(SAY_AGGRO); + if (instance->GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) != DONE) instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, IN_PROGRESS); + + DoCastSelf(SPELL_CLEAR_ALL_STATUS_AILMENTS, true); _creditBloodQuickening = instance->GetData(DATA_BLOOD_QUICKENING_STATE) == IN_PROGRESS; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index bdde946bd..cd541ced1 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -21,6 +21,8 @@ #include "Cell.h" #include "CellImpl.h" #include "CreatureScript.h" +#include "GameObject.h" +#include "GameObjectAI.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "Group.h" @@ -160,6 +162,46 @@ enum Spells // Invisible Stalker (Float, Uninteractible, LargeAOI) SPELL_SOUL_MISSILE = 72585, + + // Empowering Blood Orb + SPELL_EMPOWERED_BLOOD_2 = 70232, + SPELL_EMPOWERED_BLOOD_3 = 70304, + SPELL_EMPOWERED_BLOOD_4 = 70320, + SPELL_ORB_CONTROLLER_ACTIVE = 70293, + + // Darkfallen Generic + SPELL_BLOOD_ORB_VISUAL = 72099, + SPELL_SIPHON_ESSENCE = 70299, + + // Darkfallen Blood Knight + SPELL_VAMPIRIC_AURA = 71736, + SPELL_BLOOD_MIRROR = 70450, + SPELL_BLOOD_MIRROR_2 = 70451, + SPELL_BLOOD_MIRROR_DAMAGE_SHARE = 70445, + SPELL_UNHOLY_STRIKE = 70437, + + // Darkfallen Noble + SPELL_SHADOW_BOLT = 72960, + SPELL_CHAINS_OF_SHADOW = 70645, + + // Darkfallen Archmage + SPELL_FIREBALL = 70409, + SPELL_AMPLIFY_MAGIC = 70408, + SPELL_BLAST_WAVE = 70407, + SPELL_POLYMORPH_ALLY = 72106, + SPELL_POLYMORPH = 70410, + + // Darkfallen Advisor + SPELL_LICH_SLAP = 72057, + SPELL_SHROUD_OF_SPELL_WARDING = 72066, + + // Vampiric Fiend + SPELL_DISEASE_CLOUD = 41290, + SPELL_LEECHING_ROOT = 70671, + + // Darkfallen Tactician + SPELL_SHADOWSTEP = 70431, + SPELL_BLOOD_SAP = 70432 }; // Helper defines @@ -258,6 +300,7 @@ enum EventTypes enum DataTypesICC { DATA_DAMNED_KILLS = 1, + DATA_GUID }; enum Actions @@ -268,6 +311,9 @@ enum Actions ACTION_RESURRECT_CAPTAINS = 3, ACTION_CAPTAIN_DIES = 4, ACTION_RESET_EVENT = 5, + ACTION_SIPHON_INTERRUPTED = 6, + ACTION_EVADE = 7, + ACTION_COMBAT = 8 }; enum EventIds @@ -1940,6 +1986,624 @@ public: } }; +class ICCOrbControllerMinionSearch +{ +public: + ICCOrbControllerMinionSearch(Unit* owner, bool checkCasting) : _owner(owner), _checkCasting(checkCasting) {} + + bool operator()(Creature* target) const + { + if (!target->IsAlive() || (_checkCasting && target->HasUnitState(UNIT_STATE_CASTING)) || target->GetWaypointPath() || _owner->GetDistance(target) > 10.0f) + return false; + + switch (target->GetEntry()) + { + case NPC_DARKFALLEN_BLOOD_KNIGHT: + case NPC_DARKFALLEN_NOBLE: + case NPC_DARKFALLEN_ARCHMAGE: + case NPC_DARKFALLEN_ADVISOR: + case NPC_DARKFALLEN_TACTICIAN: + return true; + default: + return false; + } + } + +private: + // Need check to not use polymorph in a casting creature + Unit* _owner; + bool _checkCasting; +}; + +std::vector DarkFallensEmotes = +{ + EMOTE_ONESHOT_TALK, + EMOTE_ONESHOT_EXCLAMATION, + EMOTE_ONESHOT_QUESTION, + EMOTE_ONESHOT_LAUGH, + EMOTE_ONESHOT_YES, + EMOTE_ONESHOT_NO +}; + +// 38463 - Empowering Orb Visual Stalker +struct npc_icc_orb_controller : public ScriptedAI +{ + npc_icc_orb_controller(Creature* creature) : ScriptedAI(creature), _isInCombat(false), _isLongRepeat(false) {} + + void Reset() override + { + _scheduler.Schedule(1s, [this](TaskContext /*initialize*/) + { + std::vector creatures; + ICCOrbControllerMinionSearch check(me, false); + Acore::CreatureListSearcher searcher(me, creatures, check); + Cell::VisitObjects(me, searcher, 10.0f); + + if (creatures.empty()) + return; + + for (Creature* creature : creatures) + { + creature->AI()->SetGUID(me->GetGUID(), DATA_GUID); + _minionGuids.push_back(creature->GetGUID()); + } + + ScheduleVisualChannel(false); + }); + } + + void ScheduleVisualChannel(bool evading) + { + _scheduler.Schedule(evading ? 5s : 1s, [this](TaskContext visual) + { + if (_minionGuids.empty()) + return; + + ObjectGuid mGuid = Acore::Containers::SelectRandomContainerElement(_minionGuids); + if (Unit* minion = ObjectAccessor::GetUnit(*me, mGuid)) + minion->CastSpell(nullptr, SPELL_BLOOD_ORB_VISUAL); + + visual.Repeat(_isLongRepeat ? 21s : 3s); + _isLongRepeat = !_isLongRepeat; + }); + } + + void UpdateValidGuids() + { + for (GuidVector::iterator itr = _minionGuids.begin(); itr != _minionGuids.end();) + { + if (Unit* minion = ObjectAccessor::GetUnit(*me, (*itr))) + { + if (!minion->IsAlive()) + { + itr = _minionGuids.erase(itr); + continue; + } + + ++itr; + } + // Is not in world anymore + else + itr = _minionGuids.erase(itr); + } + } + + void SpellHit(Unit* caster, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_ORB_CONTROLLER_ACTIVE) + if (GameObject* orb = me->FindNearestGameObject(GO_EMPOWERING_BLOOD_ORB, 5.0f)) + orb->AI()->SetGUID(caster->GetGUID(), DATA_GUID); + } + + void SetGUID(ObjectGuid const& guid, int32 id) override + { + if (id != ACTION_COMBAT || _isInCombat) + return; + + Creature* darkfallen = ObjectAccessor::GetCreature(*me, guid); + if (!darkfallen) + return; + + _isInCombat = true; + _scheduler.CancelAll(); + if (_minionGuids.empty()) + return; + + for (ObjectGuid minionGuid : _minionGuids) + { + if (Creature* minion = ObjectAccessor::GetCreature(*me, minionGuid)) + if (minion->IsAIEnabled && !minion->IsInCombat()) + minion->AI()->DoZoneInCombat(darkfallen); + } + + if (Unit* minion = ObjectAccessor::GetUnit(*me, Acore::Containers::SelectRandomContainerElement(_minionGuids))) + minion->CastSpell(nullptr, SPELL_SIPHON_ESSENCE); + } + + void DoAction(int32 action) override + { + if (action == ACTION_EVADE && _isInCombat) + { + _isInCombat = false; + UpdateValidGuids(); + ScheduleVisualChannel(true); + if (GameObject* orb = me->FindNearestGameObject(GO_EMPOWERING_BLOOD_ORB, 5.0f)) + orb->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + } + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + + if (_isInCombat) + { + UpdateValidGuids(); + if (_minionGuids.empty()) + DoAction(ACTION_EVADE); + } + } + +private: + TaskScheduler _scheduler; + GuidVector _minionGuids; + bool _isInCombat; + bool _isLongRepeat; +}; + +struct DarkFallenAI : public ScriptedAI +{ + DarkFallenAI(Creature* creature) : ScriptedAI(creature), IsDoingEmotes(true), AttackSpellId(0) {} + + virtual void ScheduleSpells() = 0; + + void Reset() override + { + IsDoingEmotes = me->GetWaypointPath() ? false : true; + Scheduler.CancelAll(); + Scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }) + .Schedule(1s, 10s, [this](TaskContext emote) + { + if (!IsDoingEmotes) + return; + + if (roll_chance_i(20)) + { + std::vector creatures; + ICCOrbControllerMinionSearch check(me, true); + Acore::CreatureListSearcher searcher(me, creatures, check); + Cell::VisitObjects(me, searcher, 10.0f); + if (!creatures.empty()) + { + Creature* friendly = Acore::Containers::SelectRandomContainerElement(creatures); + DoCast(friendly, SPELL_POLYMORPH_ALLY); + } + } + Scheduler.Schedule(1s, [this](TaskContext /*emote*/) + { + me->HandleEmoteCommand(Acore::Containers::SelectRandomContainerElement(DarkFallensEmotes)); + }); + emote.Repeat(15s, 30s); + }); + } + + void JustEngagedWith(Unit* /*who*/) override + { + IsDoingEmotes = false; + Scheduler.CancelAll(); + ScheduleSpells(); + if (Unit* trigger = ObjectAccessor::GetUnit(*me, TriggerGuid)) + trigger->GetAI()->SetGUID(me->GetGUID(), ACTION_COMBAT); + } + + void DoAction(int32 action) override + { + if (action == ACTION_SIPHON_INTERRUPTED) + if (GameObject* orb = me->FindNearestGameObject(GO_EMPOWERING_BLOOD_ORB, 10.0f)) + orb->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + } + + void SetGUID(ObjectGuid const& guid, int32 id) override + { + if (id == DATA_GUID) + TriggerGuid = guid; + } + + void EnterEvadeMode(EvadeReason why) override + { + ScriptedAI::EnterEvadeMode(why); + if (Unit* trigger = ObjectAccessor::GetUnit(*me, TriggerGuid)) + trigger->GetAI()->DoAction(ACTION_EVADE); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !IsDoingEmotes) + return; + + Scheduler.Update(diff); + + if (AttackSpellId) + DoSpellAttackIfReady(AttackSpellId); + else + DoMeleeAttackIfReady(); + } + +protected: + TaskScheduler Scheduler; + ObjectGuid TriggerGuid; + bool IsDoingEmotes; + uint32 AttackSpellId; +}; + +struct npc_darkfallen_blood_knight : public DarkFallenAI +{ + npc_darkfallen_blood_knight(Creature* creature) : DarkFallenAI(creature) {} + + void ScheduleSpells() override + { + Scheduler.Schedule(500ms, [this](TaskContext /*context*/) + { + DoCastSelf(SPELL_VAMPIRIC_AURA); + }) + .Schedule(8s, [this](TaskContext unholyStrike) + { + DoCastVictim(SPELL_UNHOLY_STRIKE); + unholyStrike.Repeat(8s, 9s); + }) + .Schedule(6s, [this](TaskContext bloodMirror) + { + DoCastSelf(SPELL_BLOOD_MIRROR); + bloodMirror.Repeat(34s); + }); + } +}; + +struct npc_darkfallen_noble : public DarkFallenAI +{ + npc_darkfallen_noble(Creature* creature) : DarkFallenAI(creature) {} + + void ScheduleSpells() override + { + AttackSpellId = SPELL_SHADOW_BOLT; + Scheduler.Schedule(500ms, [this](TaskContext /*context*/) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_CHAINS_OF_SHADOW)) + DoCast(target, SPELL_CHAINS_OF_SHADOW); + }) + .Schedule(11s, [this](TaskContext summonVampiric) + { + // Vampiric should be summoned by 70647 but i have no idea what is miscB of summon effect + if (Unit* target = me->GetVictim()) + if (Creature* vampiric = me->SummonCreature(NPC_VAMPIRIC_FIEND, target->GetPosition(), TEMPSUMMON_CORPSE_DESPAWN)) + vampiric->AI()->AttackStart(target); + + summonVampiric.Repeat(30s); + }); + } +}; + +struct npc_vampiric_fiend : public ScriptedAI +{ + npc_vampiric_fiend(Creature* creature) : ScriptedAI(creature) {} + + void JustEngagedWith(Unit* /*who*/) override + { + DoCastSelf(SPELL_DISEASE_CLOUD); + _scheduler.Schedule(9s, [this](TaskContext /*leechingRoot*/) + { + DoCastVictim(SPELL_LEECHING_ROOT); + }) + .Schedule(38s, [this](TaskContext /*leechingRoot*/) + { + me->DespawnOrUnsummon(); + }); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _scheduler.CancelAll(); + me->DespawnOrUnsummon(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + + DoMeleeAttackIfReady(); + } + +private: + TaskScheduler _scheduler; +}; + +// 37664 - Darkfallen Archmage +struct npc_darkfallen_archmage : public DarkFallenAI +{ + npc_darkfallen_archmage(Creature* creature) : DarkFallenAI(creature) {} + + void ScheduleSpells() override + { + AttackSpellId = SPELL_FIREBALL; + Scheduler.Schedule(1s, [this](TaskContext amplifyMagic) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) + DoCast(target, SPELL_AMPLIFY_MAGIC); + + amplifyMagic.Repeat(15s, 24s); + }) + .Schedule(10s, [this](TaskContext blastWave) + { + DoCastSelf(SPELL_BLAST_WAVE); + blastWave.Repeat(25s, 30s); + }) + .Schedule(17s, [this](TaskContext polymorph) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_POLYMORPH)) + DoCast(target, SPELL_POLYMORPH); + + polymorph.Repeat(25s, 35s); + }); + } +}; + +// 37571 - Darkfallen Advisor +struct npc_darkfallen_advisor : public DarkFallenAI +{ + npc_darkfallen_advisor(Creature* creature) : DarkFallenAI(creature) {} + + void ScheduleSpells() override + { + Scheduler.Schedule(8s, [this](TaskContext lichSlap) + { + DoCastVictim(SPELL_LICH_SLAP); + lichSlap.Repeat(12s); + }) + .Schedule(50s, [this](TaskContext immunity) + { + if (Unit* target = DoSelectLowestHpFriendly(40.0f)) + DoCast(target, SPELL_SHROUD_OF_SPELL_WARDING); + + immunity.Repeat(20s, 25s); + }); + } +}; + +// 37666 - Darkfallen Tactician +struct npc_darkfallen_tactician : public DarkFallenAI +{ + npc_darkfallen_tactician(Creature* creature) : DarkFallenAI(creature) {} + + void ScheduleSpells() override + { + Scheduler.Schedule(8s, [this](TaskContext unholyStrike) + { + DoCastVictim(SPELL_UNHOLY_STRIKE); + unholyStrike.Repeat(8s, 11s); + }) + .Schedule(10s, [this](TaskContext shadowStep) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false)) + { + DoCast(target, SPELL_SHADOWSTEP); + DoCast(target, SPELL_BLOOD_SAP); + } + shadowStep.Repeat(20s); + }); + } +}; + +// 201741 - Empowering Blood Orb +struct go_empowering_blood_orb : public GameObjectAI +{ + go_empowering_blood_orb(GameObject* go) : GameObjectAI(go) {} + + void Reset() override + { + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _triggerGuid)) + trigger->DespawnOrUnsummon(); + + if (Creature* trigger = me->SummonCreature(NPC_ORB_VISUAL_STALKER, me->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN)) + _triggerGuid = trigger->GetGUID(); + else + _triggerGuid.Clear(); + } + + bool GossipHello(Player* player, bool /*reportUse*/) override + { + me->CastSpell(player, SPELL_EMPOWERED_BLOOD); + HandleObjectUse(); + return true; + } + + void HandleObjectUse() + { + me->SetGameObjectFlag(GO_FLAG_IN_USE); + me->SetGoAnimProgress(255); + me->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _triggerGuid)) + trigger->DespawnOrUnsummon(); + + _scheduler.Schedule(3s, [this](TaskContext /*context*/) + { + me->Delete(); + }); + } + + void SetGUID(ObjectGuid const& guid, int32 id) override + { + if (id == DATA_GUID) + { + if (Unit* target = ObjectAccessor::GetUnit(*me, guid)) + me->CastSpell(target, SPELL_EMPOWERED_BLOOD_3); + + HandleObjectUse(); + } + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + +private: + TaskScheduler _scheduler; + ObjectGuid _triggerGuid; +}; + +// 70227 - Empowered Blood +class spell_icc_empowered_blood : public AuraScript +{ + PrepareAuraScript(spell_icc_empowered_blood); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_EMPOWERED_BLOOD_2 }); + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_EMPOWERED_BLOOD_2, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(SPELL_EMPOWERED_BLOOD_2); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_icc_empowered_blood::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_icc_empowered_blood::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 70304 - Empowered Blood +class spell_icc_empowered_blood_3 : public AuraScript +{ + PrepareAuraScript(spell_icc_empowered_blood_3); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_EMPOWERED_BLOOD_4 }); + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_EMPOWERED_BLOOD_4, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(SPELL_EMPOWERED_BLOOD_4); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_icc_empowered_blood_3::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_icc_empowered_blood_3::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 70299 - Siphon Essence +class spell_icc_siphon_essence : public AuraScript +{ + PrepareAuraScript(spell_icc_siphon_essence); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_CANCEL) + GetTarget()->GetAI()->DoAction(ACTION_SIPHON_INTERRUPTED); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_icc_siphon_essence::OnRemove, EFFECT_1, SPELL_AURA_MOD_ROOT, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 70450 - Blood Mirror +class spell_darkfallen_blood_mirror : public SpellScript +{ + PrepareSpellScript(spell_darkfallen_blood_mirror); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_BLOOD_MIRROR_2, SPELL_BLOOD_MIRROR_DAMAGE_SHARE }); + } + + void FilterTargets(std::list& targets) + { + targets.remove_if([](WorldObject* target) + { + return !target->IsPlayer(); + }); + + if (targets.size() < 2) + { + targets.clear(); + return; + } + + Acore::Containers::RandomResize(targets, 2); + _targets = targets; + } + + void HandleMirror(SpellEffIndex /*effIndex*/) + { + if (_targets.empty()) + return; + + Unit* caster = GetCaster(); + Unit* target = _targets.front()->ToUnit(); + Unit* mirror = _targets.back()->ToUnit(); + + if (!caster || !target || !mirror) + return; + + caster->CastSpell(target, SPELL_BLOOD_MIRROR_2, true); + target->CastSpell(mirror, SPELL_BLOOD_MIRROR_DAMAGE_SHARE, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_darkfallen_blood_mirror::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectLaunch += SpellEffectFn(spell_darkfallen_blood_mirror::HandleMirror, EFFECT_0, SPELL_EFFECT_DUMMY); + } + +private: + std::list _targets; +}; + +// 72131 - Remove Empowered Blood +// 70939 - Blood Queen Lana'thel - Clear all Status Ailments +class spell_generic_remove_empowered_blood : public SpellScript +{ + PrepareSpellScript(spell_generic_remove_empowered_blood); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_EMPOWERED_BLOOD }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->RemoveAurasDueToSpell(SPELL_EMPOWERED_BLOOD); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_generic_remove_empowered_blood::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + class spell_icc_stoneform_aura : public AuraScript { PrepareAuraScript(spell_icc_stoneform_aura); @@ -3693,6 +4357,19 @@ void AddSC_icecrown_citadel() new npc_frostwing_vrykul(); new npc_impaling_spear(); new npc_arthas_teleport_visual(); + RegisterIcecrownCitadelCreatureAI(npc_icc_orb_controller); + RegisterIcecrownCitadelCreatureAI(npc_darkfallen_blood_knight); + RegisterIcecrownCitadelCreatureAI(npc_darkfallen_noble); + RegisterIcecrownCitadelCreatureAI(npc_vampiric_fiend); + RegisterIcecrownCitadelCreatureAI(npc_darkfallen_archmage); + RegisterIcecrownCitadelCreatureAI(npc_darkfallen_advisor); + RegisterIcecrownCitadelCreatureAI(npc_darkfallen_tactician); + RegisterGameObjectAI(go_empowering_blood_orb); + RegisterSpellScript(spell_icc_empowered_blood); + RegisterSpellScript(spell_icc_empowered_blood_3); + RegisterSpellScript(spell_icc_siphon_essence); + RegisterSpellScript(spell_darkfallen_blood_mirror); + RegisterSpellScript(spell_generic_remove_empowered_blood); RegisterSpellScript(spell_icc_stoneform_aura); RegisterSpellScript(spell_icc_sprit_alarm); RegisterSpellScript(spell_icc_geist_alarm); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index d3f5a724b..77b95abb4 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -62,6 +62,9 @@ enum SharedSpells SPELL_UNSATED_CRAVING = 71168, SPELL_SHADOWS_FATE = 71169, + // Empowering Blood Orb + SPELL_EMPOWERED_BLOOD = 70227, + // Misc SPELL_WEB_BEAM = 69887, SPELL_WEB_BEAM2 = 69986, @@ -282,6 +285,13 @@ enum CreaturesIds NPC_KINETIC_BOMB_TARGET = 38458, NPC_KINETIC_BOMB = 38454, NPC_SHOCK_VORTEX = 38422, + NPC_DARKFALLEN_BLOOD_KNIGHT = 37595, + NPC_DARKFALLEN_NOBLE = 37663, + NPC_DARKFALLEN_ARCHMAGE = 37664, + NPC_DARKFALLEN_ADVISOR = 37571, + NPC_DARKFALLEN_TACTICIAN = 37666, + NPC_VAMPIRIC_FIEND = 37901, + NPC_ORB_VISUAL_STALKER = 38463, // Blood-Queen Lana'thel NPC_BLOOD_QUEEN_LANA_THEL = 37955, @@ -434,6 +444,7 @@ enum GameObjectsIds GO_CRIMSON_HALL_DOOR = 201376, GO_BLOOD_ELF_COUNCIL_DOOR = 201378, GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT = 201377, + GO_EMPOWERING_BLOOD_ORB = 201741, // Blood-Queen Lana'thel GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01 = 201746,