mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-24 22:26:22 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -157,7 +157,6 @@ void AddSC_isle_of_queldanas();
|
||||
void AddSC_redridge_mountains();
|
||||
void AddSC_silverpine_forest();
|
||||
void AddSC_stormwind_city();
|
||||
void AddSC_stranglethorn_vale();
|
||||
void AddSC_tirisfal_glades();
|
||||
void AddSC_undercity();
|
||||
void AddSC_western_plaguelands();
|
||||
@@ -310,7 +309,6 @@ void AddEasternKingdomsScripts()
|
||||
AddSC_redridge_mountains();
|
||||
AddSC_silverpine_forest();
|
||||
AddSC_stormwind_city();
|
||||
AddSC_stranglethorn_vale();
|
||||
AddSC_tirisfal_glades();
|
||||
AddSC_undercity();
|
||||
AddSC_western_plaguelands();
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* 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 Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 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 Affero 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Stranglethorn_Vale
|
||||
SD%Complete: 100
|
||||
SDComment: Quest support: 592
|
||||
SDCategory: Stranglethorn Vale
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
npc_yenniku
|
||||
EndContentData */
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellInfo.h"
|
||||
|
||||
/*######
|
||||
## npc_yenniku
|
||||
######*/
|
||||
|
||||
class npc_yenniku : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_yenniku() : CreatureScript("npc_yenniku") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_yennikuAI(creature);
|
||||
}
|
||||
|
||||
struct npc_yennikuAI : public ScriptedAI
|
||||
{
|
||||
npc_yennikuAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
bReset = false;
|
||||
}
|
||||
|
||||
uint32 Reset_Timer;
|
||||
bool bReset;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Reset_Timer = 0;
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spell) override
|
||||
{
|
||||
if (bReset || spell->Id != 3607)
|
||||
return;
|
||||
|
||||
if (Player* player = caster->ToPlayer())
|
||||
{
|
||||
if (player->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE) //Yenniku's Release
|
||||
{
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);
|
||||
me->CombatStop(); //stop combat
|
||||
me->GetThreatMgr().ClearAllThreat(); //unsure of this
|
||||
me->SetFaction(FACTION_HORDE_GENERIC);
|
||||
|
||||
bReset = true;
|
||||
Reset_Timer = 60000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (bReset)
|
||||
{
|
||||
if (Reset_Timer <= diff)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
bReset = false;
|
||||
me->SetFaction(FACTION_TROLL_BLOODSCALP);
|
||||
return;
|
||||
}
|
||||
|
||||
Reset_Timer -= diff;
|
||||
|
||||
if (me->IsInCombat() && me->GetVictim())
|
||||
{
|
||||
if (Player* player = me->GetVictim()->ToPlayer())
|
||||
{
|
||||
if (player->GetTeamId() == TEAM_HORDE)
|
||||
{
|
||||
me->CombatStop();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
##
|
||||
######*/
|
||||
|
||||
void AddSC_stranglethorn_vale()
|
||||
{
|
||||
new npc_yenniku();
|
||||
}
|
||||
@@ -46,43 +46,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_midsummer_bonfire : public ScriptedAI
|
||||
{
|
||||
npc_midsummer_bonfire(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
me->IsAIEnabled = true;
|
||||
goGUID.Clear();
|
||||
if (GameObject* go = me->SummonGameObject(GO_MIDSUMMER_BONFIRE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0))
|
||||
{
|
||||
goGUID = go->GetGUID();
|
||||
me->RemoveGameObject(go, false);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid goGUID;
|
||||
|
||||
void SpellHit(Unit*, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (!goGUID)
|
||||
return;
|
||||
|
||||
// Extinguish fire
|
||||
if (spellInfo->Id == SPELL_STAMP_OUT_BONFIRE)
|
||||
{
|
||||
if (GameObject* go = ObjectAccessor::GetGameObject(*me, goGUID))
|
||||
go->SetPhaseMask(2, true);
|
||||
}
|
||||
else if (spellInfo->Id == SPELL_LIGHT_BONFIRE)
|
||||
{
|
||||
if (GameObject* go = ObjectAccessor::GetGameObject(*me, goGUID))
|
||||
{
|
||||
go->SetPhaseMask(1, true);
|
||||
go->SendCustomAnim(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_midsummer_torch_target : public ScriptedAI
|
||||
{
|
||||
npc_midsummer_torch_target(Creature* creature) : ScriptedAI(creature)
|
||||
@@ -542,7 +505,6 @@ void AddSC_event_midsummer_scripts()
|
||||
{
|
||||
// NPCs
|
||||
new go_midsummer_bonfire();
|
||||
RegisterCreatureAI(npc_midsummer_bonfire);
|
||||
RegisterCreatureAI(npc_midsummer_torch_target);
|
||||
|
||||
// Spells
|
||||
|
||||
@@ -66,231 +66,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum WanderingShay
|
||||
{
|
||||
QUEST_WANDERING_SHAY = 2845,
|
||||
|
||||
SPELL_SHAY_BELL = 11402,
|
||||
|
||||
NPC_ROCKBITER = 7765,
|
||||
|
||||
TALK_0 = 0,
|
||||
TALK_1 = 1,
|
||||
TALK_2 = 2,
|
||||
TALK_3 = 3,
|
||||
TALK_4 = 4,
|
||||
|
||||
EVENT_WANDERING_START = 1,
|
||||
EVENT_WANDERING_TALK = 2,
|
||||
EVENT_WANDERING_RANDOM = 3,
|
||||
EVENT_FINAL_TALK = 4,
|
||||
EVENT_CHECK_FOLLOWER = 5
|
||||
};
|
||||
|
||||
class npc_shay_leafrunner : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_shay_leafrunner() : CreatureScript("npc_shay_leafrunner") {}
|
||||
|
||||
struct npc_shay_leafrunnerAI : public ScriptedAI
|
||||
{
|
||||
npc_shay_leafrunnerAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
me->SetImmuneToAll(true);
|
||||
me->RestoreFaction();
|
||||
|
||||
_events.Reset();
|
||||
_playerGUID.Clear();
|
||||
_rockbiterGUID.Clear();
|
||||
}
|
||||
|
||||
void JustRespawned() override
|
||||
{
|
||||
InitializeAI();
|
||||
me->SetHomePosition(me->GetPosition());
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* target) override
|
||||
{
|
||||
if (!_playerGUID || target->GetEntry() != NPC_ROCKBITER || !me->IsInRange(target, 0.f, 10.f))
|
||||
{
|
||||
if (!me->IsInCombat() && !me->GetVictim())
|
||||
{
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
{
|
||||
if (Unit* victim = player->GetVictim())
|
||||
{
|
||||
if (me->CanStartAttack(victim))
|
||||
{
|
||||
AttackStart(victim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_rockbiterGUID = target->GetGUID();
|
||||
|
||||
Talk(TALK_4, target);
|
||||
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
{
|
||||
player->GroupEventHappens(QUEST_WANDERING_SHAY, me);
|
||||
}
|
||||
|
||||
_events.CancelEvent(EVENT_WANDERING_START);
|
||||
_events.ScheduleEvent(EVENT_FINAL_TALK, 5s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
_EnterEvadeMode(why);
|
||||
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
{
|
||||
me->GetMotionMaster()->MoveFollow(player, 3.f, M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
void FailQuest(Player* player, bool despawn)
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
player->FailQuest(QUEST_WANDERING_SHAY);
|
||||
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
|
||||
{
|
||||
if (Player* member = groupRef->GetSource())
|
||||
{
|
||||
if (member->GetGUID() != player->GetGUID())
|
||||
{
|
||||
member->FailQuest(QUEST_WANDERING_SHAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (despawn)
|
||||
{
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
{
|
||||
FailQuest(player, false);
|
||||
}
|
||||
}
|
||||
|
||||
void sQuestAccept(Player* player, Quest const* quest) override
|
||||
{
|
||||
if (quest->GetQuestId() == QUEST_WANDERING_SHAY)
|
||||
{
|
||||
_playerGUID = player->GetGUID();
|
||||
|
||||
Talk(TALK_0, player);
|
||||
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
|
||||
me->GetMotionMaster()->MoveFollow(player, 3.f, M_PI);
|
||||
|
||||
_events.ScheduleEvent(EVENT_WANDERING_START, 40s, 70s);
|
||||
_events.ScheduleEvent(EVENT_CHECK_FOLLOWER, 30s);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id == SPELL_SHAY_BELL)
|
||||
{
|
||||
_playerGUID = caster->GetGUID();
|
||||
|
||||
Talk(TALK_1, caster);
|
||||
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->GetMotionMaster()->MoveFollow(caster, 3.f, M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (UpdateVictim())
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
return;
|
||||
}
|
||||
|
||||
_events.Update(diff);
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_WANDERING_START:
|
||||
{
|
||||
Position pos = me->GetFirstCollisionPosition(15.f, rand_norm() * static_cast<float>(2 * M_PI));
|
||||
me->GetMotionMaster()->MovePoint(0, pos);
|
||||
Talk(TALK_2);
|
||||
_events.ScheduleEvent(EVENT_WANDERING_START, 60s, 70s);
|
||||
_events.ScheduleEvent(EVENT_WANDERING_TALK, 3s);
|
||||
_events.ScheduleEvent(EVENT_WANDERING_RANDOM, 8s);
|
||||
break;
|
||||
}
|
||||
case EVENT_WANDERING_TALK:
|
||||
Talk(TALK_3);
|
||||
break;
|
||||
case EVENT_WANDERING_RANDOM:
|
||||
me->SetHomePosition(me->GetPosition());
|
||||
me->GetMotionMaster()->MoveRandom(15.f);
|
||||
break;
|
||||
case EVENT_FINAL_TALK:
|
||||
if (Creature* robckbiter = ObjectAccessor::GetCreature(*me, _rockbiterGUID))
|
||||
{
|
||||
robckbiter->AI()->Talk(TALK_0, me);
|
||||
}
|
||||
me->DespawnOrUnsummon(10 * IN_MILLISECONDS);
|
||||
break;
|
||||
case EVENT_CHECK_FOLLOWER:
|
||||
{
|
||||
Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID);
|
||||
if (!player || !player->IsAlive() || !me->IsInRange(player, 0.f, 50.f))
|
||||
{
|
||||
FailQuest(player, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _playerGUID;
|
||||
ObjectGuid _rockbiterGUID;
|
||||
EventMap _events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_shay_leafrunnerAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_feralas()
|
||||
{
|
||||
new spell_gordunni_trap();
|
||||
new npc_shay_leafrunner();
|
||||
}
|
||||
|
||||
@@ -97,9 +97,6 @@ public:
|
||||
|
||||
if (m_pInstance)
|
||||
m_pInstance->SetData(TYPE_IONAR, NOT_STARTED);
|
||||
|
||||
// Ionar is immune to nature damage
|
||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
}
|
||||
|
||||
void ScheduleEvents(bool spark)
|
||||
|
||||
@@ -74,7 +74,10 @@ struct boss_exarch_maladaar : public BossAI
|
||||
_Reset();
|
||||
ScheduleHealthCheckEvent(25, [&] {
|
||||
Talk(SAY_SUMMON);
|
||||
DoCastSelf(SPELL_SUMMON_AVATAR);
|
||||
scheduler.Schedule(100ms, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_AVATAR);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -133,6 +136,11 @@ struct boss_exarch_maladaar : public BossAI
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* /*creature*/) override
|
||||
{
|
||||
// Override JustSummoned() so we don't despawn the Avatar.
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
|
||||
@@ -208,25 +208,27 @@ class spell_murmur_thundering_storm : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 33711/38794 - Murmur's Touch
|
||||
class spell_murmur_touch : public AuraScript
|
||||
// 33686 - Shockwave (Murmur's Touch final explosion)
|
||||
class spell_shockwave_knockback : public SpellScript
|
||||
{
|
||||
PrepareAuraScript(spell_murmur_touch);
|
||||
PrepareSpellScript(spell_shockwave_knockback);
|
||||
|
||||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
return ValidateSpellInfo({ SPELL_SHOCKWAVE_SERVERSIDE });
|
||||
}
|
||||
|
||||
void HandleOnHit()
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
if (GetTarget())
|
||||
{
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_SHOCKWAVE_SERVERSIDE, true);
|
||||
}
|
||||
target->CastSpell(target, SPELL_SHOCKWAVE_SERVERSIDE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_murmur_touch::HandleAfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
OnHit += SpellHitFn(spell_shockwave_knockback::HandleOnHit);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -252,6 +254,6 @@ void AddSC_boss_murmur()
|
||||
{
|
||||
RegisterShadowLabyrinthCreatureAI(boss_murmur);
|
||||
RegisterSpellScript(spell_murmur_thundering_storm);
|
||||
RegisterSpellScript(spell_murmur_touch);
|
||||
RegisterSpellScript(spell_shockwave_knockback);
|
||||
RegisterSpellScript(spell_murmur_sonic_boom_effect);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ enum EventSpells
|
||||
SPELL_SUMMON_COLDWAVE = 45952,
|
||||
SPELL_SUMMON_FROSTWIND = 45953,
|
||||
|
||||
SPELL_CHILLING_AURA = 46542,
|
||||
|
||||
/*
|
||||
SPELL_SUMMON_ICE_SPEAR_BUNNY= 46359, // any dest
|
||||
SPELL_ICE_SPEAR_KNOCKBACK = 46360, // src caster
|
||||
@@ -63,6 +65,11 @@ enum EventSpells
|
||||
*/
|
||||
};
|
||||
|
||||
enum CreatureIds
|
||||
{
|
||||
NPC_AHUNITE_HAILSTONE = 25755
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
{
|
||||
EVENT_EMERGE = 1,
|
||||
@@ -81,245 +88,241 @@ enum eEvents
|
||||
EVENT_SPELL_SUMMON_COLDWAVE,
|
||||
};
|
||||
|
||||
class boss_ahune : public CreatureScript
|
||||
enum Misc
|
||||
{
|
||||
public:
|
||||
boss_ahune() : CreatureScript("boss_ahune") { }
|
||||
SET_GUID_INVOKER = 1
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const override
|
||||
struct boss_ahune : public ScriptedAI
|
||||
{
|
||||
boss_ahune(Creature* c) : ScriptedAI(c), summons(me)
|
||||
{
|
||||
return GetTheSlavePensAI<boss_ahuneAI>(pCreature);
|
||||
SetCombatMovement(false);
|
||||
SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
InvokerGUID.Clear();
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_EMERGE, 12000);
|
||||
events.RescheduleEvent(EVENT_INVOKER_SAY_1, 1000);
|
||||
events.RescheduleEvent(EVENT_SUMMON_TOTEMS, 4000);
|
||||
}
|
||||
|
||||
struct boss_ahuneAI : public ScriptedAI
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
ObjectGuid InvokerGUID;
|
||||
|
||||
void StartPhase1()
|
||||
{
|
||||
boss_ahuneAI(Creature* c) : ScriptedAI(c), summons(me)
|
||||
me->CastSpell(me, SPELL_AHUNES_SHIELD, true);
|
||||
events.RescheduleEvent(EVENT_TOTEMS_ATTACK, 80000);
|
||||
events.RescheduleEvent(EVENT_SPELL_COLD_SLAP, 1200);
|
||||
events.RescheduleEvent(EVENT_SPELL_SUMMON_HAILSTONE, 2000);
|
||||
events.RescheduleEvent(EVENT_SPELL_SUMMON_COLDWAVE, 5000);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
events.Reset();
|
||||
StartPhase1();
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid guid, int32 id) override
|
||||
{
|
||||
if (id == SET_GUID_INVOKER)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
InvokerGUID.Clear();
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_EMERGE, 12000);
|
||||
events.RescheduleEvent(EVENT_INVOKER_SAY_1, 1000);
|
||||
events.RescheduleEvent(EVENT_SUMMON_TOTEMS, 4000);
|
||||
InvokerGUID = guid;
|
||||
}
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
ObjectGuid InvokerGUID;
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
bool CanBeSeen(Player const* player) override
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
if (player->IsGameMaster())
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_EMERGE:
|
||||
me->SetVisible(true);
|
||||
me->CastSpell(me, SPELL_EMERGE_0, false);
|
||||
events.RescheduleEvent(EVENT_ATTACK, 2000);
|
||||
break;
|
||||
case EVENT_SUMMON_TOTEMS:
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
DoSummon(NPC_TOTEM, TotemPos[i], 10 * 60 * 1000, TEMPSUMMON_TIMED_DESPAWN);
|
||||
break;
|
||||
case EVENT_INVOKER_SAY_1:
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
{
|
||||
return true;
|
||||
plr->Say("The Ice Stone has melted!", LANG_UNIVERSAL);
|
||||
plr->CastSpell(plr, SPELL_MAKE_BONFIRE, true);
|
||||
}
|
||||
|
||||
Group const* group = player->GetGroup();
|
||||
return group && sLFGMgr->GetDungeon(group->GetGUID()) == lfg::LFG_DUNGEON_FROST_LORD_AHUNE;
|
||||
}
|
||||
|
||||
void StartPhase1()
|
||||
{
|
||||
me->CastSpell(me, SPELL_AHUNES_SHIELD, true);
|
||||
events.RescheduleEvent(EVENT_TOTEMS_ATTACK, 80000);
|
||||
events.RescheduleEvent(EVENT_SPELL_COLD_SLAP, 1200);
|
||||
events.RescheduleEvent(EVENT_SPELL_SUMMON_HAILSTONE, 2000);
|
||||
events.RescheduleEvent(EVENT_SPELL_SUMMON_COLDWAVE, 5000);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
events.RescheduleEvent(EVENT_INVOKER_SAY_2, 2000);
|
||||
break;
|
||||
case EVENT_INVOKER_SAY_2:
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
plr->Say("Ahune, your strength grows no more!", LANG_UNIVERSAL);
|
||||
events.RescheduleEvent(EVENT_INVOKER_SAY_3, 2000);
|
||||
break;
|
||||
case EVENT_INVOKER_SAY_3:
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
plr->Say("Your frozen reign will not come to pass!", LANG_UNIVERSAL);
|
||||
break;
|
||||
case EVENT_ATTACK:
|
||||
events.Reset();
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
AttackStart(plr);
|
||||
me->SetInCombatWithZone();
|
||||
if (!me->IsInCombat())
|
||||
{
|
||||
EnterEvadeMode(EVADE_REASON_OTHER);
|
||||
return;
|
||||
}
|
||||
else
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
break;
|
||||
case EVENT_TOTEMS_ATTACK:
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
if (Creature* bunny = me->FindNearestCreature(NPC_TOTEM_BUNNY_1 + i, 150.0f, true))
|
||||
bunny->CastSpell(me, SPELL_TOTEM_BEAM, false);
|
||||
events.RescheduleEvent(EVENT_SUBMERGE, 10000);
|
||||
break;
|
||||
case EVENT_SUBMERGE:
|
||||
Talk(EMOTE_RETREAT);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->CastSpell(me, SPELL_SUBMERGE_0, true);
|
||||
me->CastSpell(me, SPELL_SELF_STUN, true);
|
||||
if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN))
|
||||
{
|
||||
c->SetHealth(me->GetHealth());
|
||||
}
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_COMBAT_EMERGE, 25000);
|
||||
events.RescheduleEvent(EVENT_EMERGE_WARNING, 20000);
|
||||
break;
|
||||
case EVENT_EMERGE_WARNING:
|
||||
Talk(EMOTE_RESURFACE);
|
||||
break;
|
||||
case EVENT_COMBAT_EMERGE:
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveAura(SPELL_SELF_STUN);
|
||||
me->CastSpell(me, SPELL_EMERGE_0, false);
|
||||
// me->CastSpell(me, SPELL_AHUNE_RESURFACES, true); // done in SummonedCreatureDespawn
|
||||
me->RemoveAura(SPELL_SUBMERGE_0);
|
||||
summons.DespawnEntry(NPC_FROZEN_CORE);
|
||||
StartPhase1();
|
||||
}
|
||||
break;
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch(events.ExecuteEvent())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_EMERGE:
|
||||
me->SetVisible(true);
|
||||
me->CastSpell(me, SPELL_EMERGE_0, false);
|
||||
events.RescheduleEvent(EVENT_ATTACK, 2000);
|
||||
break;
|
||||
case EVENT_SUMMON_TOTEMS:
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
DoSummon(NPC_TOTEM, TotemPos[i], 10 * 60 * 1000, TEMPSUMMON_TIMED_DESPAWN);
|
||||
break;
|
||||
case EVENT_INVOKER_SAY_1:
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
{
|
||||
plr->Say("The Ice Stone has melted!", LANG_UNIVERSAL);
|
||||
plr->CastSpell(plr, SPELL_MAKE_BONFIRE, true);
|
||||
}
|
||||
events.RescheduleEvent(EVENT_INVOKER_SAY_2, 2000);
|
||||
break;
|
||||
case EVENT_INVOKER_SAY_2:
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
plr->Say("Ahune, your strength grows no more!", LANG_UNIVERSAL);
|
||||
events.RescheduleEvent(EVENT_INVOKER_SAY_3, 2000);
|
||||
break;
|
||||
case EVENT_INVOKER_SAY_3:
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
plr->Say("Your frozen reign will not come to pass!", LANG_UNIVERSAL);
|
||||
break;
|
||||
case EVENT_ATTACK:
|
||||
events.Reset();
|
||||
if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID))
|
||||
AttackStart(plr);
|
||||
me->SetInCombatWithZone();
|
||||
if (!me->IsInCombat())
|
||||
{
|
||||
EnterEvadeMode(EVADE_REASON_OTHER);
|
||||
return;
|
||||
}
|
||||
else
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
break;
|
||||
case EVENT_TOTEMS_ATTACK:
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
if (Creature* bunny = me->FindNearestCreature(NPC_TOTEM_BUNNY_1 + i, 150.0f, true))
|
||||
bunny->CastSpell(me, SPELL_TOTEM_BEAM, false);
|
||||
events.RescheduleEvent(EVENT_SUBMERGE, 10000);
|
||||
break;
|
||||
case EVENT_SUBMERGE:
|
||||
Talk(EMOTE_RETREAT);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->CastSpell(me, SPELL_SUBMERGE_0, true);
|
||||
me->CastSpell(me, SPELL_SELF_STUN, true);
|
||||
if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_DESPAWN))
|
||||
{
|
||||
c->SetHealth(me->GetHealth());
|
||||
}
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_COMBAT_EMERGE, 25000);
|
||||
events.RescheduleEvent(EVENT_EMERGE_WARNING, 20000);
|
||||
break;
|
||||
case EVENT_EMERGE_WARNING:
|
||||
Talk(EMOTE_RESURFACE);
|
||||
break;
|
||||
case EVENT_COMBAT_EMERGE:
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveAura(SPELL_SELF_STUN);
|
||||
me->CastSpell(me, SPELL_EMERGE_0, false);
|
||||
// me->CastSpell(me, SPELL_AHUNE_RESURFACES, true); // done in SummonedCreatureDespawn
|
||||
me->RemoveAura(SPELL_SUBMERGE_0);
|
||||
StartPhase1();
|
||||
break;
|
||||
|
||||
case EVENT_SPELL_COLD_SLAP:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 5.0f, true))
|
||||
if (target->GetPositionZ() < me->GetPositionZ() + 6.0f)
|
||||
{
|
||||
int32 dmg = urand(5500, 6000);
|
||||
me->CastCustomSpell(target, SPELL_COLD_SLAP, &dmg, nullptr, nullptr, false);
|
||||
float x, y, z;
|
||||
target->GetNearPoint(target, x, y, z, target->GetObjectSize(), 30.0f, target->GetAngle(me->GetPositionX(), me->GetPositionY()) + M_PI);
|
||||
target->GetMotionMaster()->MoveJump(x, y, z + 20.0f, 10.0f, 20.0f);
|
||||
}
|
||||
events.RepeatEvent(1500);
|
||||
break;
|
||||
case EVENT_SPELL_SUMMON_HAILSTONE:
|
||||
{
|
||||
float dist = (float)urand(3, 10);
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false);
|
||||
events.RepeatEvent(30000);
|
||||
}
|
||||
break;
|
||||
case EVENT_SPELL_SUMMON_COLDWAVE:
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
float dist = (float)urand(3, 10);
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false);
|
||||
}
|
||||
{
|
||||
float dist = (float)urand(3, 10);
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false);
|
||||
}
|
||||
events.RepeatEvent(6000);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
me->DespawnOrUnsummon(1);
|
||||
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
if (summon && summon->GetEntry() == NPC_FROZEN_CORE)
|
||||
{
|
||||
if (summon->GetHealth() > 0)
|
||||
case EVENT_SPELL_COLD_SLAP:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 5.0f, true))
|
||||
if (target->GetPositionZ() < me->GetPositionZ() + 6.0f)
|
||||
{
|
||||
me->SetHealth(summon->GetHealth());
|
||||
summon->CastSpell(summon, SPELL_AHUNE_RESURFACES, true);
|
||||
int32 dmg = urand(5500, 6000);
|
||||
me->CastCustomSpell(target, SPELL_COLD_SLAP, &dmg, nullptr, nullptr, false);
|
||||
float x, y, z;
|
||||
target->GetNearPoint(target, x, y, z, target->GetObjectSize(), 30.0f, target->GetAngle(me->GetPositionX(), me->GetPositionY()) + M_PI);
|
||||
target->GetMotionMaster()->MoveJump(x, y, z + 20.0f, 10.0f, 20.0f);
|
||||
}
|
||||
else
|
||||
Unit::Kill(me, me, false);
|
||||
events.RepeatEvent(1500);
|
||||
break;
|
||||
case EVENT_SPELL_SUMMON_HAILSTONE:
|
||||
{
|
||||
float dist = (float)urand(3, 10);
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false);
|
||||
}
|
||||
break;
|
||||
case EVENT_SPELL_SUMMON_COLDWAVE:
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
float dist = (float)urand(3, 10);
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false);
|
||||
}
|
||||
{
|
||||
float dist = (float)urand(3, 10);
|
||||
float angle = rand_norm() * 2 * M_PI;
|
||||
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false);
|
||||
}
|
||||
events.RepeatEvent(12000);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
me->DespawnOrUnsummon(1);
|
||||
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
|
||||
if (summon->GetEntry() == NPC_AHUNITE_HAILSTONE)
|
||||
{
|
||||
// Doesn't work when cast normally or when added to
|
||||
// creature template addon. Needs further investigation.
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_CHILLING_AURA))
|
||||
{
|
||||
Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, summon, summon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
if (summon && summon->GetEntry() == NPC_FROZEN_CORE)
|
||||
{
|
||||
summons.DespawnAll();
|
||||
me->DespawnOrUnsummon(15000);
|
||||
if (GameObject* chest = me->SummonGameObject(187892, MinionSummonPos.GetPositionX(), MinionSummonPos.GetPositionY(), MinionSummonPos.GetPositionZ(), M_PI / 2, 0.0f, 0.0f, 0.0f, 0.0f, 900000000)) // loot
|
||||
me->RemoveGameObject(chest, false);
|
||||
|
||||
bool finished = false;
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
|
||||
if (Player* player = i->GetSource())
|
||||
{
|
||||
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, 25740, 1, me);
|
||||
|
||||
if (player->GetGroup() && !finished)
|
||||
{
|
||||
finished = true;
|
||||
sLFGMgr->FinishDungeon(player->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_FROST_LORD_AHUNE, me->FindMap());
|
||||
}
|
||||
}
|
||||
if (summon->GetHealth() > 0)
|
||||
{
|
||||
me->SetHealth(summon->GetHealth());
|
||||
summon->CastSpell(summon, SPELL_AHUNE_RESURFACES, true);
|
||||
}
|
||||
else
|
||||
Unit::Kill(me, me, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
summons.DespawnAll();
|
||||
me->DespawnOrUnsummon(15000);
|
||||
if (GameObject* chest = me->SummonGameObject(187892, MinionSummonPos.GetPositionX(), MinionSummonPos.GetPositionY(), MinionSummonPos.GetPositionZ(), M_PI / 2, 0.0f, 0.0f, 0.0f, 0.0f, 900000000)) // loot
|
||||
me->RemoveGameObject(chest, false);
|
||||
|
||||
bool finished = false;
|
||||
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, 25740, 1, me);
|
||||
|
||||
if (player->GetGroup() && !finished)
|
||||
{
|
||||
finished = true;
|
||||
sLFGMgr->FinishDungeon(player->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_FROST_LORD_AHUNE, me->FindMap());
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class go_ahune_ice_stone : public GameObjectScript
|
||||
@@ -331,8 +334,18 @@ public:
|
||||
{
|
||||
if (!player || !go)
|
||||
return true;
|
||||
if (!player->HasItemCount(ITEM_MAGMA_TOTEM))
|
||||
return true;
|
||||
|
||||
if (!player->IsGameMaster())
|
||||
{
|
||||
if (Group const* group = player->GetGroup())
|
||||
{
|
||||
if (sLFGMgr->GetDungeon(group->GetGUID()) != lfg::LFG_DUNGEON_FROST_LORD_AHUNE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (go->FindNearestCreature(NPC_AHUNE, 200.0f, true))
|
||||
return true;
|
||||
|
||||
@@ -345,10 +358,20 @@ public:
|
||||
{
|
||||
if (!player || !go)
|
||||
return true;
|
||||
|
||||
if (!player->IsGameMaster())
|
||||
{
|
||||
if (Group const* group = player->GetGroup())
|
||||
{
|
||||
if (sLFGMgr->GetDungeon(group->GetGUID()) != lfg::LFG_DUNGEON_FROST_LORD_AHUNE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action != GOSSIP_ACTION_INFO_DEF + 1337)
|
||||
return true;
|
||||
if (!player->HasItemCount(ITEM_MAGMA_TOTEM))
|
||||
return true;
|
||||
if (go->FindNearestCreature(NPC_AHUNE, 200.0f, true))
|
||||
return true;
|
||||
|
||||
@@ -360,7 +383,11 @@ public:
|
||||
c->SetVisible(false);
|
||||
c->SetDisplayId(AHUNE_DEFAULT_MODEL);
|
||||
c->SetFloatValue(UNIT_FIELD_COMBATREACH, 18.0f);
|
||||
CAST_AI(boss_ahune::boss_ahuneAI, c->AI())->InvokerGUID = player->GetGUID();
|
||||
if (c->AI())
|
||||
{
|
||||
c->AI()->SetGUID(player->GetGUID(), SET_GUID_INVOKER);
|
||||
}
|
||||
|
||||
if (Creature* bunny = go->SummonCreature(NPC_AHUNE_SUMMON_LOC_BUNNY, AhuneSummonPos, TEMPSUMMON_TIMED_DESPAWN, 12000))
|
||||
if (Creature* crystal_trigger = go->SummonCreature(WORLD_TRIGGER, go->GetPositionX(), go->GetPositionY(), 5.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 12000))
|
||||
crystal_trigger->CastSpell(bunny, SPELL_STARTING_BEAM, false);
|
||||
@@ -371,30 +398,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class npc_ahune_frozen_core : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_ahune_frozen_core() : CreatureScript("npc_ahune_frozen_core") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const override
|
||||
{
|
||||
return GetTheSlavePensAI<npc_ahune_frozen_coreAI>(pCreature);
|
||||
}
|
||||
|
||||
struct npc_ahune_frozen_coreAI : public NullCreatureAI
|
||||
{
|
||||
npc_ahune_frozen_coreAI(Creature* c) : NullCreatureAI(c) {}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void AddSC_boss_ahune()
|
||||
{
|
||||
new go_ahune_ice_stone();
|
||||
new boss_ahune();
|
||||
new npc_ahune_frozen_core();
|
||||
RegisterTheSlavePensCreatureAI(boss_ahune);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ enum MekgineerSteamrigger
|
||||
SPELL_SAW_BLADE = 31486,
|
||||
SPELL_ELECTRIFIED_NET = 35107,
|
||||
SPELL_ENRAGE = 26662,
|
||||
SPELL_REPAIR_N = 31532,
|
||||
SPELL_REPAIR_H = 37936,
|
||||
|
||||
SPELL_SUMMON_MECHANICS_1 = 31528,
|
||||
SPELL_SUMMON_MECHANICS_2 = 31529,
|
||||
|
||||
@@ -85,7 +85,15 @@ struct boss_swamplord_muselek : public BossAI
|
||||
|
||||
bool CanShootVictim()
|
||||
{
|
||||
return me->GetVictim() && !me->IsWithinRange(me->GetVictim(), 10.0f) && me->IsWithinLOSInMap(me->GetVictim());
|
||||
Unit* victim = me->GetVictim();
|
||||
|
||||
if (!victim || !me->IsWithinLOSInMap(victim) || !me->IsWithinRange(victim, 30.f) || me->IsWithinRange(victim, 10.f))
|
||||
{
|
||||
_canChase = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
@@ -100,6 +108,8 @@ struct boss_swamplord_muselek : public BossAI
|
||||
me->LoadEquipment(1, true);
|
||||
DoCastVictim(SPELL_SHOOT);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->StopMoving();
|
||||
_canChase = false;
|
||||
}
|
||||
else if (_canChase)
|
||||
{
|
||||
@@ -121,7 +131,7 @@ struct boss_swamplord_muselek : public BossAI
|
||||
context.Repeat(20s, 30s);
|
||||
}).Schedule(30s, 40s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, false, true))
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, false, true))
|
||||
{
|
||||
_markTarget = target->GetGUID();
|
||||
_canChase = false;
|
||||
@@ -135,6 +145,7 @@ struct boss_swamplord_muselek : public BossAI
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveForwards(me->GetVictim(), 10.0f);
|
||||
_canChase = false;
|
||||
}
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "hellfire_ramparts.h"
|
||||
|
||||
enum Says
|
||||
@@ -83,11 +84,6 @@ struct boss_vazruden_the_herald : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
{
|
||||
instance->SetBossState(DATA_VAZRUDEN, DONE);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
|
||||
@@ -105,7 +101,7 @@ struct boss_vazruden_the_herald : public BossAI
|
||||
{
|
||||
Talk(SAY_INTRO);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 85.0f, false);
|
||||
me->setActive(true);
|
||||
_JustEngagedWith();
|
||||
}
|
||||
else if (summons.size() == 0)
|
||||
{
|
||||
@@ -139,11 +135,11 @@ struct boss_vazruden_the_herald : public BossAI
|
||||
}
|
||||
};
|
||||
|
||||
struct boss_nazan : public BossAI
|
||||
struct boss_nazan : public ScriptedAI
|
||||
{
|
||||
boss_nazan(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
|
||||
boss_nazan(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
@@ -162,11 +158,11 @@ struct boss_nazan : public BossAI
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
scheduler.CancelGroup(GROUP_PHASE_2);
|
||||
scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
|
||||
scheduler.DelayAll(7s);
|
||||
_scheduler.DelayAll(7s);
|
||||
context.Repeat(30s);
|
||||
}).Schedule(5s, GROUP_PHASE_1, [this](TaskContext context)
|
||||
{
|
||||
@@ -191,6 +187,7 @@ struct boss_nazan : public BossAI
|
||||
{
|
||||
if (param == ACTION_FLY_DOWN)
|
||||
{
|
||||
_scheduler.CancelGroup(GROUP_PHASE_1);
|
||||
Talk(EMOTE_NAZAN);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
@@ -205,9 +202,8 @@ struct boss_nazan : public BossAI
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
scheduler.CancelGroup(GROUP_PHASE_1);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
_scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CONE_OF_FIRE);
|
||||
context.Repeat(12s);
|
||||
@@ -216,9 +212,10 @@ struct boss_nazan : public BossAI
|
||||
DoCastRandomTarget(SPELL_FIREBALL);
|
||||
context.Repeat(4s, 6s);
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
_scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_BELLOWING_ROAR);
|
||||
context.Repeat(30s);
|
||||
@@ -227,24 +224,28 @@ struct boss_nazan : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
if (!me->IsLevitating())
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
|
||||
if (!me->IsLevitating())
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct boss_vazruden : public BossAI
|
||||
struct boss_vazruden : public ScriptedAI
|
||||
{
|
||||
boss_vazruden(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
|
||||
boss_vazruden(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
@@ -263,7 +264,7 @@ struct boss_vazruden : public BossAI
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
scheduler.Schedule(5s, [this](TaskContext /*context*/)
|
||||
_scheduler.Schedule(5s, [this](TaskContext /*context*/)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
}).Schedule(4s, [this](TaskContext context)
|
||||
@@ -280,7 +281,7 @@ struct boss_vazruden : public BossAI
|
||||
_hasSpoken = true;
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
scheduler.Schedule(6s, [this](TaskContext /*context*/)
|
||||
_scheduler.Schedule(6s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_hasSpoken = false;
|
||||
});
|
||||
@@ -305,13 +306,16 @@ struct boss_vazruden : public BossAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
DoMeleeAttackIfReady();
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
bool _hasSpoken;
|
||||
bool _nazanCalled;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
class spell_vazruden_fireball : public SpellScript
|
||||
|
||||
@@ -144,17 +144,21 @@ class spell_capacitus_polarity_charge : public SpellScript
|
||||
void HandleTargets(std::list<WorldObject*>& targetList)
|
||||
{
|
||||
uint8 count = 0;
|
||||
for (std::list<WorldObject*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit)
|
||||
if ((*ihit)->GetGUID() != GetCaster()->GetGUID())
|
||||
if (Player* target = (*ihit)->ToPlayer())
|
||||
for (auto& ihit : targetList)
|
||||
if (ihit->GetGUID() != GetCaster()->GetGUID())
|
||||
if (Player* target = ihit->ToPlayer())
|
||||
if (target->HasAura(GetTriggeringSpell()->Id))
|
||||
++count;
|
||||
|
||||
uint32 spellId = GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE ? SPELL_POSITIVE_CHARGE_STACK : SPELL_NEGATIVE_CHARGE_STACK;
|
||||
if (count)
|
||||
{
|
||||
uint32 spellId = GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE ? SPELL_POSITIVE_CHARGE_STACK : SPELL_NEGATIVE_CHARGE_STACK;
|
||||
GetCaster()->SetAuraStack(spellId, GetCaster(), count);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCaster()->RemoveAurasDueToSpell(spellId);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleDamage(SpellEffIndex /*effIndex*/)
|
||||
@@ -174,6 +178,29 @@ class spell_capacitus_polarity_charge : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class spell_capacitus_polarity_charge_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_capacitus_polarity_charge_aura);
|
||||
|
||||
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->RemoveAurasDueToSpell(SPELL_POSITIVE_CHARGE_STACK);
|
||||
target->RemoveAurasDueToSpell(SPELL_NEGATIVE_CHARGE_STACK);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_capacitus_polarity_charge_aura::HandleAfterRemove, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_capacitus_polarity_shift : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_capacitus_polarity_shift);
|
||||
@@ -194,5 +221,6 @@ void AddSC_boss_mechano_lord_capacitus()
|
||||
{
|
||||
RegisterMechanarCreatureAI(boss_mechano_lord_capacitus);
|
||||
RegisterSpellScript(spell_capacitus_polarity_charge);
|
||||
RegisterSpellScript(spell_capacitus_polarity_charge_aura);
|
||||
RegisterSpellScript(spell_capacitus_polarity_shift);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user