/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "AreaDefines.h"
#include "AreaTriggerScript.h"
#include "CellImpl.h"
#include "Chat.h"
#include "CombatAI.h"
#include "CreatureScript.h"
#include "CreatureTextMgr.h"
#include "GameObjectScript.h"
#include "GridNotifiersImpl.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "Vehicle.h"
/********
QUEST Conversing With the Depths (12032)
********/
enum DepthsMisc
{
QUEST_CONVERSING_WITH_THE_DEPTHS = 12032,
DEEPDIVING_PEARL_BUFF = 41273,
NPC_OACHANOA = 26648,
NPC_CONVERSING_WITH_THE_DEPTHS_TRIGGER = 70100,
};
enum DepthsTexts
{
// Oacha'noa being summoned
SAY_OACHANOA_SUMMONED_0 = 0,
SAY_OACHANOA_SUMMONED_1 = 1,
SAY_OACHANOA_SUMMONED_2 = 2,
SAY_OACHANOA_SUMMONED_3 = 3,
//SAY_OACHANOA_SUMMONED_4 = 4, // Unused(no source) and no BroadcastTextId
// If success
SAY_OACHANOA_SUCCESS = 5,
WHISPER_OACHANOA_SUCCESS_0 = 6,
WHISPER_OACHANOA_SUCCESS_1 = 7,
WHISPER_OACHANOA_SUCCESS_2 = 8,
// If failed
SAY_OACHANOA_FAILED = 9,
};
class npc_conversing_with_the_depths_trigger : public CreatureScript
{
public:
npc_conversing_with_the_depths_trigger() : CreatureScript("npc_conversing_with_the_depths_trigger") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_conversing_with_the_depths_triggerAI (pCreature);
}
struct npc_conversing_with_the_depths_triggerAI : public ScriptedAI
{
npc_conversing_with_the_depths_triggerAI(Creature* c) : ScriptedAI(c) { }
bool running;
bool secondpart;
bool canjump;
int32 timer;
uint8 step;
ObjectGuid pGUID;
ObjectGuid oachanoaGUID;
Creature* GetOachanoa() {return ObjectAccessor::GetCreature(*me, oachanoaGUID);}
Player* GetPlayer() {return ObjectAccessor::GetPlayer(*me, pGUID);}
void Reset() override
{
running = false;
secondpart = false;
canjump = false;
timer = 0;
step = 0;
pGUID.Clear();
oachanoaGUID.Clear();
}
void NextStep(const uint32 time)
{
step++;
timer = time;
}
void DespawnOachanoa()
{
if (Creature* c = GetOachanoa())
c->DespawnOrUnsummon();
}
void UpdateAI(uint32 diff) override
{
if (running)
{
if (Player* p = GetPlayer())
if (p->GetPositionZ() < 1.0f && !secondpart) // Player is in the water
{
if (p->HasAura(DEEPDIVING_PEARL_BUFF) && canjump)
{
NextStep(500);
secondpart = true;
}
else // Despawn and fail quest if player jumps too early
{
p->SendQuestFailed(QUEST_CONVERSING_WITH_THE_DEPTHS);
DespawnOachanoa();
Reset();
}
}
if (timer != 0)
{
timer -= diff;
if (timer < 0)
timer = 0;
}
else
switch (step)
{
case 0:
NextStep(10000);
break;
case 1: // Oacha'noa being summoned
{
Creature* c = me->SummonCreature(NPC_OACHANOA, 2406.24f, 1701.98f, 0.1f, 0.3f, TEMPSUMMON_TIMED_DESPAWN, 90000, 0);
if (!c)
{
Reset();
return;
}
c->SetCanFly(true);
c->GetMotionMaster()->MovePoint(0, 2406.25f, 1701.98f, 0.1f);
oachanoaGUID = c->GetGUID();
NextStep(3000);
break;
}
case 2:
{
Player* p = GetPlayer();
if (!p)
{
Reset();
return;
}
if (Creature* c = GetOachanoa())
c->AI()->Talk(SAY_OACHANOA_SUMMONED_0, p);
NextStep(6000);
break;
}
case 3:
{
if (Creature* c = GetOachanoa())
c->AI()->Talk(SAY_OACHANOA_SUMMONED_1);
NextStep(6000);
break;
}
case 4:
{
if (Creature* c = GetOachanoa())
c->AI()->Talk(SAY_OACHANOA_SUMMONED_2);
Player* p = GetPlayer();
if (!p)
{
Reset();
return;
}
p->CastSpell(p, DEEPDIVING_PEARL_BUFF, true);
NextStep(6000);
break;
}
case 5: // 20s countdown starts, the player can jump now
{
canjump = true;
if (Creature* c = GetOachanoa())
c->AI()->Talk(SAY_OACHANOA_SUMMONED_3);
NextStep(20500);
break;
}
case 6: // If failed (player DOESN'T jump within 20 seconds)
{
Player* p = GetPlayer();
if (Creature* c = GetOachanoa())
c->AI()->Talk(SAY_OACHANOA_FAILED, p);
DespawnOachanoa();
Reset();
break;
}
case 7: // If success (player jumps)
{
Player* p = GetPlayer();
if (!p)
{
Reset();
return;
}
if (Creature* c = GetOachanoa())
c->AI()->Talk(SAY_OACHANOA_SUCCESS, p);
NextStep(6000);
break;
}
case 8:
{
Player* p = GetPlayer();
if (Creature* c = GetOachanoa())
c->AI()->Talk(WHISPER_OACHANOA_SUCCESS_0, p);
NextStep(6000);
break;
}
case 9:
{
Player* p = GetPlayer();
if (Creature* c = GetOachanoa())
c->AI()->Talk(WHISPER_OACHANOA_SUCCESS_1, p);
NextStep(6000);
break;
}
case 10:
{
Player* p = GetPlayer();
if (!p)
{
Reset();
return;
}
if (Creature* c = GetOachanoa())
c->AI()->Talk(WHISPER_OACHANOA_SUCCESS_2, p);
p->AreaExploredOrEventHappens(QUEST_CONVERSING_WITH_THE_DEPTHS);
DespawnOachanoa();
Reset();
}
}
}
}
void Start(ObjectGuid g)
{
running = true;
pGUID = g;
}
};
};
class go_the_pearl_of_the_depths : public GameObjectScript
{
public:
go_the_pearl_of_the_depths() : GameObjectScript("go_the_pearl_of_the_depths") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
if (!player || !go)
return true;
Creature* t = player->FindNearestCreature(NPC_CONVERSING_WITH_THE_DEPTHS_TRIGGER, 10.0f, true);
if (t && t->AI() && CAST_AI(npc_conversing_with_the_depths_trigger::npc_conversing_with_the_depths_triggerAI, t->AI()))
if (!CAST_AI(npc_conversing_with_the_depths_trigger::npc_conversing_with_the_depths_triggerAI, t->AI())->running)
CAST_AI(npc_conversing_with_the_depths_trigger::npc_conversing_with_the_depths_triggerAI, t->AI())->Start(player->GetGUID());
return true;
}
};
enum hourglass
{
NPC_FUTURE_HOURGLASS = 27840,
NPC_FUTURE_YOU = 27899,
NPC_PAST_HOURGLASS = 32327,
NPC_PAST_YOU = 32331,
NPC_INFINITE_ASSAILANT = 27896,
NPC_INFINITE_CHRONO_MAGUS = 27898,
NPC_INFINITE_DESTROYER = 27897,
NPC_INFINITE_TIMERENDER = 27900,
NPC_NOZDORMU = 27925,
SPELL_NOZDORMU_INVIS = 50013,
SPELL_CLONE_CASTER = 49889,
SPELL_TELEPORT_EFFECT = 52096,
EVENT_START_EVENT = 1,
EVENT_FIGHT_1 = 2,
EVENT_FIGHT_2 = 3,
EVENT_CHECK_FINISH = 4,
EVENT_FINISH_EVENT = 5,
QUEST_MYSTERY_OF_THE_INFINITE = 12470,
QUEST_MYSTERY_OF_THE_INFINITE_REDUX = 13343,
};
enum hourglassText
{
// (All are whispers) Both NPC_PAST_YOU and NPC_FUTURE_YOU share the same creature_text GroupIDs
// Start
SAY_HOURGLASS_START_1 = 1,
SAY_HOURGLASS_START_2 = 2,
// Random whispers during the fight
SAY_HOURGLASS_RANDOM_1 = 3,
SAY_HOURGLASS_RANDOM_2 = 4,
SAY_HOURGLASS_RANDOM_3 = 5,
SAY_HOURGLASS_RANDOM_4 = 6,
SAY_HOURGLASS_RANDOM_5 = 7,
SAY_HOURGLASS_RANDOM_6 = 8,
SAY_HOURGLASS_RANDOM_7 = 9,
SAY_HOURGLASS_RANDOM_8 = 10,
// End
SAY_HOURGLASS_END_1 = 11,
SAY_HOURGLASS_END_2 = 12,
};
class npc_hourglass_of_eternity : public CreatureScript
{
public:
npc_hourglass_of_eternity() : CreatureScript("npc_hourglass_of_eternity") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_hourglass_of_eternityAI (pCreature);
}
struct npc_hourglass_of_eternityAI : public ScriptedAI
{
npc_hourglass_of_eternityAI(Creature* c) : ScriptedAI(c) {}
ObjectGuid pGUID;
ObjectGuid copyGUID;
EventMap events;
uint8 count[3];
uint8 phase;
uint8 randomTalk;
uint8 lastRandomTalk;
bool IsFuture() {return me->GetEntry() == NPC_FUTURE_HOURGLASS;}
void InitializeAI() override
{
if (me->ToTempSummon())
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
{
pGUID = summoner->GetGUID();
float x, y, z;
me->GetNearPoint(summoner, x, y, z, me->GetCombatReach(), 0.0f, rand_norm() * 2 * M_PI);
if (Creature* cr = summoner->SummonCreature((IsFuture() ? NPC_FUTURE_YOU : NPC_PAST_YOU), x, y, z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 210000))
{
copyGUID = cr->GetGUID();
summoner->CastSpell(cr, SPELL_CLONE_CASTER, true);
cr->SetFaction(summoner->GetFaction());
cr->SetReactState(REACT_AGGRESSIVE);
}
}
count[0] = 2;
count[1] = 2;
count[2] = 3;
phase = 0;
events.Reset();
events.ScheduleEvent(EVENT_START_EVENT, 4s);
}
Player* GetPlayer() {return ObjectAccessor::GetPlayer(*me, pGUID);}
Creature* GetCopy() {return ObjectAccessor::GetCreature(*me, copyGUID);}
uint32 randEntry()
{
return NPC_INFINITE_ASSAILANT + urand(0, 2);
}
void ShowNozdormu()
{
if (Creature* cr = me->FindNearestCreature(NPC_NOZDORMU, 100.0f, true))
cr->RemoveAura(SPELL_NOZDORMU_INVIS);
}
void HideNozdormu()
{
if (Creature* cr = me->FindNearestCreature(NPC_NOZDORMU, 100.0f, true))
cr->AddAura(SPELL_NOZDORMU_INVIS, cr);
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_START_EVENT:
if (Creature* cr = GetCopy())
cr->AI()->Talk(SAY_HOURGLASS_START_1, GetPlayer());
events.ScheduleEvent(EVENT_FIGHT_1, 7s);
break;
case EVENT_FIGHT_1:
if (Creature* cr = GetCopy())
cr->AI()->Talk(SAY_HOURGLASS_START_2, GetPlayer());
events.ScheduleEvent(EVENT_FIGHT_2, 6s);
break;
case EVENT_FIGHT_2:
{
if (phase)
randomWhisper();
Creature* cr = nullptr;
float x, y, z;
if (phase < 3)
{
for (uint8 i = 0; i < count[phase]; ++i)
{
me->GetNearPoint(me, x, y, z, me->GetCombatReach(), 10.0f, rand_norm() * 2 * M_PI);
if ((cr = me->SummonCreature(randEntry(), x, y, z + 2.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)))
{
cr->CastSpell(cr, SPELL_TELEPORT_EFFECT, true);
cr->AI()->AttackStart(me);
cr->AddThreat(me, 100.0f);
}
}
}
else if (phase == 3)
{
me->GetNearPoint(me, x, y, z, me->GetCombatReach(), 20.0f, rand_norm() * 2 * M_PI);
if ((cr = me->SummonCreature(NPC_INFINITE_TIMERENDER, x, y, z, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)))
{
cr->CastSpell(cr, SPELL_TELEPORT_EFFECT, true);
cr->AI()->AttackStart(me);
}
events.ScheduleEvent(EVENT_CHECK_FINISH, 20s);
return;
}
++phase;
events.ScheduleEvent(EVENT_FIGHT_2, 35s);
break;
}
case EVENT_CHECK_FINISH:
{
if (me->FindNearestCreature(NPC_INFINITE_TIMERENDER, 50.0f))
{
events.Repeat(5s);
return;
}
ShowNozdormu();
if (Player* player = GetPlayer())
player->GroupEventHappens(IsFuture() ? QUEST_MYSTERY_OF_THE_INFINITE : QUEST_MYSTERY_OF_THE_INFINITE_REDUX, me);
if (Creature* cr = GetCopy())
{
cr->SetFacingToObject(me->FindNearestCreature(NPC_NOZDORMU, 100.0f, true));
cr->AI()->Talk(SAY_HOURGLASS_END_1, GetPlayer());
}
events.ScheduleEvent(EVENT_FINISH_EVENT, 6s);
break;
}
case EVENT_FINISH_EVENT:
{
HideNozdormu();
if (Creature* cr = GetCopy())
cr->AI()->Talk(SAY_HOURGLASS_END_2, GetPlayer());
me->DespawnOrUnsummon(500ms);
if (GetCopy())
GetCopy()->DespawnOrUnsummon(500ms);
break;
}
}
}
void randomWhisper() // Do not repeat the same line
{
randomTalk = urand(SAY_HOURGLASS_RANDOM_1, SAY_HOURGLASS_RANDOM_8); // 3 to 10
if (randomTalk == lastRandomTalk)
{
randomWhisper();
}
else
{
if (Creature* cr = GetCopy())
cr->AI()->Talk(randomTalk, GetPlayer());
lastRandomTalk = randomTalk;
}
}
};
};
class npc_future_you : public CreatureScript
{
public:
npc_future_you() : CreatureScript("npc_future_you") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_future_youAI (pCreature);
}
struct npc_future_youAI : public ScriptedAI
{
npc_future_youAI(Creature* c) : ScriptedAI(c) {}
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->RemoveUnitFlag(UNIT_FLAG_IN_COMBAT);
me->ClearUnitState(UNIT_STATE_EVADE);
}
void Reset() override
{
if (me->ToTempSummon() && me->ToTempSummon()->GetSummonerUnit())
me->SetFaction(me->ToTempSummon()->GetSummonerUnit()->GetFaction());
}
void MoveInLineOfSight(Unit* who) override
{
if (!me->GetVictim() && !who->IsFlying() && who->GetEntry() >= NPC_INFINITE_ASSAILANT && who->GetEntry() <= NPC_INFINITE_TIMERENDER)
AttackStart(who);
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
};
};
enum chainGun
{
NPC_INJURED_7TH_LEGION_SOLDER = 27788,
SPELL_FEAR_AURA_WITH_COWER = 49774
};
class npc_mindless_ghoul : public CreatureScript
{
public:
npc_mindless_ghoul() : CreatureScript("npc_mindless_ghoul") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_mindless_ghoulAI (pCreature);
}
struct npc_mindless_ghoulAI : public ScriptedAI
{
npc_mindless_ghoulAI(Creature* c) : ScriptedAI(c)
{
me->SetCorpseDelay(1);
}
bool CanAIAttack(Unit const* who) const override
{
return who->GetEntry() == NPC_INJURED_7TH_LEGION_SOLDER;
}
void JustDied(Unit*) override
{
me->SetCorpseDelay(1);
}
};
};
class npc_injured_7th_legion_soldier : public CreatureScript
{
public:
npc_injured_7th_legion_soldier() : CreatureScript("npc_injured_7th_legion_soldier") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_injured_7th_legion_soldierAI (pCreature);
}
struct npc_injured_7th_legion_soldierAI : public NullCreatureAI
{
npc_injured_7th_legion_soldierAI(Creature* c) : NullCreatureAI(c) {}
void Reset() override
{
me->CastSpell(me, SPELL_FEAR_AURA_WITH_COWER, true);
me->SetWalk(false);
uint32 path = me->GetEntry() * 10 + urand(0, 4);
if (me->GetPositionY() > -1150.0f)
path += 5;
me->GetMotionMaster()->MoveWaypoint(path, false);
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != WAYPOINT_MOTION_TYPE)
return;
if (point == 9)
{
Talk(0);
me->RemoveAllAuras();
me->DespawnOrUnsummon(1s);
if (TempSummon* summon = me->ToTempSummon())
if (Unit* owner = summon->GetSummonerUnit())
if (Player* player = owner->ToPlayer())
player->KilledMonsterCredit(me->GetEntry());
}
}
};
};
enum WintergardeGryphon
{
SPELL_RESCUE_VILLAGER = 48363,
SPELL_DROP_OFF_VILLAGER = 48397,
SPELL_RIDE_VEHICLE = 43671,
NPC_HELPLESS_VILLAGER_A = 27315,
NPC_HELPLESS_VILLAGER_B = 27336,
EVENT_VEHICLE_GET = 1,
EVENT_TAKE_OFF = 2,
EVENT_GET_VILLAGER = 3,
EVENT_PHASE_FEAR = 1,
EVENT_PHASE_VEHICLE = 2,
POINT_LAND = 1,
POINT_TAKE_OFF = 2,
QUEST_FLIGHT_OF_THE_WINTERGARDE_DEFENDER = 12237,
GO_TEMP_GRYPHON_STATION = 188679
};
class npc_wintergarde_gryphon : public VehicleAI
{
public:
npc_wintergarde_gryphon(Creature* creature) : VehicleAI(creature)
{
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon(3s, 0s);
}
void IsSummonedBy(WorldObject* summoner) override
{
me->SetFacingToObject(summoner);
Position pos = summoner->GetPosition();
me->GetMotionMaster()->MovePoint(POINT_LAND, pos);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_LAND)
events.ScheduleEvent(EVENT_VEHICLE_GET, 0s);
}
void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override
{
if (!apply && seatId == 0)
{
// left the vehicle with a passenger will result in despawn
if (Vehicle* gryphon = me->GetVehicleKit())
if (Unit* villager = gryphon->GetPassenger(1))
{
if (!villager->IsCreature())
return;
if (Creature* seat = villager->ToCreature())
{
seat->ExitVehicle();
seat->DespawnOrUnsummon();
}
}
events.ScheduleEvent(EVENT_TAKE_OFF, 2s);
me->CastSpell(passenger, VEHICLE_SPELL_PARACHUTE, true);
}
}
Creature* getVillager() { return ObjectAccessor::GetCreature(*me, villagerGUID); }
void UpdateAI(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_VEHICLE_GET:
{
me->SetDisableGravity(false);
me->SetHover(false);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
break;
}
case EVENT_TAKE_OFF:
{
me->DespawnOrUnsummon(4050ms);
me->SetOrientation(2.5f);
me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
Position pos = me->GetPosition();
Position offset = { 14.0f, 14.0f, 16.0f, 0.0f };
pos.RelocateOffset(offset);
me->GetMotionMaster()->MovePoint(POINT_TAKE_OFF, pos);
break;
}
case EVENT_GET_VILLAGER:
{
if (getVillager())
{
getVillager()->GetMotionMaster()->MovePoint(0, 3660.0f, -706.4f, 215.0f);
getVillager()->DespawnOrUnsummon(7s, 0s);
}
break;
}
}
}
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id != SPELL_DROP_OFF_VILLAGER)
return;
if (Vehicle* gryphon = me->GetVehicleKit())
if (Unit* villager = gryphon->GetPassenger(1))
{
villager->ExitVehicle();
villager->GetMotionMaster()->Clear(false);
villager->GetMotionMaster()->MoveIdle();
villager->SetCanFly(false); // prevents movement in flight
villagerGUID = villager->GetGUID();
villager->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
events.ScheduleEvent(EVENT_GET_VILLAGER, 3s);
}
}
private:
ObjectGuid villagerGUID;
};
class spell_q12237_rescue_villager : public SpellScript
{
PrepareSpellScript(spell_q12237_rescue_villager);
SpellCastResult CheckCast()
{
Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!owner)
return SPELL_FAILED_DONT_REPORT;
SpellCustomErrors extension = SPELL_CUSTOM_ERROR_NONE;
SpellCastResult result = SPELL_CAST_OK;
if (GetCaster()->GetAreaId() == AREA_WINTERGARDE_KEEP)
{
extension = SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER;
result = SPELL_FAILED_CUSTOM_ERROR;
}
if (!GetCaster()->FindNearestCreature(NPC_HELPLESS_VILLAGER_A, 5.0f) && !GetCaster()->FindNearestCreature(NPC_HELPLESS_VILLAGER_B, 5.0f))
{
extension = SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER;
result = SPELL_FAILED_CUSTOM_ERROR;
}
if (GetCaster()->FindNearestGameObject(GO_TEMP_GRYPHON_STATION, 15.0f))
{
extension = SPELL_CUSTOM_ERROR_NEED_HELPLESS_VILLAGER;
result = SPELL_FAILED_CUSTOM_ERROR;
}
if (GetCaster()->HasAura(SPELL_RIDE_VEHICLE))
result = SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
if (result != SPELL_CAST_OK)
{
Spell::SendCastResult(owner, GetSpellInfo(), 0, result, extension);
return result;
}
return SPELL_CAST_OK;
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
target->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_q12237_rescue_villager::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
OnCheckCast += SpellCheckCastFn(spell_q12237_rescue_villager::CheckCast);
}
};
class spell_q12237_drop_off_villager : public SpellScript
{
PrepareSpellScript(spell_q12237_drop_off_villager);
SpellCastResult CheckCast()
{
Player* master = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!master)
return SPELL_FAILED_DONT_REPORT;
SpellCustomErrors extension = SPELL_CUSTOM_ERROR_NONE;
SpellCastResult result = SPELL_CAST_OK;
if (!GetCaster()->FindNearestGameObject(GO_TEMP_GRYPHON_STATION, 10.0f))
result = SPELL_FAILED_REQUIRES_SPELL_FOCUS;
if (!GetCaster()->HasAura(SPELL_RIDE_VEHICLE))
{
extension = SPELL_CUSTOM_ERROR_NO_PASSENGER;
result = SPELL_FAILED_CUSTOM_ERROR;
}
if (result != SPELL_CAST_OK)
{
Spell::SendCastResult(master, GetSpellInfo(), 0, result, extension);
return result;
}
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_q12237_drop_off_villager::CheckCast);
}
};
class spell_call_wintergarde_gryphon : public SpellScript
{
PrepareSpellScript(spell_call_wintergarde_gryphon);
void SetDest(SpellDestination& dest)
{
// Adjust effect summon position
Position const offset = { 0.0f, 0.0f, 9.0f, 0.0f };
dest.RelocateOffset(offset);
}
SpellCastResult CheckRequirement()
{
if (Player* playerCaster = GetCaster()->ToPlayer())
{
if (playerCaster->GetQuestStatus(QUEST_FLIGHT_OF_THE_WINTERGARDE_DEFENDER) == QUEST_STATUS_INCOMPLETE)
return SPELL_CAST_OK;
}
return SPELL_FAILED_DONT_REPORT;
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_call_wintergarde_gryphon::CheckRequirement);
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_call_wintergarde_gryphon::SetDest, EFFECT_0, TARGET_DEST_CASTER_FRONT);
}
};
class npc_heated_battle : public CreatureScript
{
public:
npc_heated_battle() : CreatureScript("npc_heated_battle") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_heated_battleAI (pCreature);
}
struct npc_heated_battleAI : public CombatAI
{
npc_heated_battleAI(Creature* c) : CombatAI(c) {}
void Reset() override
{
me->SetCorpseDelay(60);
CombatAI::Reset();
if (Unit* target = me->SelectNearestTarget(50.0f))
AttackStart(target);
}
void DamageTaken(Unit* who, uint32&, DamageEffectType, SpellSchoolMask) override
{
if (who && who->IsPlayer())
{
me->SetLootRecipient(who);
me->LowerPlayerDamageReq(me->GetMaxHealth());
}
}
};
};
enum eFrostmourneCavern
{
NPC_PRINCE_ARTHAS = 27455,
};
class spell_q12478_frostmourne_cavern : public SpellScript
{
PrepareSpellScript(spell_q12478_frostmourne_cavern);
void HandleSendEvent(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
GetCaster()->SummonCreature(NPC_PRINCE_ARTHAS, 4821.3f, -580.14f, 163.541f, 4.57f);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_q12478_frostmourne_cavern::HandleSendEvent, EFFECT_0, SPELL_EFFECT_SEND_EVENT);
}
};
class spell_q12243_fire_upon_the_waters_aura : public AuraScript
{
PrepareAuraScript(spell_q12243_fire_upon_the_waters_aura);
void HandleApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
std::list servants;
GetTarget()->GetCreatureListWithEntryInGrid(servants, 27233 /*NPC_ONSLAUGHT_DECKHAND*/, 40.0f);
for (std::list::const_iterator itr = servants.begin(); itr != servants.end(); ++itr)
{
(*itr)->SetSpeed(MOVE_RUN, 0.7f, true);
(*itr)->GetMotionMaster()->MoveFleeing(GetTarget(), GetDuration());
}
}
void HandleRemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
std::list servants;
GetTarget()->GetCreatureListWithEntryInGrid(servants, 27233 /*NPC_ONSLAUGHT_DECKHAND*/, 100.0f);
for (std::list::const_iterator itr = servants.begin(); itr != servants.end(); ++itr)
(*itr)->SetSpeed(MOVE_RUN, 1.1f, true);
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_q12243_fire_upon_the_waters_aura::HandleApplyEffect, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_q12243_fire_upon_the_waters_aura::HandleRemoveEffect, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
// The Sacred and the Corrupt (24545)
enum eSandC
{
QUEST_THE_SACRED_AND_THE_CORRUPT = 24545,
NPC_SAC_LICH_KING = 37857,
NPC_SAC_LIGHTS_VENGEANCE = 37826,
NPC_SAC_LIGHTS_VENGEANCE_VEH_1 = 37827,
NPC_SAC_LIGHTS_VENGEANCE_VEH_2 = 37952,
NPC_SAC_LIGHTS_VENGEANCE_BUNNY = 38001,
NPC_SAC_WRETCHED_GHOUL = 37881,
NPC_SAC_VEGARD_1 = 37893,
GO_SAC_LIGHTS_VENGEANCE_1 = 201844,
GO_SAC_LIGHTS_VENGEANCE_2 = 201922,
GO_SAC_LIGHTS_VENGEANCE_3 = 201937,
SPELL_SAC_STUN = 70583,
SPELL_SAC_REPEL_HAMMER = 70590,
SPELL_SAC_HOLY_ZONE_AURA = 70571,
SPELL_SAC_THROW_HAMMER = 70595,
SPELL_SAC_SUMMON_GO_1 = 70603,
SPELL_SAC_SUMMON_GHOULS_AURA = 70612,
SPELL_SAC_EMERGE = 50142,
SPELL_SAC_SHIELD_OF_THE_LICH_KING = 70692,
SPELL_SAC_ZAP_PLAYER = 70653,
SPELL_SAC_LK_DESPAWN_ANIM = 70673,
SPELL_SAC_VEGARD_SUMMON_GHOULS_AURA = 70737,
SPELL_SAC_GHOUL_AREA_AURA = 70782,
SPELL_SAC_HOLY_BOMB_VISUAL = 70785,
SPELL_SAC_HOLY_BOMB_EXPLOSION = 70786,
SPELL_SAC_ZAP_GHOULS_AURA = 70789,
SPELL_SAC_GHOUL_EXPLODE = 70787,
SPELL_SAC_KILL_VEGARD = 70792,
SPELL_SAC_SUMMON_GO_2 = 70894,
SPELL_SAC_SUMMON_VEGARD_SKELETON = 70862,
SPELL_SAC_HAMMER_SHIELD = 70970,
SPELL_SAC_SUMMON_GO_3 = 70967,
// Xinef:
SPELL_SAC_BLUE_EXPLOSION = 70509,
SPELL_SAC_VEHICLE_CONTROL_AURA = 70510,
};
class WretchedGhoulCleaner
{
public:
void operator()(Creature* creature)
{
if (creature->GetEntry() == NPC_SAC_WRETCHED_GHOUL && creature->GetDisplayId() != 11686 && creature->IsAlive())
Unit::Kill(creature, creature);
}
};
class npc_q24545_lich_king : public CreatureScript
{
public:
npc_q24545_lich_king() : CreatureScript("npc_q24545_lich_king") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_q24545_lich_kingAI (pCreature);
}
struct npc_q24545_lich_kingAI : public NullCreatureAI
{
npc_q24545_lich_kingAI(Creature* c) : NullCreatureAI(c), summons(me)
{
}
EventMap events;
SummonList summons;
ObjectGuid playerGUID;
void CleanAll(bool fromReset = true)
{
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_BUNNY, 150.0f, true))
c->RemoveAllAuras();
if (fromReset)
{
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE, 150.0f, true))
c->DespawnOrUnsummon(1ms);
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_1, 150.0f, true))
c->RemoveAllAuras();
}
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_2, 150.0f, true))
c->DespawnOrUnsummon(1ms);
if (GameObject* go = me->FindNearestGameObject(GO_SAC_LIGHTS_VENGEANCE_1, 150.0f))
go->Delete();
if (GameObject* go = me->FindNearestGameObject(GO_SAC_LIGHTS_VENGEANCE_2, 150.0f))
go->Delete();
WretchedGhoulCleaner cleaner;
Acore::CreatureWorker worker(me, cleaner);
Cell::VisitObjects(me, worker, 150.0f);
}
void Reset() override
{
events.Reset();
events.ScheduleEvent(998, 10s);
events.ScheduleEvent(999, 0ms);
events.ScheduleEvent(1, 3s);
summons.DespawnAll();
playerGUID.Clear();
CleanAll();
me->setActive(false);
me->SetWalk(true);
me->SetVisible(false);
me->RemoveAllAuras();
me->InterruptNonMeleeSpells(true);
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->UpdatePosition(x, y, z, o, true);
me->StopMovingOnCurrentPos();
me->GetMotionMaster()->Clear();
}
void SetGUID(ObjectGuid const& guid, int32 /*id*/) override
{
if (playerGUID || events.HasTimeUntilEvent(998) || events.HasTimeUntilEvent(2))
return;
me->setActive(true);
playerGUID = guid;
events.ScheduleEvent(2, 15min);
events.ScheduleEvent(3, 0ms);
}
void SetData(uint32 type, uint32 data) override
{
if (!playerGUID || type != data)
return;
if (data == 1)
events.ScheduleEvent(15, 0ms);
else if (data == 2)
{
if (GameObject* go = me->FindNearestGameObject(GO_SAC_LIGHTS_VENGEANCE_2, 150.0f))
go->Delete();
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_1, 150.0f, true))
{
c->CastSpell(c, SPELL_SAC_HAMMER_SHIELD, true);
c->CastSpell(c, SPELL_SAC_SUMMON_GO_3, true);
if (Player* p = ObjectAccessor::GetPlayer(*me, playerGUID))
p->KnockbackFrom(c->GetPositionX(), c->GetPositionY(), 5.0f, 3.0f);
}
events.ScheduleEvent(18, 3s);
}
else if (data == 3)
{
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_1, 150.0f, true))
{
c->RemoveAllAuras();
c->CastSpell(c, SPELL_SAC_HOLY_ZONE_AURA, true);
if (GameObject* go = me->FindNearestGameObject(GO_SAC_LIGHTS_VENGEANCE_3, 150.0f))
go->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
playerGUID.Clear();
events.RescheduleEvent(2, 1min);
}
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
switch (events.ExecuteEvent())
{
case 0:
break;
case 998: // ensure everything is cleaned up
CleanAll(false);
break;
case 999: // apply holy aura
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_1, 150.0f, true))
if (Creature* l = me->SummonCreature(NPC_SAC_LIGHTS_VENGEANCE, *c, TEMPSUMMON_MANUAL_DESPAWN))
{
l->CastSpell(c, SPELL_SAC_VEHICLE_CONTROL_AURA, true);
c->CastSpell(c, SPELL_SAC_HOLY_ZONE_AURA, true);
}
break;
case 1: // check player
if (playerGUID)
{
bool valid = false;
if (Player* p = ObjectAccessor::GetPlayer(*me, playerGUID))
if (p->IsAlive() && p->GetPhaseMask() & 2 && p->GetExactDistSq(me) < 100.0f * 100.0f && !p->IsGameMaster())
valid = true;
if (!valid)
{
Reset();
return;
}
}
events.ScheduleEvent(1, 3s);
break;
case 2: // reset timer
Reset();
break;
case 3: // start event
if (Player* p = ObjectAccessor::GetPlayer(*me, playerGUID))
{
me->CastSpell(p, SPELL_SAC_STUN, true);
me->SetVisible(true);
Movement::PointsArray path;
path.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
path.push_back(G3D::Vector3(4825.35f, -582.99f, 164.83f));
path.push_back(G3D::Vector3(4813.38f, -580.94f, 162.62f));
me->GetMotionMaster()->MoveSplinePath(&path);
events.ScheduleEvent(4, 10s);
}
break;
case 4: // talk 0
Talk(0);
events.ScheduleEvent(5, 6s);
break;
case 5: // talk 1
Talk(1);
events.ScheduleEvent(6, 4s);
events.ScheduleEvent(7, 11s);
break;
case 6: // repel hammer
me->CastSpell((Unit*)nullptr, SPELL_SAC_REPEL_HAMMER, false);
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_1, 150.0f, true))
c->CastSpell(c, SPELL_SAC_BLUE_EXPLOSION, true);
events.ScheduleEvent(65, 3500ms);
break;
case 65: // spawn hammer go
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_BUNNY, 150.0f, true))
{
c->CastSpell(c, SPELL_SAC_HOLY_ZONE_AURA, true);
c->CastSpell(c, SPELL_SAC_SUMMON_GO_1, true);
}
break;
case 7: // talk 2
Talk(2);
events.ScheduleEvent(8, 8s);
events.ScheduleEvent(9, 11s + 500ms);
break;
case 8: // summon ghouls
me->CastSpell((Unit*)nullptr, SPELL_SAC_SUMMON_GHOULS_AURA, false);
break;
case 9: // talk 3
Talk(3);
events.ScheduleEvent(10, 10s);
break;
case 10: // summon vegard
me->SummonCreature(NPC_SAC_VEGARD_1, 4812.12f, -586.08f, 162.49f, 3.14f, TEMPSUMMON_MANUAL_DESPAWN);
events.ScheduleEvent(11, 4s);
events.ScheduleEvent(12, 5s);
break;
case 11: // vagard shield
if (Creature* c = me->FindNearestCreature(NPC_SAC_VEGARD_1, 50.0f, true))
c->CastSpell(c, SPELL_SAC_SHIELD_OF_THE_LICH_KING, false);
break;
case 12: // talk 4
Talk(4);
if (Player* p = ObjectAccessor::GetPlayer(*me, playerGUID))
me->CastSpell(p, SPELL_SAC_ZAP_PLAYER, false);
events.ScheduleEvent(13, 3500ms);
events.ScheduleEvent(14, 6s);
break;
case 13: // despawn
me->CastSpell(me, SPELL_SAC_LK_DESPAWN_ANIM, false);
break;
case 14: // vagard talk 0
me->SetVisible(false);
me->RemoveAllAuras();
if (Creature* c = me->FindNearestCreature(NPC_SAC_VEGARD_1, 50.0f, true))
{
c->AI()->Talk(0);
c->CastSpell(c, SPELL_SAC_VEGARD_SUMMON_GHOULS_AURA, false);
}
if (GameObject* go = me->FindNearestGameObject(GO_SAC_LIGHTS_VENGEANCE_1, 150.0f))
go->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
break;
case 15: // remove light
if (Creature* x = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_2, 150.0f, true))
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_BUNNY, 150.0f, true))
{
c->RemoveAurasDueToSpell(SPELL_SAC_HOLY_ZONE_AURA);
if (Creature* l = me->SummonCreature(NPC_SAC_LIGHTS_VENGEANCE, *c, TEMPSUMMON_MANUAL_DESPAWN))
{
x->SetCanFly(true);
x->SetDisableGravity(true);
x->SetHover(true);
x->NearTeleportTo(4812.09f, -585.55f, 172.03f, 3.75f);
l->EnterVehicle(x, 1);
//l->ClearUnitState(UNIT_STATE_ONVEHICLE);
l->CastSpell(l, SPELL_SAC_HOLY_BOMB_VISUAL, false);
l->AddAura(SPELL_SAC_HOLY_BOMB_VISUAL, l);
events.ScheduleEvent(16, 5s);
}
}
break;
case 16: // add aura to kill ghouls
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE, 150.0f, true))
c->CastSpell(c, SPELL_SAC_ZAP_GHOULS_AURA, true);
if (Creature* c = me->FindNearestCreature(NPC_SAC_VEGARD_1, 50.0f, true))
c->RemoveAurasDueToSpell(SPELL_SAC_VEGARD_SUMMON_GHOULS_AURA);
events.ScheduleEvent(17, 12s);
break;
case 17: // kill vegard
{
WretchedGhoulCleaner cleaner;
Acore::CreatureWorker worker(me, cleaner);
Cell::VisitObjects(me, worker, 150.0f);
if (Creature* c = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE, 150.0f, true))
if (Creature* v = me->FindNearestCreature(NPC_SAC_VEGARD_1, 50.0f, true))
if (Creature* b = me->FindNearestCreature(NPC_SAC_LIGHTS_VENGEANCE_VEH_1, 150.0f, true))
{
c->CastSpell(v, SPELL_SAC_KILL_VEGARD, true);
v->SetDisplayId(11686);
v->DespawnOrUnsummon(1s);
b->CastSpell(b, SPELL_SAC_HOLY_BOMB_EXPLOSION, true);
b->CastSpell(b, SPELL_SAC_SUMMON_GO_2, true);
if (Unit* vb = c->GetVehicleBase())
{
if (Unit* pass = vb->GetVehicleKit()->GetPassenger(0))
if (pass->IsCreature())
pass->ToCreature()->DespawnOrUnsummon(1ms);
vb->RemoveAllAuras();
vb->ToCreature()->DespawnOrUnsummon(1ms);
}
c->ToCreature()->DespawnOrUnsummon(1ms);
}
}
break;
case 18: // summon vegard
me->CastSpell(me, SPELL_SAC_SUMMON_VEGARD_SKELETON, true);
break;
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void SummonedCreatureDespawn(Creature* summon) override
{
summons.Despawn(summon);
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
if (spell->Id == SPELL_SAC_REPEL_HAMMER && target->IsCreature())
{
target->CastSpell((Unit*)nullptr, SPELL_SAC_THROW_HAMMER, true);
target->ToCreature()->DespawnOrUnsummon(1ms);
if (Unit* c = target->GetVehicleBase())
c->RemoveAurasDueToSpell(SPELL_SAC_HOLY_ZONE_AURA);
}
}
};
};
class at_q24545_frostmourne_cavern : public AreaTriggerScript
{
public:
at_q24545_frostmourne_cavern() : AreaTriggerScript("at_q24545_frostmourne_cavern") { }
bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override
{
if (player->GetPhaseMask() & 2)
if (Creature* c = player->FindNearestCreature(NPC_SAC_LICH_KING, 60.0f, true))
c->AI()->SetGUID(player->GetGUID());
return true;
}
};
class SACActivateEvent : public BasicEvent
{
public:
SACActivateEvent(Creature* owner) : _owner(owner) {}
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
{
if (!_owner->IsAlive())
return true;
_owner->GetMotionMaster()->MoveRandom(5.0f);
_owner->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
_owner->SetReactState(REACT_AGGRESSIVE);
_owner->CastSpell(_owner, SPELL_SAC_GHOUL_AREA_AURA, true);
return true;
}
private:
Creature* _owner;
};
class SACDeactivateEvent : public BasicEvent
{
public:
SACDeactivateEvent(Creature* owner) : _owner(owner) {}
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
{
_owner->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
_owner->SetReactState(REACT_PASSIVE);
_owner->SetDisplayId(11686);
return true;
}
private:
Creature* _owner;
};
class npc_q24545_wretched_ghoul : public CreatureScript
{
public:
npc_q24545_wretched_ghoul() : CreatureScript("npc_q24545_wretched_ghoul") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_q24545_wretched_ghoulAI (pCreature);
}
struct npc_q24545_wretched_ghoulAI : public ScriptedAI
{
npc_q24545_wretched_ghoulAI(Creature* c) : ScriptedAI(c)
{
Deactivate();
}
void Reset() override
{
me->SetCorpseDelay(3);
}
void DoAction(int32 a) override
{
if (a == -1)
Activate();
else if (a == -2)
{
me->CastSpell(me, SPELL_SAC_GHOUL_EXPLODE, true);
me->KillSelf();
me->m_Events.KillAllEvents(true);
Deactivate();
}
}
void AttackStart(Unit* who) override
{
if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
return;
ScriptedAI::AttackStart(who);
}
bool CanAIAttack(Unit const* target) const override
{
if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) || target->HasUnitState(UNIT_STATE_STUNNED) || me->GetDisplayId() == 11686)
return false;
Position homePos = me->GetHomePosition();
return target->GetExactDistSq(&homePos) < 30.0f * 30.0f;
}
void Activate()
{
me->SetDisplayId(me->GetNativeDisplayId());
me->CastSpell(me, SPELL_SAC_EMERGE, true);
me->m_Events.AddEventAtOffset(new SACActivateEvent(me), 4s);
}
void Deactivate()
{
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_PASSIVE);
me->SetDisplayId(11686);
}
void JustDied(Unit* /*killer*/) override
{
me->RemoveAurasDueToSpell(SPELL_SAC_GHOUL_AREA_AURA);
me->m_Events.AddEventAtOffset(new SACDeactivateEvent(me), 4s);
}
void JustRespawned() override
{
Deactivate();
}
};
};
class GhoulTargetCheck
{
public:
explicit GhoulTargetCheck(bool alive) : _alive(alive) {}
bool operator()(WorldObject* object) const
{
return _alive ^ (!object->IsCreature() || ((Unit*)object)->GetDisplayId() != 11686);
}
private:
bool _alive;
};
class spell_q24545_aod_special : public SpellScript
{
PrepareSpellScript(spell_q24545_aod_special);
void FilterTargets(std::list& targets)
{
targets.remove_if(GhoulTargetCheck(GetSpellInfo()->Id == 70790));
Acore::Containers::RandomResize(targets, 2);
}
void HandleScript(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (Unit* target = GetHitUnit())
if (target->IsCreature())
target->ToCreature()->AI()->DoAction(GetSpellInfo()->Id == 70790 ? -2 : -1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_q24545_aod_special::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_q24545_aod_special::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
class npc_q24545_vegard_dummy : public CreatureScript
{
public:
npc_q24545_vegard_dummy() : CreatureScript("npc_q24545_vegard_dummy") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_q24545_vegard_dummyAI (pCreature);
}
struct npc_q24545_vegard_dummyAI : public NullCreatureAI
{
npc_q24545_vegard_dummyAI(Creature* c) : NullCreatureAI(c)
{
done = false;
}
bool done;
void UpdateAI(uint32 /*diff*/) override
{
if (!done)
{
done = true;
me->CastSpell(me, SPELL_SAC_EMERGE, true);
}
}
};
};
class npc_q24545_vegard : public CreatureScript
{
public:
npc_q24545_vegard() : CreatureScript("npc_q24545_vegard") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_q24545_vegardAI (pCreature);
}
struct npc_q24545_vegardAI : public ScriptedAI
{
npc_q24545_vegardAI(Creature* c) : ScriptedAI(c)
{
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
events.Reset();
events.ScheduleEvent(1, 7s);
events.ScheduleEvent(2, 7s, 20s);
events.ScheduleEvent(3, 7s, 20s);
events.ScheduleEvent(4, 7s, 20s);
events.ScheduleEvent(5, 7s, 20s);
events.ScheduleEvent(6, 1ms);
}
EventMap events;
void JustDied(Unit* /*killer*/) override
{
Talk(1);
me->DespawnOrUnsummon(10s);
if (Creature* c = me->FindNearestCreature(NPC_SAC_LICH_KING, 200.0f, true))
c->AI()->SetData(3, 3);
}
void KilledUnit(Unit* who) override
{
if (who->IsPlayer())
Talk(2);
}
void UpdateAI(uint32 diff) override
{
UpdateVictim();
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case 0:
break;
case 1:
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
if (Unit* t = me->SelectNearestTarget(50.0f))
AttackStart(t);
break;
case 2:
me->CastSpell((Unit*)nullptr, 70866, false);
events.Repeat(30s, 35s);
break;
case 3:
if (me->GetVictim())
me->CastSpell(me->GetVictim(), 70886, false);
events.Repeat(15s, 30s);
break;
case 4:
if (me->GetVictim())
me->CastSpell(me->GetVictim(), 71003, false);
events.Repeat(15s, 30s);
break;
case 5:
if (me->GetVictim())
me->CastSpell(me->GetVictim(), 70864, false);
events.Repeat(8s, 12s);
break;
case 6:
Talk(0);
me->CastSpell(me, SPELL_SAC_EMERGE, true);
break;
}
DoMeleeAttackIfReady();
}
};
};
class npc_spiritual_insight : public CreatureScript
{
public:
npc_spiritual_insight() : CreatureScript("npc_spiritual_insight") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_spiritual_insightAI (pCreature);
}
struct npc_spiritual_insightAI : public NullCreatureAI
{
npc_spiritual_insightAI(Creature* c) : NullCreatureAI(c) {}
uint8 GetSpeachId()
{
if (me->GetDistance2d(2686, 934) < 2.0f)
return 0;
if (me->GetDistance2d(3097, 1037) < 2.0f)
return 1;
if (me->GetDistance2d(3014, 1321) < 2.0f)
return 2;
if (me->GetDistance2d(2854, 1514) < 2.0f)
return 3;
if (me->GetDistance2d(3129, 1556) < 2.0f)
return 4;
return 5;
}
void IsSummonedBy(WorldObject* summoner) override
{
if (!summoner || !summoner->IsPlayer())
return;
uint8 id = GetSpeachId();
std::string const& text = sCreatureTextMgr->GetLocalizedChatString(me->GetEntry(), 0, id, 0, LOCALE_enUS);
WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_MONSTER_WHISPER, LANG_UNIVERSAL, me->GetGUID(), summoner->GetGUID(), text, CHAT_TAG_NONE, "Toalu'u the Mystic");
summoner->ToPlayer()->SendDirectMessage(&data);
if (id == 1)
if (Aura* aura = summoner->ToUnit()->GetAura(47189)) // Transform Aura
aura->SetDuration(aura->GetDuration() - MINUTE * IN_MILLISECONDS);
}
};
};
/*#####
# npc_commander_eligor_dawnbringer
#####*/
enum CommanderEligorDawnbringer
{
MODEL_IMAGE_OF_KELTHUZAD = 24787, // Image of Kel'Thuzad
MODEL_IMAGE_OF_SAPPHIRON = 24788, // Image of Sapphiron
MODEL_IMAGE_OF_RAZUVIOUS = 24799, // Image of Razuvious
MODEL_IMAGE_OF_GOTHIK = 24804, // Image of Gothik
MODEL_IMAGE_OF_THANE = 24802, // Image of Thane Korth'azz
MODEL_IMAGE_OF_BLAUMEUX = 24794, // Image of Lady Blaumeux
MODEL_IMAGE_OF_ZELIEK = 24800, // Image of Sir Zeliek
MODEL_IMAGE_OF_PATCHWERK = 24798, // Image of Patchwerk
MODEL_IMAGE_OF_GROBBULUS = 24792, // Image of Grobbulus
MODEL_IMAGE_OF_THADDIUS = 24801, // Image of Thaddius
MODEL_IMAGE_OF_GLUTH = 24803, // Image of Gluth
MODEL_IMAGE_OF_ANUBREKHAN = 24789, // Image of Anub'rekhan
MODEL_IMAGE_OF_FAERLINA = 24790, // Image of Faerlina
MODEL_IMAGE_OF_MAEXXNA = 24796, // Image of Maexxna
MODEL_IMAGE_OF_NOTH = 24797, // Image of Noth
MODEL_IMAGE_OF_HEIGAN = 24793, // Image of Heigan
MODEL_IMAGE_OF_LOATHEB = 24795, // Image of Loatheb
NPC_IMAGE_OF_KELTHUZAD = 27766, // Image of Kel'Thuzad
NPC_IMAGE_OF_SAPPHIRON = 27767, // Image of Sapphiron
NPC_IMAGE_OF_RAZUVIOUS = 27768, // Image of Razuvious
NPC_IMAGE_OF_GOTHIK = 27769, // Image of Gothik
NPC_IMAGE_OF_THANE = 27770, // Image of Thane Korth'azz
NPC_IMAGE_OF_BLAUMEUX = 27771, // Image of Lady Blaumeux
NPC_IMAGE_OF_ZELIEK = 27772, // Image of Sir Zeliek
NPC_IMAGE_OF_PATCHWERK = 27773, // Image of Patchwerk
NPC_IMAGE_OF_GROBBULUS = 27774, // Image of Grobbulus
NPC_IMAGE_OF_THADDIUS = 27775, // Image of Thaddius
NPC_IMAGE_OF_GLUTH = 27782, // Image of Gluth
NPC_IMAGE_OF_ANUBREKHAN = 27776, // Image of Anub'rekhan
NPC_IMAGE_OF_FAERLINA = 27777, // Image of Faerlina
NPC_IMAGE_OF_MAEXXNA = 27778, // Image of Maexxna
NPC_IMAGE_OF_NOTH = 27779, // Image of Noth
NPC_IMAGE_OF_HEIGAN = 27780, // Image of Heigan
NPC_IMAGE_OF_LOATHEB = 27781, // Image of Loatheb
NPC_INFANTRYMAN = 27160, // Add in case I randomize the spawning
NPC_SENTINAL = 27162,
NPC_BATTLE_MAGE = 27164,
// Five platforms to choose from
SAY_PINNACLE = 0,
SAY_DEATH_KNIGHT_WING = 1,
SAY_ABOMINATION_WING = 2,
SAY_SPIDER_WING = 3,
SAY_PLAGUE_WING = 4,
// Used in all talks
SAY_TALK_COMPLETE = 5,
// Pinnacle of Naxxramas
SAY_SAPPHIRON = 6,
SAY_KELTHUZAD_1 = 7,
SAY_KELTHUZAD_2 = 8,
SAY_KELTHUZAD_3 = 9,
// Death knight wing of Naxxramas
SAY_RAZUVIOUS = 10,
SAY_GOTHIK = 11,
SAY_DEATH_KNIGHTS_1 = 12,
SAY_DEATH_KNIGHTS_2 = 13,
SAY_DEATH_KNIGHTS_3 = 14,
SAY_DEATH_KNIGHTS_4 = 15,
// Blighted abomination wing of Naxxramas
SAY_PATCHWERK = 16,
SAY_GROBBULUS = 17,
SAY_GLUTH = 18,
SAY_THADDIUS = 19,
// Accursed spider wing of Naxxramas
SAY_ANUBREKHAN = 20,
SAY_FAERLINA = 21,
SAY_MAEXXNA = 22,
// Dread plague wing of Naxxramas
SAY_NOTH = 23,
SAY_HEIGAN_1 = 24,
SAY_HEIGAN_2 = 25,
SAY_LOATHEB = 26,
SPELL_HEROIC_IMAGE_CHANNEL = 49519,
EVENT_START_RANDOM = 1,
EVENT_MOVE_TO_POINT = 2,
EVENT_TALK_COMPLETE = 3,
EVENT_GET_TARGETS = 4,
EVENT_KELTHUZAD_2 = 5,
EVENT_KELTHUZAD_3 = 6,
EVENT_DEATH_KNIGHTS_2 = 7,
EVENT_DEATH_KNIGHTS_3 = 8,
EVENT_DEATH_KNIGHTS_4 = 9,
EVENT_HEIGAN_2 = 10
};
uint32 const AudienceMobs[3] = { NPC_INFANTRYMAN, NPC_SENTINAL, NPC_BATTLE_MAGE };
Position const PosTalkLocations[6] =
{
{ 3805.453f, -682.9075f, 222.2917f, 2.793398f }, // Pinnacle of Naxxramas
{ 3807.508f, -691.0882f, 221.9688f, 2.094395f }, // Death knight wing of Naxxramas
{ 3797.228f, -690.3555f, 222.5019f, 1.134464f }, // Blighted abomination wing of Naxxramas
{ 3804.038f, -672.3098f, 222.5019f, 4.578917f }, // Accursed spider wing of Naxxramas
{ 3815.097f, -680.2596f, 221.9777f, 2.86234f }, // Dread plague wing of Naxxramas
{ 3798.05f, -680.611f, 222.9825f, 6.038839f }, // Home
};
class npc_commander_eligor_dawnbringer : public CreatureScript
{
public:
npc_commander_eligor_dawnbringer() : CreatureScript("npc_commander_eligor_dawnbringer") {}
struct npc_commander_eligor_dawnbringerAI : public ScriptedAI
{
npc_commander_eligor_dawnbringerAI(Creature* creature) : ScriptedAI(creature)
{
talkWing = 0;
}
void Reset() override
{
talkWing = 0;
for (uint8 i = 0; i < 10; ++i)
audienceList[i].Clear();
for (uint8 i = 0; i < 5; ++i)
imageList[i].Clear();
_events.ScheduleEvent(EVENT_GET_TARGETS, 5s);
_events.ScheduleEvent(EVENT_START_RANDOM, 20s);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE)
{
if (id == 1)
{
me->SetFacingTo(PosTalkLocations[talkWing].GetOrientation());
TurnAudience();
switch (talkWing)
{
case 0: // Pinnacle of Naxxramas
{
switch (urand (0, 1))
{
case 0:
ChangeImage(NPC_IMAGE_OF_KELTHUZAD, MODEL_IMAGE_OF_KELTHUZAD, SAY_KELTHUZAD_1);
_events.ScheduleEvent(EVENT_KELTHUZAD_2, 8s);
break;
case 1:
ChangeImage(NPC_IMAGE_OF_SAPPHIRON, MODEL_IMAGE_OF_SAPPHIRON, SAY_SAPPHIRON);
break;
}
}
break;
case 1: // Death knight wing of Naxxramas
{
switch (urand (0, 2))
{
case 0:
ChangeImage(NPC_IMAGE_OF_RAZUVIOUS, MODEL_IMAGE_OF_RAZUVIOUS, SAY_RAZUVIOUS);
break;
case 1:
ChangeImage(NPC_IMAGE_OF_GOTHIK, MODEL_IMAGE_OF_GOTHIK, SAY_GOTHIK);
break;
case 2:
ChangeImage(NPC_IMAGE_OF_THANE, MODEL_IMAGE_OF_THANE, SAY_DEATH_KNIGHTS_1);
_events.ScheduleEvent(EVENT_DEATH_KNIGHTS_2, 10s);
break;
}
}
break;
case 2: // Blighted abomination wing of Naxxramas
{
switch (urand (0, 3))
{
case 0:
ChangeImage(NPC_IMAGE_OF_PATCHWERK, MODEL_IMAGE_OF_PATCHWERK, SAY_PATCHWERK);
break;
case 1:
ChangeImage(NPC_IMAGE_OF_GROBBULUS, MODEL_IMAGE_OF_GROBBULUS, SAY_GROBBULUS);
break;
case 2:
ChangeImage(NPC_IMAGE_OF_THADDIUS, MODEL_IMAGE_OF_THADDIUS, SAY_THADDIUS);
break;
case 3:
ChangeImage(NPC_IMAGE_OF_GLUTH, MODEL_IMAGE_OF_GLUTH, SAY_GLUTH);
break;
}
}
break;
case 3: // Accursed spider wing of Naxxramas
{
switch (urand (0, 2))
{
case 0:
ChangeImage(NPC_IMAGE_OF_ANUBREKHAN, MODEL_IMAGE_OF_ANUBREKHAN, SAY_ANUBREKHAN);
break;
case 1:
ChangeImage(NPC_IMAGE_OF_FAERLINA, MODEL_IMAGE_OF_FAERLINA, SAY_FAERLINA);
break;
case 2:
ChangeImage(NPC_IMAGE_OF_MAEXXNA, MODEL_IMAGE_OF_MAEXXNA, SAY_MAEXXNA);
break;
}
}
break;
case 4: // Dread plague wing of Naxxramas
{
switch (urand (0, 2))
{
case 0:
ChangeImage(NPC_IMAGE_OF_NOTH, MODEL_IMAGE_OF_NOTH, SAY_NOTH);
break;
case 1:
ChangeImage(NPC_IMAGE_OF_HEIGAN, MODEL_IMAGE_OF_HEIGAN, SAY_HEIGAN_1);
_events.ScheduleEvent(EVENT_HEIGAN_2, 8s);
break;
case 2:
ChangeImage(NPC_IMAGE_OF_LOATHEB, MODEL_IMAGE_OF_LOATHEB, SAY_LOATHEB);
break;
}
}
break;
case 5: // Home
_events.ScheduleEvent(EVENT_START_RANDOM, 30s);
break;
}
}
}
}
void StoreTargets()
{
uint8 creturesCount = 0;
for (uint8 ii = 0; ii < 3; ++ii)
{
std::list creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, AudienceMobs[ii], 15.0f);
for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
{
if (Creature* creature = *itr)
{
audienceList[creturesCount] = creature->GetGUID();
++creturesCount;
}
}
}
if (Creature* creature = me->FindNearestCreature(NPC_IMAGE_OF_KELTHUZAD, 20.0f, true))
imageList[0] = creature->GetGUID();
if (Creature* creature = me->FindNearestCreature(NPC_IMAGE_OF_RAZUVIOUS, 20.0f, true))
imageList[1] = creature->GetGUID();
if (Creature* creature = me->FindNearestCreature(NPC_IMAGE_OF_PATCHWERK, 20.0f, true))
imageList[2] = creature->GetGUID();
if (Creature* creature = me->FindNearestCreature(NPC_IMAGE_OF_ANUBREKHAN, 20.0f, true))
imageList[3] = creature->GetGUID();
if (Creature* creature = me->FindNearestCreature(NPC_IMAGE_OF_NOTH, 20.0f, true))
imageList[4] = creature->GetGUID();
}
void ChangeImage(uint32 entry, uint32 model, uint8 text)
{
if (Creature* creature = ObjectAccessor::GetCreature(*me, imageList[talkWing]))
{
Talk(text);
creature->SetEntry(entry);
creature->SetDisplayId(model);
creature->CastSpell(creature, SPELL_HEROIC_IMAGE_CHANNEL);
_events.ScheduleEvent(EVENT_TALK_COMPLETE, 40s);
}
}
void TurnAudience()
{
for (uint8 i = 0; i < 10; ++i)
{
if (Creature* creature = ObjectAccessor::GetCreature(*me, audienceList[i]))
creature->SetFacingToObject(me);
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_START_RANDOM:
talkWing = urand (0, 4);
Talk(talkWing);
_events.ScheduleEvent(EVENT_MOVE_TO_POINT, 8s);
break;
case EVENT_MOVE_TO_POINT:
me->SetWalk(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(1, PosTalkLocations[talkWing].m_positionX, PosTalkLocations[talkWing].m_positionY, PosTalkLocations[talkWing].m_positionZ);
break;
case EVENT_TALK_COMPLETE:
talkWing = 5;
Talk(talkWing);
_events.ScheduleEvent(EVENT_MOVE_TO_POINT, 5s);
break;
case EVENT_GET_TARGETS:
StoreTargets();
break;
case EVENT_KELTHUZAD_2:
Talk(SAY_KELTHUZAD_2);
_events.ScheduleEvent(EVENT_KELTHUZAD_3, 8s);
break;
case EVENT_KELTHUZAD_3:
Talk(SAY_KELTHUZAD_3);
break;
case EVENT_DEATH_KNIGHTS_2:
Talk(SAY_DEATH_KNIGHTS_2);
if (Creature* creature = ObjectAccessor::GetCreature(*me, imageList[talkWing]))
{
creature->SetEntry(NPC_IMAGE_OF_BLAUMEUX);
creature->SetDisplayId(MODEL_IMAGE_OF_BLAUMEUX);
}
_events.ScheduleEvent(EVENT_DEATH_KNIGHTS_3, 10s);
break;
case EVENT_DEATH_KNIGHTS_3:
Talk(SAY_DEATH_KNIGHTS_3);
if (Creature* creature = ObjectAccessor::GetCreature(*me, imageList[talkWing]))
{
creature->SetEntry(NPC_IMAGE_OF_ZELIEK);
creature->SetDisplayId(MODEL_IMAGE_OF_ZELIEK);
}
_events.ScheduleEvent(EVENT_DEATH_KNIGHTS_4, 10s);
break;
case EVENT_DEATH_KNIGHTS_4:
Talk(SAY_DEATH_KNIGHTS_4);
break;
case EVENT_HEIGAN_2:
Talk(SAY_HEIGAN_2);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
ObjectGuid audienceList[10];
ObjectGuid imageList[5];
uint8 talkWing;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_commander_eligor_dawnbringerAI(creature);
}
};
/*######
## Quest Strengthen the Ancients (12096|12092)
######*/
enum StrengthenAncientsMisc
{
SAY_WALKER_FRIENDLY = 0,
SAY_WALKER_ENEMY = 1,
SPELL_CREATE_ITEM_BARK = 47550,
};
class spell_q12096_q12092_dummy : public SpellScript
{
PrepareSpellScript(spell_q12096_q12092_dummy);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_CREATE_ITEM_BARK });
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
uint32 roll = rand() % 2;
Creature* tree = GetHitCreature();
Player* player = GetCaster()->ToPlayer();
if (!tree || !player)
return;
tree->RemoveNpcFlag(UNIT_NPC_FLAG_SPELLCLICK);
if (roll == 1) // friendly version
{
tree->CastSpell(player, SPELL_CREATE_ITEM_BARK);
tree->AI()->Talk(SAY_WALKER_FRIENDLY, player);
tree->DespawnOrUnsummon(1s);
}
else if (roll == 0) // enemy version
{
tree->AI()->Talk(SAY_WALKER_ENEMY, player);
tree->SetFaction(FACTION_MONSTER);
tree->Attack(player, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_dummy::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
/*#####
# npc_torturer_lecraft
#####*/
enum TorturerLeCraft
{
SPELL_HEMORRHAGE = 30478,
SPELL_KIDNEY_SHOT = 30621,
SPELL_HIGH_EXECUTORS_BRANDING_IRON = 48603,
NPC_TORTURER_LECRAFT = 27394,
EVENT_HEMORRHAGE = 1,
EVENT_KIDNEY_SHOT = 2,
SAY_AGGRO = 0
};
class npc_torturer_lecraft : public CreatureScript
{
public:
npc_torturer_lecraft() : CreatureScript("npc_torturer_lecraft") {}
struct npc_torturer_lecraftAI : public ScriptedAI
{
npc_torturer_lecraftAI(Creature* creature) : ScriptedAI(creature)
{
_playerGUID.Clear();
}
void Reset() override
{
_textCounter = 1;
_playerGUID.Clear();
_events.Reset();
}
void JustEngagedWith(Unit* who) override
{
_events.ScheduleEvent(EVENT_HEMORRHAGE, 5s, 8s);
_events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12s, 15s);
if (Player* player = who->ToPlayer())
Talk (SAY_AGGRO, player);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (spell->Id != SPELL_HIGH_EXECUTORS_BRANDING_IRON)
return;
if (Player* player = caster->ToPlayer())
{
if (_textCounter == 1)
_playerGUID = player->GetGUID();
if (_playerGUID != player->GetGUID())
return;
Talk(_textCounter, player);
if (_textCounter == 5)
player->KilledMonsterCredit(NPC_TORTURER_LECRAFT);
++_textCounter;
if (_textCounter == 13)
_textCounter = 6;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_HEMORRHAGE:
DoCastVictim(SPELL_HEMORRHAGE);
_events.ScheduleEvent(EVENT_HEMORRHAGE, 12s, 168s);
break;
case EVENT_KIDNEY_SHOT:
DoCastVictim(SPELL_KIDNEY_SHOT);
_events.ScheduleEvent(EVENT_KIDNEY_SHOT, 20s, 26s);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
EventMap _events;
uint8 _textCounter;
ObjectGuid _playerGUID;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_torturer_lecraftAI(creature);
}
};
// 47447 - Corrosive Spit
class spell_dragonblight_corrosive_spit : public AuraScript
{
PrepareAuraScript(spell_dragonblight_corrosive_spit);
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
}
void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (GetTarget()->HasAura(aurEff->GetSpellInfo()->GetEffect(EFFECT_0).CalcValue()))
GetAura()->Remove();
}
void PeriodicTick(AuraEffect const* aurEff)
{
if (GetTarget()->HasAura(aurEff->GetSpellInfo()->GetEffect(EFFECT_0).CalcValue()))
{
PreventDefaultAction();
GetAura()->Remove();
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_dragonblight_corrosive_spit::AfterApply, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dragonblight_corrosive_spit::PeriodicTick, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
}
};
// 48297 - Hand Over Reins
enum HandOverReins
{
SPELL_ONSLAUGHT_RIDING_CROP = 48290
};
class spell_handover_reins : public SpellScript
{
PrepareSpellScript(spell_handover_reins);
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
GetCaster()->RemoveAura(SPELL_ONSLAUGHT_RIDING_CROP);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_handover_reins::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
enum FlameFurySpells
{
SPELL_FLAME_FURY_1 = 50351,
SPELL_FLAME_FURY_2 = 50353,
SPELL_FLAME_FURY_3 = 50354,
SPELL_FLAME_FURY_4 = 50355,
SPELL_FLAME_FURY_5 = 50357
};
// 50348 - Flame Fury
class spell_dragonblight_flame_fury : public AuraScript
{
PrepareAuraScript(spell_dragonblight_flame_fury);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(spellIds);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* owner = GetUnitOwner())
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && !owner->IsAlive())
owner->CastSpell(owner, Acore::Containers::SelectRandomContainerElement(spellIds), true);
}
private:
std::array const spellIds = { SPELL_FLAME_FURY_1, SPELL_FLAME_FURY_2, SPELL_FLAME_FURY_3, SPELL_FLAME_FURY_4, SPELL_FLAME_FURY_5 };
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_dragonblight_flame_fury::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
}
};
enum DevourGhoulSpells
{
SPELL_DEVOUR_GHOUL_RIDE_VEHICLE = 50437,
SPELL_DEVOUR_PERIODIC = 50432,
SPELL_NOURISHMENT = 50443
};
// 50430 - Devour Ghoul
class spell_dragonblight_devour_ghoul: public SpellScript
{
PrepareSpellScript(spell_dragonblight_devour_ghoul);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DEVOUR_GHOUL_RIDE_VEHICLE });
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
if (GetCaster())
{
GetHitUnit()->CastSpell(GetCaster(), SPELL_DEVOUR_GHOUL_RIDE_VEHICLE, true);
GetCaster()->CastSpell(GetHitUnit(), SPELL_DEVOUR_PERIODIC, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_dragonblight_devour_ghoul::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 50432 - Devour Ghoul
class spell_dragonblight_devour_ghoul_periodic : public AuraScript
{
PrepareAuraScript(spell_dragonblight_devour_ghoul_periodic);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_NOURISHMENT });
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetCaster())
GetCaster()->CastSpell(GetCaster(), SPELL_NOURISHMENT, true);
if (GetUnitOwner() && GetUnitOwner()->ToCreature())
{
GetUnitOwner()->ExitVehicle();
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2s);
}
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_dragonblight_devour_ghoul_periodic::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_dragonblight()
{
new npc_conversing_with_the_depths_trigger();
new go_the_pearl_of_the_depths();
new npc_hourglass_of_eternity();
new npc_future_you();
new npc_mindless_ghoul();
new npc_injured_7th_legion_soldier();
RegisterCreatureAI(npc_wintergarde_gryphon);
RegisterSpellScript(spell_q12237_rescue_villager);
RegisterSpellScript(spell_q12237_drop_off_villager);
RegisterSpellScript(spell_call_wintergarde_gryphon);
new npc_heated_battle();
RegisterSpellScript(spell_q12478_frostmourne_cavern);
RegisterSpellScript(spell_q12243_fire_upon_the_waters_aura);
new npc_q24545_lich_king();
new at_q24545_frostmourne_cavern();
new npc_q24545_wretched_ghoul();
RegisterSpellScript(spell_q24545_aod_special);
new npc_q24545_vegard_dummy();
new npc_q24545_vegard();
new npc_spiritual_insight();
new npc_commander_eligor_dawnbringer();
RegisterSpellScript(spell_q12096_q12092_dummy);
new npc_torturer_lecraft();
RegisterSpellScript(spell_dragonblight_corrosive_spit);
RegisterSpellScript(spell_handover_reins);
RegisterSpellScript(spell_dragonblight_flame_fury);
RegisterSpellScript(spell_dragonblight_devour_ghoul);
RegisterSpellScript(spell_dragonblight_devour_ghoul_periodic);
}