Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2023-04-10 08:27:49 -06:00
committed by GitHub
45 changed files with 1426 additions and 519 deletions

View File

@@ -117,6 +117,7 @@ void EventProcessor::CancelEventGroup(uint8 group)
{
if (itr->second->m_eventGroup != group)
{
++itr;
continue;
}

View File

@@ -691,6 +691,14 @@ void BossAI::ScheduleHealthCheckEvent(uint32 healthPct, std::function<void()> ex
_healthCheckEvents.push_back(HealthCheckEventData(healthPct, exec));
};
void BossAI::ScheduleHealthCheckEvent(std::initializer_list<uint8> healthPct, std::function<void()> exec)
{
for (auto const& checks : healthPct)
{
_healthCheckEvents.push_back(HealthCheckEventData(checks, exec));
}
}
bool BossAI::_ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function<void()> exec) const
{
if (me->HealthBelowPctDamaged(healthPct, damage))

View File

@@ -470,6 +470,7 @@ public:
void UpdateAI(uint32 diff) override;
void ScheduleHealthCheckEvent(uint32 healthPct, std::function<void()> exec);
void ScheduleHealthCheckEvent(std::initializer_list<uint8> healthPct, std::function<void()> exec);
// Hook used to execute events scheduled into EventMap without the need
// to override UpdateAI

View File

@@ -1635,7 +1635,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
float x, y, z;
target->GetPosition(x, y, z);
if (e.action.moveToPos.ContactDistance > 0)
target->GetContactPoint(me, x, y, z, e.action.moveToPos.ContactDistance);
{
target->GetNearPoint(me, x, y, z, e.action.moveToPos.ContactDistance, 0, target->GetAngle(me));
}
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
}
break;

View File

@@ -1428,7 +1428,7 @@ enum SMARTAI_TARGETS
SMART_TARGET_SUMMONED_CREATURES = 204, // Entry
SMART_TARGET_INSTANCE_STORAGE = 205, // Instance data index, Type (creature (1), gameobject (2))
SMART_TARGET_AC_END = 205 // placeholder
SMART_TARGET_AC_END = 206 // placeholder
};
struct SmartTarget

View File

