mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
fix(Scripts/IcecrownCitadel): Fixed Blood Orb Game Object (#24340)
Co-authored-by: Lucas Nascimento <keader.android@gmail.com>
This commit is contained in:
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<uint32> 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<Creature*> creatures;
|
||||
ICCOrbControllerMinionSearch check(me, false);
|
||||
Acore::CreatureListSearcher<ICCOrbControllerMinionSearch> 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<Creature*> creatures;
|
||||
ICCOrbControllerMinionSearch check(me, true);
|
||||
Acore::CreatureListSearcher<ICCOrbControllerMinionSearch> 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<WorldObject*>& 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<WorldObject*> _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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user