@@ -208,7 +208,10 @@ void InstanceScript::UpdateMinionState(Creature* minion, EncounterState state)
minion->Respawn();
else
{
minion->AI()->DoZoneInCombat(nullptr, 100.0f);
if (minion->GetReactState() == REACT_AGGRESSIVE)
{
minion->AI()->DoZoneInCombat(nullptr, 100.0f);
}
}
break;
default:
@@ -362,6 +365,20 @@ void InstanceScript::StorePersistentData(uint32 index, uint32 data)
persistentData[index] = data;
}
void InstanceScript::DoForAllMinions(uint32 id, std::function<void(Creature*)> exec)
{
BossInfo* bossInfo = &bosses[id];
MinionSet listCopy = bossInfo->minion;
for (auto const& minion : listCopy)
{
if (minion)
{
exec(minion);
}
}
}
void InstanceScript::Load(const char* data)
{
if (!data)

View File

@@ -260,6 +260,9 @@ public:
// Allows to perform particular actions
virtual void DoAction(int32 /*action*/) {}
// Allows executing code using all creatures registered in the instance script as minions
void DoForAllMinions(uint32 id, std::function<void(Creature*)> exec);
protected:
void SetHeaders(std::string const& dataHeaders);
void SetBossNumber(uint32 number) { bosses.resize(number); }

View File

@@ -69,6 +69,7 @@ enum Events
EVENT_JEDOGA_PREPARE_RITUAL,
EVENT_JEDOGA_MOVE_UP,
EVENT_JEDOGA_MOVE_DOWN,
EVENT_JEDGA_START_RITUAL,
// Initiate
EVENT_RITUAL_BEGIN_MOVE,
@@ -384,11 +385,9 @@ struct boss_jedoga_shadowseeker : public BossAI
if (!summons.empty())
{
sacraficeTarget_GUID = Acore::Containers::SelectRandomContainerElement(summons);
if (Creature* volunteer = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID))
if (ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID))
{
Talk(SAY_SACRIFICE_1);
sacraficeTarget_GUID = volunteer->GetGUID();
volunteer->AI()->DoAction(ACTION_RITUAL_BEGIN);
events.ScheduleEvent(EVENT_JEDGA_START_RITUAL, 3s, 0, PHASE_RITUAL);
}
// Something failed, let players continue but do not grant achievement
else
@@ -506,6 +505,17 @@ struct boss_jedoga_shadowseeker : public BossAI
me->GetMotionMaster()->MovePoint(POINT_DOWN, JedogaPosition[1], false);
break;
}
case EVENT_JEDGA_START_RITUAL:
{
sacraficeTarget_GUID = Acore::Containers::SelectRandomContainerElement(summons);
if (Creature* volunteer = ObjectAccessor::GetCreature(*me, sacraficeTarget_GUID))
{
Talk(SAY_SACRIFICE_1);
sacraficeTarget_GUID = volunteer->GetGUID();
volunteer->AI()->DoAction(ACTION_RITUAL_BEGIN);
}
break;
}
}
}
@@ -632,12 +642,8 @@ struct npc_twilight_volunteer : public ScriptedAI
if (Creature* jedoga = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_JEDOGA_SHADOWSEEKER)))
{
jedoga->AI()->Talk(SAY_SACRIFICE_2);
jedoga->CastSpell(nullptr, SPELL_SACRIFICE_BEAM);
if (Creature* ritualTrigger = jedoga->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaPosition[2], TEMPSUMMON_TIMED_DESPAWN, 5000))
{
ritualTrigger->CastSpell(ritualTrigger, SPELL_SACRIFICE_VISUAL);
}
jedoga->CastSpell(nullptr, SPELL_SACRIFICE_BEAM); /// @todo: Visual is not working. (cosmetic)
jedoga->AI()->DoAction(ACTION_SACRAFICE);
}
Talk(SAY_SACRIFICED);
@@ -656,6 +662,14 @@ struct npc_twilight_volunteer : public ScriptedAI
me->SetHomePosition(JedogaPosition[2]);
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_RITUAL, JedogaPosition[2], false);
if (Creature* jedoga = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_JEDOGA_SHADOWSEEKER)))
{
if (Creature* ritualTrigger = jedoga->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaPosition[2], TEMPSUMMON_TIMED_DESPAWN, 15000))
{
ritualTrigger->CastSpell(ritualTrigger, SPELL_SACRIFICE_VISUAL);
}
}
}
}
@@ -688,31 +702,6 @@ class spell_random_lightning_visual_effect : public SpellScript
}
};
// 56150 - Sacrifice Beam
class spell_jedoga_sacrafice_beam : public AuraScript
{
PrepareAuraScript(spell_jedoga_sacrafice_beam);
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_UNIT;
}
void HandleRemoval(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
AuraRemoveMode const removeMode = GetTargetApplication()->GetRemoveMode();
if (removeMode == AURA_REMOVE_BY_DEFAULT || removeMode == AURA_REMOVE_BY_EXPIRE)
{
GetCaster()->ToCreature()->AI()->DoAction(ACTION_SACRAFICE);
}
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_jedoga_sacrafice_beam::HandleRemoval, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
// CriteriaID 7359, Volunteer Work (2056)
class achievement_volunteer_work : public AchievementCriteriaScript
{
@@ -740,7 +729,6 @@ void AddSC_boss_jedoga_shadowseeker()
// Spells
RegisterSpellScript(spell_random_lightning_visual_effect);
RegisterSpellScript(spell_jedoga_sacrafice_beam);
// Achievements
new achievement_volunteer_work();

View File

@@ -85,8 +85,6 @@ enum PaletressEvents
EVENT_SPELL_WAKING_NIGHTMARE,
};
#define TEXT_RADIATE "Eadric the Pure begins to radiate light. Shield your eyes!"
class boss_eadric : public CreatureScript
{
public:
@@ -119,10 +117,7 @@ public:
{
if( who->GetTypeId() == TYPEID_PLAYER )
{
if( urand(0, 1) )
Talk(TEXT_EADRIC_SLAIN_1);
else
Talk(TEXT_EADRIC_SLAIN_2);
Talk(SAY_EADRIC_KILL_PLAYER);
}
}
@@ -131,7 +126,7 @@ public:
events.Reset();
events.ScheduleEvent(EVENT_SPELL_RADIANCE, 16000);
events.ScheduleEvent(EVENT_SPELL_HAMMER_RIGHTEOUS, 25000);
Talk(TEXT_EADRIC_AGGRO);
Talk(SAY_EADRIC_AGGRO);
me->CastSpell(me, SPELL_VENGEANCE, false);
if( pInstance )
pInstance->SetData(BOSS_ARGENT_CHALLENGE, IN_PROGRESS);
@@ -154,7 +149,7 @@ public:
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_CAST_SPELL, 68574, me); // paletress' spell credits encounter, but shouldn't credit achievements
me->SetFaction(FACTION_FRIENDLY);
events.Reset();
Talk(TEXT_EADRIC_DEATH);
Talk(SAY_EADRIC_DEFEATED);
me->GetThreatMgr().clearReferences();
me->SetRegeneratingHealth(false);
_EnterEvadeMode();
@@ -182,16 +177,14 @@ public:
break;
case EVENT_SPELL_RADIANCE:
me->CastSpell((Unit*)nullptr, SPELL_RADIANCE, false);
me->TextEmote(TEXT_RADIATE, nullptr, true);
Talk(SAY_EADRIC_EMOTE_RADIANCE);
events.Repeat(16s);
break;
case EVENT_SPELL_HAMMER_RIGHTEOUS:
if( Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 55.0f, true) )
{
char buffer[100];
snprintf(buffer, sizeof(buffer), "Eadric the Pure targets %s with the Hammer of the Righteous!", target->GetName().c_str());
me->TextEmote(buffer, nullptr, true);
Talk(TEXT_EADRIC_HAMMER);
Talk(SAY_EADRIC_EMOTE_HAMMER_RIGHTEOUS, target);
Talk(SAY_EADRIC_HAMMER_RIGHTEOUS);
me->CastSpell(target, SPELL_HAMMER_JUSTICE, true);
me->CastSpell(target, SPELL_HAMMER_RIGHTEOUS, false);
}
@@ -251,10 +244,7 @@ public:
{
if( who->GetTypeId() == TYPEID_PLAYER )
{
if( urand(0, 1) )
Talk(TEXT_PALETRESS_SLAIN_1);
else
Talk(TEXT_PALETRESS_SLAIN_2);
Talk(SAY_PALETRESS_KILL_PLAYER);
}
}
@@ -264,7 +254,7 @@ public:
events.ScheduleEvent(EVENT_SPELL_HOLY_FIRE, 9s, 12s);
events.ScheduleEvent(EVENT_SPELL_SMITE, 2s, 3s);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
Talk(TEXT_PALETRESS_AGGRO);
Talk(SAY_PALETRESS_AGGRO);
if( pInstance )
pInstance->SetData(BOSS_ARGENT_CHALLENGE, IN_PROGRESS);
}
@@ -275,7 +265,7 @@ public:
{
MemoryGUID.Clear();
me->RemoveAura(SPELL_SHIELD);
Talk(TEXT_PALETRESS_MEMORY_DEFEATED);
Talk(SAY_PALETRESS_MEMORY_DEATH);
}
else if( param == (-1) )
{
@@ -302,7 +292,7 @@ public:
me->CastSpell((Unit*)nullptr, 68574, true); // achievements
me->SetFaction(FACTION_FRIENDLY);
events.Reset();
Talk(TEXT_PALETRESS_DEATH);
Talk(SAY_PALETRESS_DEFEATED);
me->GetThreatMgr().clearReferences();
me->SetRegeneratingHealth(false);
_EnterEvadeMode();
@@ -341,7 +331,7 @@ public:
if( !summoned && HealthBelowPct(25) )
{
me->InterruptNonMeleeSpells(true);
Talk(TEXT_PALETRESS_MEMORY_SUMMON);
Talk(SAY_PALETRESS_MEMORY_SUMMON);
me->CastSpell((Unit*)nullptr, SPELL_HOLY_NOVA, false);
me->CastSpell(me, SPELL_SHIELD, false);
me->CastSpell((Unit*)nullptr, SPELL_SUMMON_MEMORY, false);

View File

@@ -174,7 +174,7 @@ public:
return;
pInstance->SetData(BOSS_BLACK_KNIGHT, IN_PROGRESS);
Talk(TEXT_BK_AGGRO);
Talk(SAY_BK_AGGRO);
me->CastSpell((Unit*)nullptr, (pInstance->GetData(DATA_TEAMID_IN_INSTANCE) == TEAM_HORDE ? SPELL_RAISE_DEAD_JAEREN : SPELL_RAISE_DEAD_ARELAS), false);
if( Creature* announcer = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_ANNOUNCER)) )
announcer->DespawnOrUnsummon();
@@ -209,7 +209,7 @@ public:
{
case 2:
me->SetDisplayId(MODEL_SKELETON);
Talk(TEXT_BK_SKELETON_RES);
Talk(SAY_BK_PHASE_2);
me->CastSpell(me, SPELL_ARMY_DEAD, false);
events.Reset();
@@ -220,7 +220,7 @@ public:
break;
case 3:
me->SetDisplayId(MODEL_GHOST);
Talk(TEXT_BK_GHOST_RES);
Talk(SAY_BK_PHASE_3);
events.Reset();
events.ScheduleEvent(EVENT_SPELL_DEATH_BITE, 2s);
@@ -251,8 +251,8 @@ public:
case EVENT_ANNOUNCER_SAY_ZOMBIE:
if( pInstance && !summons.empty() )
if( Creature* ghoul = pInstance->instance->GetCreature(*summons.begin()) )
ghoul->Yell("[Zombie] .... . Brains ....", LANG_UNIVERSAL);
if (urand(0, 1))
ghoul->Yell("[Zombie] .... . Brains ....", LANG_UNIVERSAL); /// @todo: Multiple variations + not always happening, from video sources, needs sniff to transition from DB.
break;
case EVENT_SPELL_PLAGUE_STRIKE:
if( me->GetVictim() )
@@ -307,17 +307,14 @@ public:
{
if( victim->GetTypeId() == TYPEID_PLAYER )
{
if( urand(0, 1) )
Talk(TEXT_BK_SLAIN_1);
else
Talk(TEXT_BK_SLAIN_2);
Talk(SAY_BK_KILL_PLAYER);
}
}
void JustDied(Unit* /*killer*/) override
{
me->CastSpell((Unit*)nullptr, SPELL_BK_KILL_CREDIT, true);
Talk(TEXT_BK_DEATH);
Talk(SAY_BK_DEATH);
if( pInstance )
pInstance->SetData(BOSS_BLACK_KNIGHT, DONE);
if( me->ToTempSummon() )

View File

@@ -90,6 +90,11 @@ enum ChampionSpells
SPELL_ROLLING_THROW = 67546, // not implemented yet!
};
enum Texts
{
SAY_TRAMPLED = 0,
};
#define SPELL_FIREBALL DUNGEON_MODE(SPELL_FIREBALL_N, SPELL_FIREBALL_H)
#define SPELL_BLAST_WAVE DUNGEON_MODE(SPELL_BLAST_WAVE_N, SPELL_BLAST_WAVE_H)
#define SPELL_POLYMORPH DUNGEON_MODE(SPELL_POLYMORPH_N, SPELL_POLYMORPH_H)
@@ -647,16 +652,8 @@ public:
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
switch( spell->Id )
{
case SPELL_TRAMPLE_STUN:
{
char buffer[50];
snprintf(buffer, sizeof(buffer), "%s is trampled!", me->GetName().c_str());
me->TextEmote(buffer);
}
break;
}
if (spell->Id == SPELL_TRAMPLE_STUN)
Talk(SAY_TRAMPLED, me);
}
void UpdateAI(uint32 diff) override

View File

@@ -25,6 +25,17 @@
const Position SpawnPosition = {746.67f, 684.08f, 412.5f, 4.65f};
#define CLEANUP_CHECK_INTERVAL 5000
/**
* @todo: Missing dialog/RP (already populated in DB) && spawns (can use ToC25 locations?) for:
*
* Garrosh Hellscream 34995
* King Varian Wrynn 34990
* Lady Jaina Proudmoore 34992 (missing in DB)
* Thrall 34994
*
* And possibly NPC_TIRION 33628 is wrong (should be 34996, from ToC25, needs a sniff to confirm, check .h)
*/
class Group;
class instance_trial_of_the_champion : public InstanceMapScript
@@ -523,9 +534,9 @@ public:
{
Counter = urand(0, 1);
if( Counter )
announcer->AI()->Talk(TEXT_INTRODUCE_EADRIC);
announcer->AI()->Talk(SAY_EADRIC_INTRO_ANNOUNCER);
else
announcer->AI()->Talk(TEXT_INTRODUCE_PALETRESS);
announcer->AI()->Talk(SAY_JAEREN_PALETRESS_INTRO);
}
HandleGameObject(GO_EnterGateGUID, false);
events.RescheduleEvent(EVENT_START_ARGENT_CHALLENGE_INTRO, 0ms);
@@ -702,27 +713,27 @@ public:
case 0:
CHAMPION_TO_SUMMON = NPC_MOKRA;
MINION_TO_SUMMON = NPC_ORGRIMMAR_MINION;
TEXT_ID = TEXT_MOKRA_SKILLCRUSHER;
TEXT_ID = SAY_GRAND_CHAMPIONS_INTRO_SKULLCRUSHER;
break;
case 1:
CHAMPION_TO_SUMMON = NPC_ERESSEA;
MINION_TO_SUMMON = NPC_SILVERMOON_MINION;
TEXT_ID = TEXT_ERESSEA_DAWNSINGER;
TEXT_ID = SAY_GRAND_CHAMPIONS_INTRO_DAWNSINGER;
break;
case 2:
CHAMPION_TO_SUMMON = NPC_RUNOK;
MINION_TO_SUMMON = NPC_THUNDER_BLUFF_MINION;
TEXT_ID = TEXT_RUNOK_WILDMANE;
TEXT_ID = SAY_GRAND_CHAMPIONS_INTRO_WILDMANE;
break;
case 3:
CHAMPION_TO_SUMMON = NPC_ZULTORE;
MINION_TO_SUMMON = NPC_SENJIN_MINION;
TEXT_ID = TEXT_ZUL_TORE;
TEXT_ID = SAY_GRAND_CHAMPIONS_INTRO_ZULTORE;
break;
case 4:
CHAMPION_TO_SUMMON = NPC_VISCERI;
MINION_TO_SUMMON = NPC_UNDERCITY_MINION;
TEXT_ID = TEXT_DEATHSTALKER_VESCERI;
TEXT_ID = SAY_GRAND_CHAMPIONS_INTRO_DEATHSTALKER;
break;
default:
return;
@@ -767,10 +778,7 @@ public:
if (!shortver)
if( Creature* announcer = instance->GetCreature(NPC_AnnouncerGUID) )
{
if( TeamIdInInstance == TEAM_HORDE )
TEXT_ID -= 10;
announcer->AI()->Talk(TEXT_ID);
announcer->AI()->Talk(TEXT_ID + 1);
announcer->AI()->Talk(TEXT_ID); /// @todo: Missing Argent Raid Spectator cheers.
}
}
@@ -1007,16 +1015,6 @@ public:
HandleGameObject(GO_MainGateGUID, true, gate);
HandleGameObject(GO_EnterGateGUID, false, gate);
}
if( Counter )
{
announcer->AI()->Talk(TEXT_CHEER_EADRIC_1);
announcer->AI()->Talk(TEXT_CHEER_EADRIC_2);
}
else
{
announcer->AI()->Talk(TEXT_CHEER_PALETRESS_1);
announcer->AI()->Talk(TEXT_CHEER_PALETRESS_2);
}
}
for( int8 i = 0; i < 3; ++i )
@@ -1060,7 +1058,7 @@ public:
case EVENT_ARGENT_CHALLENGE_SAY_1:
{
if( Creature* ac = instance->GetCreature(NPC_ArgentChampionGUID) )
ac->AI()->Talk(Counter ? TEXT_EADRIC_SAY_1 : TEXT_PALETRESS_SAY_1);
ac->AI()->Talk(Counter ? SAY_EADRIC_INTRO : SAY_PALETRESS_INTRO_1);
if( !Counter )
events.ScheduleEvent(EVENT_ARGENT_CHALLENGE_SAY_2, 6s);
}
@@ -1068,7 +1066,7 @@ public:
case EVENT_ARGENT_CHALLENGE_SAY_2:
{
if( Creature* ac = instance->GetCreature(NPC_ArgentChampionGUID) )
ac->AI()->Talk(TEXT_PALETRESS_SAY_2);
ac->AI()->Talk(SAY_PALETRESS_INTRO_2);
}
break;
case EVENT_ARGENT_SOLDIER_GROUP_ATTACK:
@@ -1163,7 +1161,7 @@ public:
}
announcer->SetFacingToObject(bk_vehicle);
announcer->AI()->Talk(TEXT_BK_RAFTERS);
announcer->AI()->Talk(SAY_KNIGHT_INTRO);
}
}
break;
@@ -1174,7 +1172,7 @@ public:
Position exitPos = { 751.003357f, 638.145508f, 411.570129f, M_PI };
bk->ExitVehicle(/*&exitPos*/);
bk->GetMotionMaster()->MoveJump(exitPos, 2.0f, 2.0f);
bk->AI()->Talk(TEXT_BK_SPOILED);
bk->AI()->Talk(SAY_BK_INTRO_1);
}
events.ScheduleEvent(EVENT_BLACK_KNIGHT_CAST_ANNOUNCER, 2s);
}
@@ -1212,7 +1210,7 @@ public:
{
bk->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
bk->GetMotionMaster()->MovePoint(0, 746.81f, 623.15f, 411.42f);
bk->AI()->Talk(TEXT_BK_LICH);
bk->AI()->Talk(SAY_BK_INTRO_2);
}
if( Creature* announcer = instance->GetCreature(NPC_AnnouncerGUID) )
if (announcer->IsAlive())
@@ -1225,7 +1223,7 @@ public:
if( Creature* bk = instance->GetCreature(NPC_BlackKnightGUID) )
{
bk->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
bk->AI()->Talk(TEXT_BK_TASK);
bk->AI()->Talk(SAY_BK_INTRO_3);
}
events.ScheduleEvent(EVENT_BLACK_KNIGHT_ATTACK, 5s);
}

View File

@@ -21,10 +21,23 @@
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#define GOSSIP_START_EVENT1a "I am ready."
#define GOSSIP_START_EVENT1b "I am ready. However I'd like to skip the pageantry."
#define GOSSIP_START_EVENT2 "I'm ready for the next challenge."
#define GOSSIP_START_EVENT3 "I'm ready."
enum Texts
{
NPC_TEXT_NOT_MOUNTED_H = 15043, // Horde text
NPC_TEXT_NOT_MOUNTED_A = 14757, // Alliance text
NPC_TEXT_CHALLENGE_1 = 14688,
NPC_TEXT_CHALLENGE_2 = 14737,
NPC_TEXT_CHALLENGE_3 = 14738,
GOSSIP_MENU_STAGE = 10614,
GOSSIP_START_EVENT_1A = 0,
GOSSIP_START_EVENT_1B = 3, // Skip roleplay
GOSSIP_START_EVENT_2 = 1,
GOSSIP_START_EVENT_3 = 2,
};
class npc_announcer_toc5 : public CreatureScript
{
@@ -47,29 +60,28 @@ public:
if (!player->GetVehicle())
{
if (pInstance->GetData(DATA_TEAMID_IN_INSTANCE) == TEAM_HORDE)
gossipTextId = 15043; //Horde text
gossipTextId = NPC_TEXT_NOT_MOUNTED_H;
else
gossipTextId = 14757; //Alliance text
gossipTextId = NPC_TEXT_NOT_MOUNTED_A;
}
else
{
gossipTextId = 14688;
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1a, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1338);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1b, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1341);
gossipTextId = NPC_TEXT_CHALLENGE_1;
AddGossipItemFor(player, GOSSIP_MENU_STAGE, GOSSIP_START_EVENT_1A, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, GOSSIP_MENU_STAGE, GOSSIP_START_EVENT_1B, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
}
break;
case INSTANCE_PROGRESS_CHAMPIONS_DEAD:
gossipTextId = 14737;
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1339);
gossipTextId = NPC_TEXT_CHALLENGE_2;
AddGossipItemFor(player, GOSSIP_MENU_STAGE, GOSSIP_START_EVENT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
break;
case INSTANCE_PROGRESS_ARGENT_CHALLENGE_DIED:
gossipTextId = 14738;
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_START_EVENT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1340);
gossipTextId = NPC_TEXT_CHALLENGE_3;
AddGossipItemFor(player, GOSSIP_MENU_STAGE, GOSSIP_START_EVENT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
break;
default:
return true;
}
SendGossipMenuFor(player, gossipTextId, creature->GetGUID());
return true;
}
@@ -83,9 +95,9 @@ public:
if(!pInstance)
return true;
if(uiAction == GOSSIP_ACTION_INFO_DEF + 1338 || uiAction == GOSSIP_ACTION_INFO_DEF + 1341 || uiAction == GOSSIP_ACTION_INFO_DEF + 1339 || uiAction == GOSSIP_ACTION_INFO_DEF + 1340)
if(uiAction == GOSSIP_ACTION_INFO_DEF + 1 || uiAction == GOSSIP_ACTION_INFO_DEF + 2 || uiAction == GOSSIP_ACTION_INFO_DEF + 3 || uiAction == GOSSIP_ACTION_INFO_DEF + 4)
{
pInstance->SetData(DATA_ANNOUNCER_GOSSIP_SELECT, (uiAction == GOSSIP_ACTION_INFO_DEF + 1341 ? 1 : 0));
pInstance->SetData(DATA_ANNOUNCER_GOSSIP_SELECT, (uiAction == GOSSIP_ACTION_INFO_DEF + 2 ? 1 : 0));
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
}

View File

@@ -141,11 +141,28 @@ enum eNpcs
NPC_BLACK_KNIGHT = 35451,
NPC_JAEREN = 35004,
NPC_ARELAS = 35005,
NPC_JAEREN = 35004, // Horde
NPC_ARELAS = 35005, // Alliance
NPC_RISEN_JAEREN = 35545,
NPC_RISEN_ARELAS = 35564,
NPC_TIRION = 33628,
NPC_TIRION = 33628, // Possibly wrong npc here, 34996 had already populated creature_text (from ToC25) that matches. Needs a sniff to confirm.
/// @todo: Argent Raid Spectator - FX - Missing spawns for Toc5 (map 650), ToC25 probably matches positions, needs a sniff to confirm.
// Horde
NPC_SPECTATOR_HORDE = 34883,
NPC_SPECTATOR_BELF = 34904,
NPC_SPECTATOR_TAUREN = 34903,
NPC_SPECTATOR_TROLL = 34902,
NPC_SPECTATOR_ORC = 34901,
NPC_SPECTATOR_UNDEAD = 34905,
// Alliance
NPC_SPECTATOR_ALLIANCE = 34887,
NPC_SPECTATOR_DWARF = 34906,
NPC_SPECTATOR_GNOME = 34910,
NPC_SPECTATOR_HUMAN = 34900,
NPC_SPECTATOR_NELF = 34909,
NPC_SPECTATOR_DRAENEI = 34908,
};
enum eGameObjects
@@ -175,69 +192,57 @@ enum eVehicles
enum eTexts
{
TEXT_LANA_STOUTHAMMER = 1,
TEXT_CHEER_LANA_STOUTHAMMER = 2,
TEXT_COLOSOS = 3,
TEXT_CHEER_COLOSOS = 4,
TEXT_EVENSONG = 5,
TEXT_CHEER_EVENSONG = 6,
TEXT_MARSHAL_JACOB_ALERIUS = 7,
TEXT_CHEER_MARSHAL_JACOB_ALERIUS = 8,
TEXT_AMBROSE_BOLTSPARK = 9,
TEXT_CHEER_AMBROSE_BOLTSPARK = 10,
// Spectators
SAY_SPECTATOR_CHEER = 0,
TEXT_DEATHSTALKER_VESCERI = 11,
TEXT_CHEER_DEATHSTALKER_VESCERI = 12,
TEXT_RUNOK_WILDMANE = 13,
TEXT_CHEER_RUNOK_WILDMANE = 14,
TEXT_ZUL_TORE = 15,
TEXT_CHEER_ZUL_TORE = 16,
TEXT_MOKRA_SKILLCRUSHER = 17,
TEXT_CHEER_MOKRA_SKILLCRUSHER = 18,
TEXT_ERESSEA_DAWNSINGER = 19,
TEXT_CHEER_ERESSEA_DAWNSINGER = 20,
// Announcers: Alliance Announcer - Arelas Brightstar && Horde Announcer - Jaeren Sunsworn
SAY_EADRIC_INTRO_ANNOUNCER = 0,
SAY_JAEREN_PALETRESS_INTRO = 1,
SAY_GRAND_CHAMPIONS_INTRO_1 = 2,
SAY_GRAND_CHAMPIONS_INTRO_DAWNSINGER = 3, // Boltspark
SAY_GRAND_CHAMPIONS_INTRO_ZULTORE = 4, // Jaelyne
SAY_GRAND_CHAMPIONS_INTRO_SKULLCRUSHER = 5, // Jacob
SAY_GRAND_CHAMPIONS_INTRO_DEATHSTALKER = 6, // Lana
SAY_GRAND_CHAMPIONS_INTRO_WILDMANE = 7, // Colosos
SAY_KNIGHT_INTRO = 8,
// Eadric
SAY_EADRIC_INTRO = 0,
SAY_EADRIC_AGGRO = 1,
SAY_EADRIC_EMOTE_RADIANCE = 2,
SAY_EADRIC_EMOTE_HAMMER_RIGHTEOUS = 3,
SAY_EADRIC_HAMMER_RIGHTEOUS = 4,
SAY_EADRIC_KILL_PLAYER = 5, // "You! You need more practice." && "Nay, nay, and I say yet again nay! Not good enough."
SAY_EADRIC_DEFEATED = 6,
// Confessor Paletress
SAY_PALETRESS_INTRO_1 = 0,
SAY_PALETRESS_INTRO_2 = 1,
SAY_PALETRESS_AGGRO = 2,
SAY_PALETRESS_MEMORY_SUMMON = 3,
SAY_PALETRESS_MEMORY_DEATH = 4,
SAY_PALETRESS_KILL_PLAYER = 5, // "Take your rest. "&& "Be at ease."
SAY_PALETRESS_DEFEATED = 6,
// Tirion
TEXT_WELCOME = 21,
TEXT_WELCOME_2 = 22,
TEXT_BEGIN = 23,
TEXT_GRATZ_SLAIN_CHAMPIONS = 24,
TEXT_INTRODUCE_EADRIC = 25,
TEXT_INTRODUCE_PALETRESS = 26,
TEXT_CHEER_EADRIC_1 = 27,
TEXT_CHEER_EADRIC_2 = 28,
TEXT_EADRIC_SAY_1 = 39,
TEXT_CHEER_PALETRESS_1 = 29,
TEXT_CHEER_PALETRESS_2 = 30,
TEXT_PALETRESS_SAY_1 = 37,
TEXT_PALETRESS_SAY_2 = 38,
TEXT_YOU_MAY_BEGIN = 41,
// Tirion - The Black Knight Interactions
TEXT_BK_INTRO = 31,
TEXT_BK_RAFTERS = 32,
TEXT_BK_SPOILED = 33,
TEXT_BK_MEANING = 34,
TEXT_BK_LICH = 35,
TEXT_BK_TASK = 36,
TEXT_EADRIC_AGGRO = 42,
TEXT_EADRIC_HAMMER = 43,
TEXT_EADRIC_SLAIN_1 = 44,
TEXT_EADRIC_SLAIN_2 = 45,
TEXT_EADRIC_DEATH = 46,
TEXT_PALETRESS_AGGRO = 47,
TEXT_PALETRESS_MEMORY_SUMMON = 48,
TEXT_PALETRESS_MEMORY_DEFEATED = 51,
TEXT_PALETRESS_SLAIN_1 = 49,
TEXT_PALETRESS_SLAIN_2 = 50,
TEXT_PALETRESS_DEATH = 52,
TEXT_BK_AGGRO = 53,
TEXT_BK_SLAIN_1 = 57,
TEXT_BK_SLAIN_2 = 58,
TEXT_BK_SKELETON_RES = 54,
TEXT_BK_GHOST_RES = 55,
TEXT_BK_DEATH = 56,
// The Black Knight
SAY_BK_INTRO_1 = 0,
SAY_BK_INTRO_2 = 1,
SAY_BK_INTRO_3 = 2,
SAY_BK_AGGRO = 3,
SAY_BK_PHASE_2 = 4, // Skeleton
SAY_BK_PHASE_3 = 5, // Ghost
SAY_BK_KILL_PLAYER = 6, // "Pathetic." && "A waste of flesh."
SAY_BK_DEATH = 7,
};
template <class AI, class T>

View File

@@ -277,12 +277,6 @@ public:
_experimentState = (data ? 1 : 0);
}
void AttackStart(Unit* who) override
{
if (instance->CheckRequiredBosses(DATA_PROFESSOR_PUTRICIDE))
BossAI::AttackStart(who);
}
bool CanAIAttack(Unit const* target) const override
{
return me->IsVisible() && target->GetPositionZ() > 388.0f && target->GetPositionZ() < 410.0f && target->GetPositionY() > 3157.1f && target->GetExactDist2dSq(4356.0f, 3211.0f) < 80.0f * 80.0f;

View File

@@ -1007,13 +1007,6 @@ public:
me->SendMovementFlagUpdate();
}
void AttackStart(Unit* victim) override
{
if (me->HasReactState(REACT_PASSIVE) || me->IsImmuneToAll())
return;
BossAI::AttackStart(victim);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
@@ -1039,13 +1032,6 @@ public:
void JustEngagedWith(Unit* /*attacker*/) override
{
if (me->HasReactState(REACT_PASSIVE) || me->IsImmuneToAll())
{
me->CombatStop(false);
me->SetImmuneToAll(true);
me->SetReactState(REACT_PASSIVE);
return;
}
_JustEngagedWith();
me->LowerPlayerDamageReq(me->GetMaxHealth());
if (Creature* crok = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_CROK_SCOURGEBANE)))

View File

@@ -1457,7 +1457,7 @@ public:
bool CheckRequiredBosses(uint32 bossId, Player const* player) const override
{
if (player->GetSession() && player->GetSession()->GetSecurity() >= SEC_MODERATOR)
if (player && player->GetSession() && player->GetSession()->GetSecurity() >= SEC_MODERATOR)
{
return true;
}

View File

@@ -56,16 +56,19 @@ struct boss_talon_king_ikiss : public BossAI
_Reset();
_spoken = false;
ScheduleHealthCheckEvent(80, [&] {
TeleportAndCastExplosion();
});
ScheduleHealthCheckEvent({ 80, 50, 25 }, [&] {
me->InterruptNonMeleeSpells(false);
DoCastAOE(SPELL_BLINK);
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
Talk(EMOTE_ARCANE_EXP);
ScheduleHealthCheckEvent(50, [&] {
TeleportAndCastExplosion();
});
ScheduleHealthCheckEvent(25, [&] {
TeleportAndCastExplosion();
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/)
{
me->GetThreatMgr().ResetAllThreat();
});
});
ScheduleHealthCheckEvent(20, [&] {
@@ -79,22 +82,6 @@ struct boss_talon_king_ikiss : public BossAI
return _spoken;
}
void TeleportAndCastExplosion()
{
me->InterruptNonMeleeSpells(false);
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
DoCastAOE(SPELL_BLINK);
Talk(EMOTE_ARCANE_EXP);
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
}).Schedule(6500ms, [this](TaskContext /*context*/)
{
me->GetThreatMgr().ResetAllThreat();
});
}
void MoveInLineOfSight(Unit* who) override
{
if (!_spoken && who->IsPlayer())

View File

@@ -17,7 +17,6 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
#include "shadow_labyrinth.h"
enum eEnums
@@ -35,7 +34,12 @@ enum eEnums
EVENT_SPELL_CORROSIVE = 1,
EVENT_SPELL_FEAR = 2,
EVENT_SPELL_ENRAGE = 3
EVENT_SPELL_ENRAGE = 3,
PATH_ID_START = 1873100,
PATH_ID_PATHING = 1873101,
SOUND_INTRO = 9349
};
class boss_ambassador_hellmaw : public CreatureScript
@@ -48,9 +52,9 @@ public:
return GetShadowLabyrinthAI<boss_ambassador_hellmawAI>(creature);
}
struct boss_ambassador_hellmawAI : public npc_escortAI
struct boss_ambassador_hellmawAI : public ScriptedAI
{
boss_ambassador_hellmawAI(Creature* creature) : npc_escortAI(creature)
boss_ambassador_hellmawAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
@@ -59,64 +63,102 @@ public:
EventMap events;
bool isBanished;
void DoAction(int32 param) override
void InitializeAI() override
{
if (param != 1)
return;
Reset();
me->RemoveAurasDueToSpell(SPELL_BANISH);
Talk(SAY_INTRO);
Start(true, false, ObjectGuid::Empty, nullptr, false, true);
isBanished = false;
if (instance && instance->GetData(TYPE_RITUALISTS) != DONE)
{
isBanished = true;
me->SetImmuneToAll(true);
me->m_Events.AddEventAtOffset([this]()
{
DoCastSelf(SPELL_BANISH, true);
}, 500ms);
}
else
{
me->GetMotionMaster()->MovePath(PATH_ID_START, false);
}
}
void Reset() override
{
events.Reset();
isBanished = false;
me->SetImmuneToAll(false);
if (instance)
{
instance->SetData(TYPE_HELLMAW, NOT_STARTED);
if (instance->GetData(TYPE_OVERSEER) != DONE)
{
isBanished = true;
me->CastSpell(me, SPELL_BANISH, true);
}
else
Start(true, false, ObjectGuid::Empty, nullptr, false, true);
}
}
void DoAction(int32 param) override
{
if (param != 1)
{
return;
}
me->RemoveAurasDueToSpell(SPELL_BANISH);
Talk(SAY_INTRO);
DoPlaySoundToSet(me, SOUND_INTRO);
isBanished = false;
me->SetImmuneToAll(false);
me->GetMotionMaster()->MovePath(PATH_ID_START, false);
}
void JustEngagedWith(Unit*) override
{
if (isBanished)
{
return;
}
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_CORROSIVE, urand(5000, 10000));
events.ScheduleEvent(EVENT_SPELL_FEAR, urand(15000, 20000));
if (IsHeroic())
{
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 180000);
}
if (instance)
{
instance->SetData(TYPE_HELLMAW, IN_PROGRESS);
}
}
void MoveInLineOfSight(Unit* who) override
{
if (isBanished)
{
return;
npc_escortAI::MoveInLineOfSight(who);
}
ScriptedAI::MoveInLineOfSight(who);
}
void AttackStart(Unit* who) override
{
if (isBanished)
{
return;
npc_escortAI::AttackStart(who);
}
ScriptedAI::AttackStart(who);
}
void WaypointReached(uint32 /*waypointId*/) override
void PathEndReached(uint32 pathId) override
{
if (pathId == PATH_ID_START)
{
me->m_Events.AddEventAtOffset([this]()
{
me->GetMotionMaster()->MovePath(PATH_ID_PATHING, true);
}, 20s);
}
}
void KilledUnit(Unit* victim) override
@@ -132,19 +174,63 @@ public:
instance->SetData(TYPE_HELLMAW, DONE);
}
void UpdateAI(uint32 diff) override
bool CanAIAttack(Unit const* /*unit*/) const override
{
npc_escortAI::UpdateAI(diff);
return !isBanished;
}
if (!UpdateVictim())
return;
if (isBanished)
void DoMeleeAttackIfReady(bool ignoreCasting)
{
if (!ignoreCasting && me->HasUnitState(UNIT_STATE_CASTING))
{
EnterEvadeMode();
return;
}
Unit* victim = me->GetVictim();
if (!victim || !victim->IsInWorld())
{
return;
}
if (!me->IsWithinMeleeRange(victim))
{
return;
}
//Make sure our attack is ready and we aren't currently casting before checking distance
if (me->isAttackReady())
{
// xinef: prevent base and off attack in same time, delay attack at 0.2 sec
if (me->haveOffhandWeapon())
{
if (me->getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
{
me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
}
}
me->AttackerStateUpdate(victim, BASE_ATTACK, false, ignoreCasting);
me->resetAttackTimer();
}
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
{
// xinef: delay main hand attack if both will hit at the same time (players code)
if (me->getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
{
me->setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
}
me->AttackerStateUpdate(victim, OFF_ATTACK, false, ignoreCasting);
me->resetAttackTimer(OFF_ATTACK);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
@@ -161,7 +247,7 @@ public:
break;
}
DoMeleeAttackIfReady();
DoMeleeAttackIfReady(me->FindCurrentSpellBySpellId(SPELL_CORROSIVE_ACID) != nullptr);
}
};
};

View File

@@ -39,13 +39,13 @@ public:
ObjectGuid m_uiRefectoryDoorGUID;
ObjectGuid m_uiScreamingHallDoorGUID;
uint32 m_uiFelOverseerCount;
uint32 _ritualistsAliveCount;
void Initialize() override
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
m_uiFelOverseerCount = 0;
_ritualistsAliveCount = 0;
}
bool IsEncounterInProgress() const override
@@ -76,11 +76,13 @@ public:
void OnCreatureCreate(Creature* creature) override
{
InstanceScript::OnCreatureCreate(creature);
switch (creature->GetEntry())
{
case NPC_FEL_OVERSEER:
case NPC_CABAL_RITUALIST:
if (creature->IsAlive())
++m_uiFelOverseerCount;
++_ritualistsAliveCount;
break;
case NPC_HELLMAW:
m_uiHellmawGUID = creature->GetGUID();
@@ -88,19 +90,26 @@ public:
}
}
void OnUnitDeath(Unit* unit) override
{
InstanceScript::OnUnitDeath(unit);
if (unit->GetEntry() == NPC_CABAL_RITUALIST)
if (!--_ritualistsAliveCount)
{
m_auiEncounter[TYPE_RITUALISTS] = DONE;
SaveToDB();
if (Creature* cr = instance->GetCreature(m_uiHellmawGUID))
{
cr->AI()->DoAction(1);
}
}
}
void SetData(uint32 type, uint32 uiData) override
{
switch (type)
{
case TYPE_OVERSEER:
if (!--m_uiFelOverseerCount)
{
m_auiEncounter[type] = DONE;
if (Creature* cr = instance->GetCreature(m_uiHellmawGUID))
cr->AI()->DoAction(1);
}
break;
case DATA_BLACKHEARTTHEINCITEREVENT:
if (uiData == DONE)
DoUseDoorOrButton(m_uiRefectoryDoorGUID);
@@ -125,7 +134,7 @@ public:
uint32 GetData(uint32 type) const override
{
if (type == TYPE_OVERSEER)
if (type == TYPE_RITUALISTS)
return m_auiEncounter[0];
return 0;
}

View File

@@ -27,7 +27,7 @@
enum slData
{
TYPE_OVERSEER = 0,
TYPE_RITUALISTS = 0,
TYPE_HELLMAW = 1,
DATA_BLACKHEARTTHEINCITEREVENT = 2,
DATA_GRANDMASTERVORPILEVENT = 3,
@@ -37,7 +37,7 @@ enum slData
enum slNPCandGO
{
NPC_FEL_OVERSEER = 18796,
NPC_CABAL_RITUALIST = 18794,
NPC_HELLMAW = 18731,
REFECTORY_DOOR = 183296, //door opened when blackheart the inciter dies

View File

@@ -29,11 +29,7 @@ enum HydromancerThespia
SPELL_LIGHTNING_CLOUD = 25033,
SPELL_LUNG_BURST = 31481,
SPELL_ENVELOPING_WINDS = 31718,
EVENT_SPELL_LIGHTNING = 1,
EVENT_SPELL_LUNG = 2,
EVENT_SPELL_ENVELOPING = 3
SPELL_ENVELOPING_WINDS = 31718
};
struct boss_hydromancer_thespia : public BossAI
@@ -44,47 +40,39 @@ struct boss_hydromancer_thespia : public BossAI
{
_JustDied();
Talk(SAY_DEAD);
instance->DoForAllMinions(DATA_HYDROMANCER_THESPIA, [&](Creature* creature) {
creature->DespawnOrUnsummon();
});
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
events.ScheduleEvent(EVENT_SPELL_LIGHTNING, 9800);
events.ScheduleEvent(EVENT_SPELL_LUNG, 13300);
events.ScheduleEvent(EVENT_SPELL_ENVELOPING, 14500);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
scheduler.Schedule(9800ms, [this](TaskContext context)
{
case EVENT_SPELL_LIGHTNING:
Talk(SAY_SPELL);
DoCastRandomTarget(SPELL_LIGHTNING_CLOUD);
events.RepeatEvent(urand(12100, 14500));
break;
case EVENT_SPELL_LUNG:
context.Repeat(12100ms, 14500ms);
}).Schedule(13300ms, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_LUNG_BURST);
events.RepeatEvent(urand(21800, 25400));
break;
case EVENT_SPELL_ENVELOPING:
context.Repeat(21800ms, 25400ms);
}).Schedule(14500ms, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_ENVELOPING_WINDS);
events.RepeatEvent(urand(30000, 40000));
break;
}
DoMeleeAttackIfReady();
context.Repeat(30s, 40s);
});
}
};

View File

@@ -33,20 +33,22 @@ enum MekgineerSteamrigger
SPELL_REPAIR_N = 31532,
SPELL_REPAIR_H = 37936,
NPC_STREAMRIGGER_MECHANIC = 17951,
SPELL_SUMMON_MECHANICS_1 = 31528,
SPELL_SUMMON_MECHANICS_2 = 31529,
SPELL_SUMMON_MECHANICS_3 = 31530,
EVENT_CHECK_HP25 = 1,
EVENT_CHECK_HP50 = 2,
EVENT_CHECK_HP75 = 3,
EVENT_SPELL_SHRINK = 4,
EVENT_SPELL_SAW = 5,
EVENT_SPELL_NET = 6,
EVENT_ENRAGE = 7
NPC_STREAMRIGGER_MECHANIC = 17951
};
struct boss_mekgineer_steamrigger : public BossAI
{
boss_mekgineer_steamrigger(Creature* creature) : BossAI(creature, DATA_MEKGINEER_STEAMRIGGER) { }
boss_mekgineer_steamrigger(Creature* creature) : BossAI(creature, DATA_MEKGINEER_STEAMRIGGER)
{
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void JustDied(Unit* /*killer*/) override
{
@@ -57,131 +59,73 @@ struct boss_mekgineer_steamrigger : public BossAI
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
events.ScheduleEvent(EVENT_SPELL_SHRINK, 26550);
events.ScheduleEvent(EVENT_SPELL_SAW, 6050, 17650);
events.ScheduleEvent(EVENT_SPELL_NET, 14400);
events.ScheduleEvent(EVENT_ENRAGE, 300000);
events.ScheduleEvent(EVENT_CHECK_HP75, 5000);
events.ScheduleEvent(EVENT_CHECK_HP50, 5000);
events.ScheduleEvent(EVENT_CHECK_HP25, 5000);
}
void SummonMechanics()
{
Talk(SAY_MECHANICS);
me->SummonCreature(NPC_STREAMRIGGER_MECHANIC, me->GetPositionX() + 15.0f, me->GetPositionY() + 15.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_STREAMRIGGER_MECHANIC, me->GetPositionX() - 15.0f, me->GetPositionY() + 15.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
me->SummonCreature(NPC_STREAMRIGGER_MECHANIC, me->GetPositionX() - 15.0f, me->GetPositionY() - 15.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
if (urand(0, 1))
me->SummonCreature(NPC_STREAMRIGGER_MECHANIC, me->GetPositionX() + 15.0f, me->GetPositionY() - 15.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
}
void JustSummoned(Creature* cr) override
{
cr->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (uint32 eventId = events.ExecuteEvent())
scheduler.Schedule(26550ms, [this](TaskContext context)
{
DoCastVictim(SPELL_SUPER_SHRINK_RAY);
context.Repeat(35100ms, 54100ms);
}).Schedule(6050ms, 17650ms, [this](TaskContext context)
{
if (DoCastRandomTarget(SPELL_SAW_BLADE, 1) != SPELL_CAST_OK)
{
DoCastVictim(SPELL_SAW_BLADE);
}
context.Repeat(6050ms, 17650ms);
}).Schedule(14400ms, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_ELECTRIFIED_NET);
context.Repeat(21800ms, 34200ms);
}).Schedule(5min, [this](TaskContext /*context*/)
{
case EVENT_SPELL_SHRINK:
me->CastSpell(me->GetVictim(), SPELL_SUPER_SHRINK_RAY, false);
events.Repeat(35100ms, 54100ms);
break;
case EVENT_SPELL_SAW:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
me->CastSpell(target, SPELL_SAW_BLADE, false);
else
me->CastSpell(me->GetVictim(), SPELL_SAW_BLADE, false);
events.Repeat(6050ms, 17650ms);
break;
case EVENT_SPELL_NET:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_ELECTRIFIED_NET, false);
events.Repeat(21800ms, 34200ms);
break;
case EVENT_ENRAGE:
DoCastSelf(SPELL_ENRAGE, true);
break;
case EVENT_CHECK_HP25:
case EVENT_CHECK_HP50:
case EVENT_CHECK_HP75:
if (me->HealthBelowPct(eventId * 25))
{
SummonMechanics();
return;
}
events.RepeatEvent(2000);
break;
}
DoMeleeAttackIfReady();
}
};
struct npc_steamrigger_mechanic : public ScriptedAI
{
npc_steamrigger_mechanic(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
_scheduler.CancelAll();
}
void JustEngagedWith(Unit* victim) override
{
ScriptedAI::JustEngagedWith(victim);
_scheduler.Schedule(2s, [this](TaskContext context)
{
if (InstanceScript* instance = me->GetInstanceScript())
{
if (Creature* boss = instance->GetCreature(DATA_MEKGINEER_STEAMRIGGER))
{
if (me->IsWithinDistInMap(boss, 13.0f))
{
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
me->CastSpell(me, DUNGEON_MODE(SPELL_REPAIR_N, SPELL_REPAIR_H), false);
}
}
}
}
context.Repeat();
});
if (!IsHeroic())
{
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&] {
Talk(SAY_MECHANICS);
for (auto const& spell : { SPELL_SUMMON_MECHANICS_1, SPELL_SUMMON_MECHANICS_2, SPELL_SUMMON_MECHANICS_3 })
{
DoCastAOE(spell, true);
}
});
}
else
{
scheduler.Schedule(15600ms, [this](TaskContext context)
{
if (roll_chance_i(15))
{
Talk(SAY_MECHANICS);
}
DoCastAOE(RAND(SPELL_SUMMON_MECHANICS_1, SPELL_SUMMON_MECHANICS_2, SPELL_SUMMON_MECHANICS_3), true);
context.Repeat(15600ms, 25400ms);
});
}
}
void MoveInLineOfSight(Unit* /*who*/) override {}
void UpdateAI(uint32 diff) override
void JustSummoned(Creature* creature) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff,
std::bind(&BossAI::DoMeleeAttackIfReady, this));
if (creature->GetEntry() == NPC_STREAMRIGGER_MECHANIC)
{
creature->GetMotionMaster()->MoveFollow(me, 5.0f, 0.0f);
}
}
private:
TaskScheduler _scheduler;
};
void AddSC_boss_mekgineer_steamrigger()
{
RegisterSteamvaultCreatureAI(boss_mekgineer_steamrigger);
RegisterSteamvaultCreatureAI(npc_steamrigger_mechanic);
}

View File

@@ -17,44 +17,110 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
#include "SpellScript.h"
#include "SpellAuras.h"
#include "steam_vault.h"
enum NagaDistiller
enum Texts
{
SAY_INTRO = 0,
SAY_REGEN = 1,
SAY_AGGRO = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
SAY_INTRO = 0,
SAY_REGEN = 1,
SAY_AGGRO = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
EMOTE_DISTILLER = 5
};
SPELL_SPELL_REFLECTION = 31534,
SPELL_IMPALE = 39061,
SPELL_HEAD_CRACK = 16172,
SPELL_WARLORDS_RAGE = 37081,
SPELL_WARLORDS_RAGE_NAGA = 31543,
SPELL_WARLORDS_RAGE_PROC = 36453,
enum Spells
{
SPELL_SPELL_REFLECTION = 31534,
SPELL_IMPALE = 39061,
SPELL_HEAD_CRACK = 16172,
SPELL_WARLORDS_RAGE = 37081,
SPELL_WARLORDS_RAGE_DISTILLER = 31543,
SPELL_WARLORDS_RAGE_PROC = 36453
};
NPC_NAGA_DISTILLER = 17954,
EVENT_SPELL_REFLECTION = 1,
EVENT_SPELL_IMPALE = 2,
EVENT_SPELL_HEAD_CRACK = 3,
EVENT_SPELL_RAGE = 4
enum Misc
{
POINT_DISTILLER = 1
};
struct boss_warlord_kalithresh : public BossAI
{
boss_warlord_kalithresh(Creature* creature) : BossAI(creature, DATA_WARLORD_KALITHRESH) { }
boss_warlord_kalithresh(Creature* creature) : BossAI(creature, DATA_WARLORD_KALITHRESH), _introDone(false) { }
void Reset() override
{
_Reset();
instance->DoForAllMinions(DATA_WARLORD_KALITHRESH, [&](Creature* minion) {
minion->SetReactState(REACT_PASSIVE);
minion->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
});
}
void MoveInLineOfSight(Unit* who) override
{
if (!_introDone && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 35.0f))
{
Talk(SAY_INTRO);
_introDone = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 20000, 36000);
events.ScheduleEvent(EVENT_SPELL_IMPALE, 7000, 14000);
events.ScheduleEvent(EVENT_SPELL_HEAD_CRACK, 15000);
events.ScheduleEvent(EVENT_SPELL_RAGE, 20000);
scheduler.Schedule(20s, 36s, [this](TaskContext context)
{
DoCastSelf(SPELL_SPELL_REFLECTION);
context.Repeat();
}).Schedule(7s, 14s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_IMPALE, 0, 10.0f);
context.Repeat(7500ms, 12500ms);
}).Schedule(15s, [this](TaskContext context)
{
DoCastVictim(SPELL_HEAD_CRACK);
context.Repeat(45s, 55s);
}).Schedule(20s, [this](TaskContext context)
{
Talk(SAY_REGEN);
Talk(EMOTE_DISTILLER);
if (Creature* distiller = me->FindNearestCreature(NPC_NAGA_DISTILLER, 8.0f))
{
distiller->AI()->DoCast(me, SPELL_WARLORDS_RAGE_DISTILLER, true);
distiller->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
}
else
{
if (Creature* distiller = me->FindNearestCreature(NPC_NAGA_DISTILLER, 100.0f))
{
me->GetMotionMaster()->MoveFollow(distiller, 8.0f, 0.0f);
scheduler.Schedule(1s, [this](TaskContext chaseContext)
{
if (Creature* distiller = me->FindNearestCreature(NPC_NAGA_DISTILLER, 8.0f))
{
distiller->AI()->DoCast(me, SPELL_WARLORDS_RAGE_DISTILLER, true);
distiller->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->ResumeChasingVictim();
}
else
{
chaseContext.Repeat();
}
});
}
}
context.Repeat(45s);
});
}
void KilledUnit(Unit* victim) override
@@ -69,85 +135,39 @@ struct boss_warlord_kalithresh : public BossAI
{
Talk(SAY_DEATH);
_JustDied();
instance->DoForAllMinions(DATA_WARLORD_KALITHRESH, [&](Creature* minion) {
minion->KillSelf();
});
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_SPELL_REFLECTION:
me->CastSpell(me, SPELL_SPELL_REFLECTION, false);
events.Repeat(20s, 36s);
break;
case EVENT_SPELL_IMPALE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true))
me->CastSpell(target, SPELL_IMPALE, false);
events.Repeat(7500ms, 12500ms);
break;
case EVENT_SPELL_HEAD_CRACK:
DoCastVictim(SPELL_HEAD_CRACK);
events.Repeat(45s, 55s);
break;
case EVENT_SPELL_RAGE:
if (Creature* distiller = me->FindNearestCreature(NPC_NAGA_DISTILLER, 100.0f))
{
Talk(SAY_REGEN);
//me->CastSpell(me, SPELL_WARLORDS_RAGE, false);
distiller->AI()->DoAction(1);
}
events.RepeatEvent(45000);
break;
}
DoMeleeAttackIfReady();
}
private:
bool _introDone;
};
struct npc_naga_distiller : public NullCreatureAI
// 31543 - Warlord's Rage
class spell_warlords_rage : public AuraScript
{
npc_naga_distiller(Creature* creature) : NullCreatureAI(creature) { }
PrepareAuraScript(spell_warlords_rage);
uint32 spellTimer;
void Reset() override
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
spellTimer = 0;
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
void DoAction(int32 param) override
{
if (param != 1)
return;
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->CastSpell(me, SPELL_WARLORDS_RAGE_NAGA, true);
spellTimer = 1;
}
void UpdateAI(uint32 diff) override
{
if (spellTimer)
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
{
spellTimer += diff;
if (spellTimer >= 12000)
if (GetTarget())
{
if (Creature* kali = me->FindNearestCreature(NPC_WARLORD_KALITHRESH, 100.0f))
kali->CastSpell(kali, SPELL_WARLORDS_RAGE_PROC, true);
me->KillSelf();
GetTarget()->CastSpell(GetTarget(), SPELL_WARLORDS_RAGE_PROC, true);
}
}
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_warlords_rage::HandleAfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_warlord_kalithresh()
{
RegisterSteamvaultCreatureAI(boss_warlord_kalithresh);
RegisterSteamvaultCreatureAI(npc_naga_distiller);
RegisterSpellScript(spell_warlords_rage);
}

View File

@@ -25,6 +25,13 @@ enum MainChambersAccessPanelSays
SAY_LOUD_RUMBLE = 1
};
MinionData const minionData[] =
{
{ NPC_NAGA_DISTILLER, DATA_WARLORD_KALITHRESH },
{ NPC_THESPIA_WATER_ELEMENTAL, DATA_HYDROMANCER_THESPIA },
{ 0, 0 }
};
class go_main_chambers_access_panel : public GameObjectScript
{
public:
@@ -91,14 +98,16 @@ public:
ObjectData const creatureData[] =
{
{ NPC_MEKGINEER_STEAMRIGGER, DATA_MEKGINEER_STEAMRIGGER },
{ NPC_DOOR_CONTROLLER, DATA_DOOR_CONTROLLER }
{ NPC_DOOR_CONTROLLER, DATA_DOOR_CONTROLLER },
{ 0, 0 }
};
ObjectData const objectData[] =
{
{ GO_ACCESS_PANEL_HYDRO, DATA_ACCESS_PANEL_HYDROMANCER },
{ GO_ACCESS_PANEL_MEK, DATA_ACCESS_PANEL_MEKGINEER },
{ GO_MAIN_CHAMBERS_DOOR, DATA_MAIN_CHAMBERS_DOOR }
{ GO_MAIN_CHAMBERS_DOOR, DATA_MAIN_CHAMBERS_DOOR },
{ 0, 0, }
};
class instance_steam_vault : public InstanceMapScript
@@ -113,6 +122,7 @@ public:
SetHeaders(DataHeaders);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, objectData);
LoadMinionData(minionData);
}
void OnGameObjectCreate(GameObject* go) override

View File

@@ -51,6 +51,12 @@ enum steamVaultNPCGO
NPC_DOOR_CONTROLLER = 20926
};
enum Creatures
{
NPC_NAGA_DISTILLER = 17954,
NPC_THESPIA_WATER_ELEMENTAL = 17917
};
template <class AI, class T>
inline AI* GetSteamVaultAI(T* obj)
{

View File

@@ -43,7 +43,10 @@ enum DeathKnightSpells
SPELL_DK_DISMISS_GARGOYLE = 50515,
SPELL_DK_SANCTUARY = 54661,
SPELL_DK_NIGHT_OF_THE_DEAD = 62137,
SPELL_DK_PET_SCALING = 61017
SPELL_DK_PET_SCALING = 61017,
// Risen Ally
SPELL_DK_RAISE_ALLY = 46619,
SPELL_GHOUL_FRENZY = 62218,
};
class npc_pet_dk_ebon_gargoyle : public CreatureScript
@@ -255,6 +258,38 @@ public:
}
};
class npc_pet_dk_risen_ally : public CreatureScript
{
public:
npc_pet_dk_risen_ally() : CreatureScript("npc_pet_dk_risen_ally") { }
struct npc_pet_dk_risen_allyAI : public PossessedAI
{
npc_pet_dk_risen_allyAI(Creature* c) : PossessedAI(c) { }
void OnCharmed(bool apply) override
{
if (!apply)
{
if (Unit* owner = me->GetCharmerOrOwner())
{
if (Player* player = owner->ToPlayer())
{
player->RemoveAurasDueToSpell(SPELL_DK_RAISE_ALLY); // Remove Raise Ally aura
player->RemoveAurasDueToSpell(SPELL_GHOUL_FRENZY); // Remove Frenzy aura
//player->ClearResurrectRequestData();
}
}
}
}
};
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_pet_dk_risen_allyAI (pCreature);
}
};
class npc_pet_dk_army_of_the_dead : public CreatureScript
{
public:
@@ -335,6 +370,7 @@ void AddSC_deathknight_pet_scripts()
{
new npc_pet_dk_ebon_gargoyle();
new npc_pet_dk_ghoul();
new npc_pet_dk_risen_ally();
new npc_pet_dk_army_of_the_dead();
new npc_pet_dk_dancing_rune_weapon();
RegisterSpellScript(spell_pet_dk_gargoyle_strike);

View File

@@ -72,7 +72,11 @@ enum DeathKnightSpells
SPELL_DK_UNHOLY_PRESENCE = 48265,
SPELL_DK_UNHOLY_PRESENCE_TRIGGERED = 49772,
SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189,
SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284
SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284,
// Risen Ally
SPELL_DK_RAISE_ALLY = 46619,
SPELL_DK_THRASH = 47480,
SPELL_GHOUL_FRENZY = 62218,
};
enum DeathKnightSpellIcons
@@ -82,7 +86,8 @@ enum DeathKnightSpellIcons
enum Misc
{
NPC_DK_GHOUL = 26125
NPC_DK_GHOUL = 26125,
NPC_RISEN_ALLY = 30230
};
// 50526 - Wandering Plague
@@ -1496,6 +1501,53 @@ class spell_dk_ghoul_explode : public SpellScript
}
};
// 47480 - Thrash
class spell_dk_ghoul_thrash : public SpellScript
{
PrepareSpellScript(spell_dk_ghoul_thrash);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_GHOUL_FRENZY });
}
void CalcDamage(SpellEffIndex /*effIndex*/)
{
/*
Causes more damage per frenzy point:
1 point : (Attack power * 40 * 0.01 + Attack power * 0.05)-(Attack power * 40 * 0.01 + Attack power * 0.10) damage
2 points : (Attack power * 40 * 0.01 + Attack power * 0.10)-(Attack power * 40 * 0.01 + Attack power * 0.20) damage
3 points : (Attack power * 40 * 0.01 + Attack power * 0.15)-(Attack power * 40 * 0.01 + Attack power * 0.30) damage
4 points : (Attack power * 40 * 0.01 + Attack power * 0.20)-(Attack power * 40 * 0.01 + Attack power * 0.40) damage
5 points : (Attack power * 40 * 0.01 + Attack power * 0.25)-(Attack power * 40 * 0.01 + Attack power * 0.50) damage
*/
if (Aura* frenzy = GetCaster()->GetAura(SPELL_GHOUL_FRENZY))
{
float APBonus = GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK);
float fixedDamageBonus = APBonus * GetEffectValue() * 0.01f;
APBonus *= 0.05f * frenzy->GetStackAmount();
SetEffectValue(fixedDamageBonus + urand(int32(APBonus), int32(APBonus * 2.f)));
if (Unit* caster = GetCaster())
{
caster->RemoveAurasDueToSpell(SPELL_GHOUL_FRENZY);
if (Unit* charmer = caster->GetCharmer())
{
charmer->RemoveAurasDueToSpell(SPELL_GHOUL_FRENZY);
}
}
}
}
void Register() override
{
OnEffectLaunchTarget += SpellEffectFn(spell_dk_ghoul_thrash::CalcDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 48792 - Icebound Fortitude
class spell_dk_icebound_fortitude : public AuraScript
{
@@ -2184,4 +2236,5 @@ void AddSC_deathknight_spell_scripts()
RegisterSpellScript(spell_dk_spell_deflection);
RegisterSpellScript(spell_dk_vampiric_blood);
RegisterSpellScript(spell_dk_will_of_the_necropolis);
RegisterSpellScript(spell_dk_ghoul_thrash);
}

View File

@@ -4792,6 +4792,41 @@ class spell_freezing_circle : public SpellScript
}
};
enum Threshalisk
{
SPELL_THRESHALISK_CHARGE = 35385,
SPELL_RUSHING_CHARGE = 35382,
};
class spell_gen_threshalisk_charge : public SpellScript
{
PrepareSpellScript(spell_gen_threshalisk_charge);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_THRESHALISK_CHARGE });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
if (Creature* caster = GetCaster()->ToCreature())
{
if (Unit* victim = caster->GetVictim())
{
if (caster->GetReactState() != REACT_PASSIVE)
{
caster->CastSpell(victim, GetSpellInfo()->Effects[EFFECT_1].TriggerSpell, true);
}
}
}
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_gen_threshalisk_charge::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_silithyst);
@@ -4934,4 +4969,5 @@ void AddSC_generic_spell_scripts()
RegisterSpellScriptWithArgs(spell_gen_apply_aura_after_expiration, "spell_itch_aq40", SPELL_VEKNISS_CATALYST, EFFECT_0, SPELL_AURA_DUMMY);
RegisterSpellScript(spell_gen_basic_campfire);
RegisterSpellScript(spell_freezing_circle);
RegisterSpellScript(spell_gen_threshalisk_charge);
}