mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 22:56:24 +00:00
Merge branch 'master' into Playerbot
# Conflicts: # src/server/game/Entities/Player/Player.cpp
This commit is contained in:
@@ -381,6 +381,7 @@ public:
|
||||
break;
|
||||
case EVENT_STARTED:
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetInCombatWithZone();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -513,7 +514,7 @@ public:
|
||||
enum OhganSpells
|
||||
{
|
||||
SPELL_SUNDERARMOR = 24317,
|
||||
SPELL_THRASH = 3417 // Triggers 3391
|
||||
SPELL_THRASH = 3391
|
||||
};
|
||||
|
||||
class npc_ohgan : public CreatureScript
|
||||
@@ -527,7 +528,6 @@ public:
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->AddAura(SPELL_THRASH, me);
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
@@ -547,6 +547,11 @@ public:
|
||||
DoCastVictim(SPELL_SUNDERARMOR);
|
||||
context.Repeat(6s, 12s);
|
||||
});
|
||||
_scheduler.Schedule(12s, 18s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
context.Repeat(12s, 18s);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
|
||||
@@ -15,138 +15,113 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Duskwood
|
||||
SD%Complete: 100
|
||||
SDComment: Quest Support:8735
|
||||
SDCategory: Duskwood
|
||||
EndScriptData */
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
enum TwilightCorrupter
|
||||
enum Spells
|
||||
{
|
||||
ITEM_FRAGMENT = 21149,
|
||||
NPC_TWILIGHT_CORRUPTER = 15625,
|
||||
YELL_TWILIGHTCORRUPTOR_RESPAWN = 0,
|
||||
YELL_TWILIGHTCORRUPTOR_AGGRO = 1,
|
||||
YELL_TWILIGHTCORRUPTOR_KILL = 2,
|
||||
SPELL_SOUL_CORRUPTION = 25805,
|
||||
SPELL_CREATURE_OF_NIGHTMARE = 25806,
|
||||
SPELL_LEVEL_UP = 24312,
|
||||
SPELL_SWELL_OF_SOULS = 21307,
|
||||
};
|
||||
|
||||
EVENT_SOUL_CORRUPTION = 1,
|
||||
EVENT_CREATURE_OF_NIGHTMARE = 2
|
||||
enum Misc
|
||||
{
|
||||
ITEM_FRAGMENT = 21149,
|
||||
NPC_TWILIGHT_CORRUPTER = 15625
|
||||
};
|
||||
|
||||
enum Say
|
||||
{
|
||||
SAY_RESPAWN = 0,
|
||||
SAY_AGGRO,
|
||||
SAY_KILL
|
||||
};
|
||||
|
||||
/*######
|
||||
# boss_twilight_corrupter
|
||||
######*/
|
||||
|
||||
class boss_twilight_corrupter : public CreatureScript
|
||||
struct boss_twilight_corrupter : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
boss_twilight_corrupter() : CreatureScript("boss_twilight_corrupter") { }
|
||||
boss_twilight_corrupter(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
struct boss_twilight_corrupterAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_twilight_corrupterAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
KillCount = 0;
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
// Xinef: check if copy is summoned
|
||||
std::list<Creature*> cList;
|
||||
me->GetCreatureListWithEntryInGrid(cList, me->GetEntry(), 50.0f);
|
||||
if (!cList.empty())
|
||||
for (std::list<Creature*>::const_iterator itr = cList.begin(); itr != cList.end(); ++itr)
|
||||
if ((*itr)->IsAlive() && me->GetGUID() != (*itr)->GetGUID())
|
||||
{
|
||||
me->DespawnOrUnsummon(1);
|
||||
break;
|
||||
}
|
||||
|
||||
_introSpoken = false;
|
||||
ScriptedAI::InitializeAI();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!_introSpoken && who->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
_introSpoken = true;
|
||||
Talk(YELL_TWILIGHTCORRUPTOR_RESPAWN, who);
|
||||
me->SetFaction(FACTION_MONSTER);
|
||||
}
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(YELL_TWILIGHTCORRUPTOR_AGGRO);
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EVENT_SOUL_CORRUPTION, 15000);
|
||||
_events.ScheduleEvent(EVENT_CREATURE_OF_NIGHTMARE, 30000);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
++KillCount;
|
||||
Talk(YELL_TWILIGHTCORRUPTOR_KILL, victim);
|
||||
|
||||
if (KillCount == 3)
|
||||
{
|
||||
DoCast(me, SPELL_LEVEL_UP, true);
|
||||
KillCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SOUL_CORRUPTION:
|
||||
DoCastVictim(SPELL_SOUL_CORRUPTION);
|
||||
_events.ScheduleEvent(EVENT_SOUL_CORRUPTION, rand() % 4000 + 15000);
|
||||
break;
|
||||
case EVENT_CREATURE_OF_NIGHTMARE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true))
|
||||
DoCast(target, SPELL_CREATURE_OF_NIGHTMARE);
|
||||
_events.ScheduleEvent(EVENT_CREATURE_OF_NIGHTMARE, 45000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap _events;
|
||||
uint8 KillCount;
|
||||
bool _introSpoken;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new boss_twilight_corrupterAI(creature);
|
||||
_scheduler.CancelAll();
|
||||
me->RemoveAurasDueToSpell(SPELL_SWELL_OF_SOULS);
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
// Xinef: check if copy is summoned
|
||||
std::list<Creature*> cList;
|
||||
me->GetCreatureListWithEntryInGrid(cList, me->GetEntry(), 50.0f);
|
||||
for (Creature* creature : cList)
|
||||
{
|
||||
if (creature->IsAlive() && me->GetGUID() != creature->GetGUID())
|
||||
{
|
||||
me->DespawnOrUnsummon(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_introSpoken = false;
|
||||
ScriptedAI::InitializeAI();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!_introSpoken && who->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
_introSpoken = true;
|
||||
Talk(SAY_RESPAWN, who);
|
||||
me->SetFaction(FACTION_MONSTER);
|
||||
}
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_scheduler
|
||||
.Schedule(12s, 18s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_CREATURE_OF_NIGHTMARE, 1, 100.f);
|
||||
context.Repeat(35s, 45s);
|
||||
})
|
||||
.Schedule(9s, 16s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SOUL_CORRUPTION);
|
||||
context.Repeat(5s, 9s);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
Talk(SAY_KILL, victim);
|
||||
DoCastSelf(SPELL_SWELL_OF_SOULS);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
bool _introSpoken;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
/*######
|
||||
@@ -169,6 +144,6 @@ public:
|
||||
|
||||
void AddSC_duskwood()
|
||||
{
|
||||
new boss_twilight_corrupter();
|
||||
RegisterCreatureAI(boss_twilight_corrupter);
|
||||
new at_twilight_grove();
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ struct boss_ayamiss : public BossAI
|
||||
else if (type == WAYPOINT_MOTION_TYPE && id == POINT_GROUND)
|
||||
{
|
||||
SetCombatMovement(true);
|
||||
me->SetDisableGravity(false);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
|
||||
@@ -45,15 +45,13 @@ enum Events
|
||||
{
|
||||
EVENT_DISMEMBER = 1,
|
||||
EVENT_GATHERING_SPEED = 2,
|
||||
EVENT_FULL_SPEED = 3,
|
||||
EVENT_CREEPING_PLAGUE = 4,
|
||||
EVENT_RESPAWN_EGG = 5,
|
||||
EVENT_CREEPING_PLAGUE = 3
|
||||
};
|
||||
|
||||
enum Phases
|
||||
{
|
||||
PHASE_EGG = 0,
|
||||
PHASE_TRANSFORM = 1
|
||||
PHASE_EGG = 1,
|
||||
PHASE_TRANSFORM = 2
|
||||
};
|
||||
|
||||
struct boss_buru : public BossAI
|
||||
@@ -66,8 +64,10 @@ struct boss_buru : public BossAI
|
||||
|
||||
DoCastSelf(SPELL_FULL_SPEED, true);
|
||||
|
||||
_phase = PHASE_EGG;
|
||||
instance->SetData(DATA_BURU_PHASE, _phase);
|
||||
|
||||
ManipulateEggs(true);
|
||||
_eggs.clear();
|
||||
}
|
||||
|
||||
void ManipulateEggs(bool respawn)
|
||||
@@ -81,14 +81,15 @@ struct boss_buru : public BossAI
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
me->AddThreat(who, 1000000.f);
|
||||
Talk(EMOTE_TARGET, who);
|
||||
DoCastSelf(SPELL_THORNS);
|
||||
_phase = PHASE_EGG;
|
||||
instance->SetData(DATA_BURU_PHASE, _phase);
|
||||
ManipulateEggs(true);
|
||||
me->RemoveAurasDueToSpell(SPELL_FULL_SPEED);
|
||||
events.ScheduleEvent(EVENT_DISMEMBER, 5s);
|
||||
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s);
|
||||
events.ScheduleEvent(EVENT_FULL_SPEED, 60s);
|
||||
_phase = PHASE_EGG;
|
||||
events.ScheduleEvent(EVENT_GATHERING_SPEED, 2s);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
@@ -114,10 +115,9 @@ struct boss_buru : public BossAI
|
||||
if (_phase != PHASE_EGG)
|
||||
return;
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_FULL_SPEED);
|
||||
me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED);
|
||||
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s);
|
||||
events.ScheduleEvent(EVENT_FULL_SPEED, 60s);
|
||||
events.CancelEvent(EVENT_GATHERING_SPEED);
|
||||
events.ScheduleEvent(EVENT_GATHERING_SPEED, 2s);
|
||||
if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.f, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
@@ -127,17 +127,11 @@ struct boss_buru : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid const guid, int32 /*type*/) override
|
||||
{
|
||||
_eggs.push_back(guid);
|
||||
events.ScheduleEvent(EVENT_RESPAWN_EGG, 120s);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (attacker->GetEntry() != NPC_BURU_EGG && _phase == PHASE_EGG)
|
||||
if (attacker->GetEntry() == NPC_BURU_EGG)
|
||||
{
|
||||
damage = damage * 0.01f; // 99% dmg resist
|
||||
me->LowerPlayerDamageReq(damage);
|
||||
}
|
||||
|
||||
if (me->HealthBelowPctDamaged(20, damage) && _phase == PHASE_EGG)
|
||||
@@ -145,8 +139,10 @@ struct boss_buru : public BossAI
|
||||
DoCastSelf(SPELL_FULL_SPEED, true);
|
||||
ManipulateEggs(false);
|
||||
me->RemoveAurasDueToSpell(SPELL_THORNS);
|
||||
me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED);
|
||||
events.Reset();
|
||||
_phase = PHASE_TRANSFORM;
|
||||
instance->SetData(DATA_BURU_PHASE, _phase);
|
||||
DoResetThreat();
|
||||
events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2s);
|
||||
DoCastSelf(SPELL_BURU_TRANSFORM);
|
||||
@@ -172,19 +168,10 @@ struct boss_buru : public BossAI
|
||||
DoCastSelf(SPELL_GATHERING_SPEED);
|
||||
events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s);
|
||||
break;
|
||||
case EVENT_FULL_SPEED:
|
||||
DoCastSelf(SPELL_FULL_SPEED);
|
||||
break;
|
||||
case EVENT_CREEPING_PLAGUE:
|
||||
DoCastAOE(SPELL_CREEPING_PLAGUE);
|
||||
events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 6s);
|
||||
break;
|
||||
case EVENT_RESPAWN_EGG:
|
||||
if (Creature* egg = me->GetMap()->GetCreature(*_eggs.begin()))
|
||||
egg->Respawn();
|
||||
|
||||
_eggs.pop_front();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -194,7 +181,6 @@ struct boss_buru : public BossAI
|
||||
}
|
||||
private:
|
||||
uint8 _phase;
|
||||
GuidList _eggs;
|
||||
};
|
||||
|
||||
struct npc_buru_egg : public ScriptedAI
|
||||
@@ -204,6 +190,7 @@ struct npc_buru_egg : public ScriptedAI
|
||||
_instance = me->GetInstanceScript();
|
||||
SetCombatMovement(false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetControlled(true, UNIT_STATE_STUNNED);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* attacker) override
|
||||
@@ -238,14 +225,17 @@ struct npc_buru_egg : public ScriptedAI
|
||||
{
|
||||
if (Creature* buru = _instance->GetCreature(DATA_BURU))
|
||||
{
|
||||
DoCastSelf(SPELL_EXPLODE);
|
||||
DoCastSelf(SPELL_EXPLODE, true);
|
||||
DoCastSelf(SPELL_BURU_EGG_TRIGGER, true);
|
||||
buru->CastSpell(buru, SPELL_CREATURE_SPECIAL, true);
|
||||
if (buru->GetAI())
|
||||
buru->AI()->SetGUID(me->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
me->DespawnOrUnsummon(5000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override { }
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
@@ -77,8 +77,15 @@ struct boss_kurinnaxx : public BossAI
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (killer)
|
||||
{
|
||||
killer->GetMap()->LoadGrid(-9502.80f, 2042.65f); // Ossirian grid
|
||||
|
||||
if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
{
|
||||
player->SummonCreature(NPC_ANDOROV, -8538.177f, 1486.0956f, 32.39054f, 3.7638654f, TEMPSUMMON_CORPSE_DESPAWN, 600000000);
|
||||
}
|
||||
}
|
||||
|
||||
if (Creature* ossirian = instance->GetCreature(DATA_OSSIRIAN))
|
||||
{
|
||||
ossirian->setActive(true);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GameObjectAI.h"
|
||||
#include "MiscPackets.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
@@ -43,6 +44,7 @@ enum Spells
|
||||
SPELL_SAND_STORM = 25160,
|
||||
SPELL_SUMMON_CRYSTAL = 25192,
|
||||
SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK = 27627, // Server-side
|
||||
SPELL_SPEED_BURST = 25184, // Server-side
|
||||
|
||||
// Crystal
|
||||
SPELL_FIRE_WEAKNESS = 25177,
|
||||
@@ -54,19 +56,27 @@ enum Spells
|
||||
|
||||
enum Actions
|
||||
{
|
||||
ACTION_TRIGGER_WEAKNESS = 1
|
||||
ACTION_TRIGGER_WEAKNESS = 1,
|
||||
ACTION_DESPAWN_TRIGGER = 2
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_SILENCE = 1,
|
||||
EVENT_CYCLONE = 2,
|
||||
EVENT_STOMP = 3
|
||||
EVENT_STOMP = 3,
|
||||
EVENT_SPEEDUP = 4
|
||||
};
|
||||
|
||||
uint8 const NUM_CRYSTALS = 11;
|
||||
enum Misc
|
||||
{
|
||||
GUID_TRIGGER_PAIR = 1,
|
||||
};
|
||||
|
||||
uint8 const NUM_CRYSTALS = 12;
|
||||
Position CrystalCoordinates[NUM_CRYSTALS] =
|
||||
{
|
||||
{ -9407.7197265625f, 1960.20996093750f, 85.6390991210937f, 1.11700999736786f },
|
||||
{ -9388.4404296875f, 1940.20996093750f, 85.6390991210937f, 3.17650008201599f },
|
||||
{ -9357.8603515625f, 1929.07995605469f, 85.6390991210937f, 1.06465005874634f },
|
||||
{ -9383.2900390625f, 2012.68005371094f, 85.6511001586914f, 2.93214988708496f },
|
||||
@@ -80,7 +90,11 @@ Position CrystalCoordinates[NUM_CRYSTALS] =
|
||||
{ -9367.1699218750f, 1780.89001464844f, 85.6390991210937f, 1.90241003036499f }
|
||||
};
|
||||
|
||||
Position initialCrystalPosition = { -9407.7197265625f, 1960.2099609375f, 85.6390991210937f, 1.11700999736786f };
|
||||
Position VortexPositions[2] =
|
||||
{
|
||||
{ -9524.06f, 1881.9224f, 85.64029f, 0.0f },
|
||||
{ -9228.479, 1925.3331f, 85.64147f, 0.0f }
|
||||
};
|
||||
|
||||
uint8 const NUM_WEAKNESS = 5;
|
||||
uint32 const spellWeakness[NUM_WEAKNESS] =
|
||||
@@ -96,102 +110,54 @@ struct boss_ossirian : public BossAI
|
||||
void InitializeAI() override
|
||||
{
|
||||
Reset();
|
||||
|
||||
if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, initialCrystalPosition))
|
||||
{
|
||||
_triggerGUID[0] = trigger->GetGUID();
|
||||
if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL,
|
||||
initialCrystalPosition.GetPositionX(),
|
||||
initialCrystalPosition.GetPositionY(),
|
||||
initialCrystalPosition.GetPositionZ(),
|
||||
0, 0, 0, 0, 0, uint32(-1)))
|
||||
{
|
||||
_crystalGUID[0] = crystal->GetGUID();
|
||||
crystal->SetOwnerGUID(ObjectGuid::Empty);
|
||||
crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
|
||||
_crystalIterator = urand(0, NUM_CRYSTALS - 1);
|
||||
_triggerGUID[1].Clear();
|
||||
_crystalGUID[1].Clear();
|
||||
}
|
||||
_crystalIterator = urand(1, NUM_CRYSTALS - 1);
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
if (me->IsVisible())
|
||||
if (!ObjectAccessor::GetGameObject(*me, _firstCrystalGUID))
|
||||
{
|
||||
Creature* trigger = me->GetMap()->GetCreature(_triggerGUID[0]);
|
||||
if (trigger)
|
||||
if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[0]))
|
||||
{
|
||||
trigger->DespawnOrUnsummon();
|
||||
if (GameObject* crystal = me->GetMap()->GetGameObject(_crystalGUID[0]))
|
||||
crystal->Delete();
|
||||
}
|
||||
|
||||
trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, initialCrystalPosition);
|
||||
if (trigger)
|
||||
{
|
||||
_triggerGUID[0] = trigger->GetGUID();
|
||||
if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL,
|
||||
initialCrystalPosition.GetPositionX(),
|
||||
initialCrystalPosition.GetPositionY(),
|
||||
initialCrystalPosition.GetPositionZ(),
|
||||
if (GameObject* crystal = me->SummonGameObject(GO_OSSIRIAN_CRYSTAL,
|
||||
CrystalCoordinates[0].GetPositionX(),
|
||||
CrystalCoordinates[0].GetPositionY(),
|
||||
CrystalCoordinates[0].GetPositionZ(),
|
||||
0, 0, 0, 0, 0, uint32(-1)))
|
||||
{
|
||||
_crystalGUID[0] = crystal->GetGUID();
|
||||
_firstCrystalGUID = crystal->GetGUID();
|
||||
crystal->SetOwnerGUID(ObjectGuid::Empty);
|
||||
crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE);
|
||||
crystal->AI()->SetGUID(trigger->GetGUID(), GUID_TRIGGER_PAIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spell) override
|
||||
void JustSummoned(Creature* creature) override
|
||||
{
|
||||
summons.Summon(creature);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
for (uint32 weakness : spellWeakness)
|
||||
{
|
||||
if (spell->Id == weakness)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN);
|
||||
|
||||
if (caster->GetGUID() == _triggerGUID[1])
|
||||
{
|
||||
if (Creature* creatureCaster = caster->ToCreature())
|
||||
{
|
||||
creatureCaster->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid guid, int32 action) override
|
||||
{
|
||||
if (action == ACTION_TRIGGER_WEAKNESS)
|
||||
if (action == ACTION_TRIGGER_WEAKNESS && guid != _firstCrystalGUID)
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (_crystalGUID[i] == guid)
|
||||
{
|
||||
if (Creature* trigger = me->GetMap()->GetCreature(_triggerGUID[i]))
|
||||
{
|
||||
if (!trigger->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false);
|
||||
}
|
||||
}
|
||||
|
||||
SpawnNextCrystal();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
SpawnNextCrystal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +165,7 @@ struct boss_ossirian : public BossAI
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_SPEEDUP, 10s);
|
||||
events.ScheduleEvent(EVENT_SILENCE, 30s);
|
||||
events.ScheduleEvent(EVENT_CYCLONE, 20s);
|
||||
events.ScheduleEvent(EVENT_STOMP, 30s);
|
||||
@@ -212,16 +179,30 @@ struct boss_ossirian : public BossAI
|
||||
WorldPackets::Misc::Weather weather(WEATHER_STATE_HEAVY_SANDSTORM, 1.0f);
|
||||
map->SendToPlayers(weather.Write());
|
||||
|
||||
SpawnNextCrystal();
|
||||
SpawnNextCrystal(3);
|
||||
|
||||
std::list<uint32> pathIds = { 1446800, 1446790 };
|
||||
|
||||
for (Position pos : VortexPositions)
|
||||
{
|
||||
if (Creature* vortex = me->SummonCreature(NPC_SAND_VORTEX, pos))
|
||||
{
|
||||
vortex->GetMotionMaster()->MovePath(pathIds.front(), true);
|
||||
pathIds.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
|
||||
if (GameObject* crystal = GetClosestGameObjectWithEntry(summon, GO_OSSIRIAN_CRYSTAL, 5.0f))
|
||||
if (summon->GetEntry() == NPC_OSSIRIAN_TRIGGER)
|
||||
{
|
||||
crystal->Delete();
|
||||
if (GameObject* crystal = GetClosestGameObjectWithEntry(summon, GO_OSSIRIAN_CRYSTAL, 5.0f))
|
||||
{
|
||||
crystal->Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,24 +211,26 @@ struct boss_ossirian : public BossAI
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void SpawnNextCrystal()
|
||||
void SpawnNextCrystal(uint8 count = 1)
|
||||
{
|
||||
if (_crystalIterator == NUM_CRYSTALS)
|
||||
_crystalIterator = 0;
|
||||
|
||||
if (Creature* trigger = me->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[_crystalIterator]))
|
||||
for (uint8 i = 0; i < count; ++i)
|
||||
{
|
||||
_triggerGUID[1] = trigger->GetGUID();
|
||||
if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL,
|
||||
CrystalCoordinates[_crystalIterator].GetPositionX(),
|
||||
CrystalCoordinates[_crystalIterator].GetPositionY(),
|
||||
CrystalCoordinates[_crystalIterator].GetPositionZ(),
|
||||
0, 0, 0, 0, 0, uint32(-1)))
|
||||
if (_crystalIterator == NUM_CRYSTALS)
|
||||
_crystalIterator = 1;
|
||||
|
||||
if (Creature* trigger = me->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[_crystalIterator]))
|
||||
{
|
||||
_crystalGUID[1] = crystal->GetGUID();
|
||||
++_crystalIterator;
|
||||
crystal->SetOwnerGUID(ObjectGuid::Empty);
|
||||
crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE);
|
||||
if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL,
|
||||
CrystalCoordinates[_crystalIterator].GetPositionX(),
|
||||
CrystalCoordinates[_crystalIterator].GetPositionY(),
|
||||
CrystalCoordinates[_crystalIterator].GetPositionZ(),
|
||||
0, 0, 0, 0, 0, uint32(-1)))
|
||||
{
|
||||
++_crystalIterator;
|
||||
crystal->SetOwnerGUID(ObjectGuid::Empty);
|
||||
crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE);
|
||||
crystal->AI()->SetGUID(trigger->GetGUID(), GUID_TRIGGER_PAIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,6 +279,9 @@ struct boss_ossirian : public BossAI
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SPEEDUP:
|
||||
DoCastSelf(SPELL_SPEED_BURST);
|
||||
break;
|
||||
case EVENT_SILENCE:
|
||||
DoCastAOE(SPELL_CURSE_OF_TONGUES);
|
||||
events.ScheduleEvent(EVENT_SILENCE, 20s, 30s);
|
||||
@@ -316,9 +302,8 @@ struct boss_ossirian : public BossAI
|
||||
}
|
||||
|
||||
protected:
|
||||
std::array<ObjectGuid, 2> _triggerGUID;
|
||||
std::array<ObjectGuid, 2> _crystalGUID;
|
||||
uint8 _crystalIterator;
|
||||
ObjectGuid _firstCrystalGUID;
|
||||
bool _saidIntro;
|
||||
};
|
||||
|
||||
@@ -327,18 +312,61 @@ class go_ossirian_crystal : public GameObjectScript
|
||||
public:
|
||||
go_ossirian_crystal() : GameObjectScript("go_ossirian_crystal") { }
|
||||
|
||||
bool OnGossipHello(Player* player, GameObject* go) override
|
||||
struct go_ossirian_crystalAI : public GameObjectAI
|
||||
{
|
||||
InstanceScript* instance = player->GetInstanceScript();
|
||||
if (!instance)
|
||||
return true;
|
||||
go_ossirian_crystalAI(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
|
||||
|
||||
Creature* ossirian = instance->GetCreature(DATA_OSSIRIAN);
|
||||
if (!ossirian)
|
||||
return true;
|
||||
void SetGUID(ObjectGuid guid, int32 type) override
|
||||
{
|
||||
if (type == GUID_TRIGGER_PAIR)
|
||||
{
|
||||
_triggerGUID = guid;
|
||||
}
|
||||
}
|
||||
|
||||
ossirian->AI()->SetGUID(go->GetGUID(), ACTION_TRIGGER_WEAKNESS);
|
||||
return false;
|
||||
bool GossipHello(Player* /*player*/, bool reportUse) override
|
||||
{
|
||||
if (reportUse)
|
||||
{
|
||||
if (!_instance)
|
||||
return true;
|
||||
|
||||
Creature* ossirian = _instance->GetCreature(DATA_OSSIRIAN);
|
||||
if (!ossirian)
|
||||
return true;
|
||||
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _triggerGUID))
|
||||
{
|
||||
if (!trigger->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
ossirian->AI()->SetGUID(me->GetGUID(), ACTION_TRIGGER_WEAKNESS);
|
||||
trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_DESPAWN_TRIGGER)
|
||||
{
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _triggerGUID))
|
||||
{
|
||||
trigger->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
ObjectGuid _triggerGUID;
|
||||
};
|
||||
|
||||
GameObjectAI* GetAI(GameObject* go) const override
|
||||
{
|
||||
return new go_ossirian_crystalAI(go);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -442,10 +470,30 @@ class spell_crystal_weakness : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class spell_aq_shadow_storm : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_aq_shadow_storm);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
targets.remove_if([caster](WorldObject const* obj)
|
||||
{
|
||||
return caster->GetExactDist2d(obj) < 25.0f;
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_aq_shadow_storm::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_ossirian()
|
||||
{
|
||||
RegisterRuinsOfAhnQirajCreatureAI(boss_ossirian);
|
||||
new go_ossirian_crystal();
|
||||
RegisterCreatureAI(npc_anubisath_guardian);
|
||||
RegisterSpellScript(spell_crystal_weakness);
|
||||
RegisterSpellScript(spell_aq_shadow_storm);
|
||||
}
|
||||
|
||||
@@ -15,21 +15,22 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SmartAI.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ruins_of_ahnqiraj.h"
|
||||
|
||||
enum Yells
|
||||
{
|
||||
SAY_UNK1 = 6,
|
||||
SAY_UNK2 = 7,
|
||||
SAY_UNK3 = 8,
|
||||
// The time of our retribution is at hand! Let darkness reign in the hearts of our enemies! Sound: 8645 Emote: 35
|
||||
SAY_DEATH = 9,
|
||||
SAY_CHANGEAGGRO = 10,
|
||||
SAY_KILLS_ANDOROV = 11,
|
||||
SAY_COMPLETE_QUEST = 12 // Yell when realm complete quest 8743 for world event
|
||||
// Warriors, Captains, continue the fight! Sound: 8640
|
||||
// Warriors, Captains, continue the fight! Sound: 8640
|
||||
};
|
||||
|
||||
enum Spells
|
||||
@@ -60,6 +61,12 @@ struct boss_rajaxx : public BossAI
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
|
||||
if (Creature* andorov = instance->instance->GetCreature(instance->GetGuidData(DATA_ANDOROV)))
|
||||
{
|
||||
andorov->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_VENDOR);
|
||||
andorov->ForceValuesUpdateAtIndex(UNIT_NPC_FLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
@@ -123,8 +130,236 @@ class spell_rajaxx_thundercrash : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
enum AndorovMisc
|
||||
{
|
||||
// Factions
|
||||
FACTION_ANDOROV_ESCORT = 250,
|
||||
|
||||
// Spells
|
||||
SPELL_AURA_OF_COMMAND = 25516,
|
||||
SPELL_BASH = 25515,
|
||||
SPELL_STRIKE = 22591,
|
||||
|
||||
// Texts
|
||||
SAY_ANDOROV_INTRO = 0, // Before for the first wave
|
||||
SAY_ANDOROV_ATTACK = 1, // Beginning the event
|
||||
|
||||
// Gossips
|
||||
GOSSIP_ANDRNOV = 7047,
|
||||
|
||||
// Events
|
||||
EVENT_BASH = 1,
|
||||
EVENT_COMMAND_AURA,
|
||||
EVENT_STRIKE
|
||||
};
|
||||
|
||||
struct npc_general_andorov : public npc_escortAI
|
||||
{
|
||||
npc_general_andorov(Creature* creature) : npc_escortAI(creature), _summons(me)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
SetDespawnAtEnd(false);
|
||||
SetDespawnAtFar(false);
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 /*uiSender*/, uint32 uiAction) override
|
||||
{
|
||||
if (uiAction)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
SetEscortPaused(false);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
if (Creature* kaldoreielitist = me->SummonCreature(NPC_KALDOREI_ELITE, *me))
|
||||
{
|
||||
kaldoreielitist->SetImmuneToNPC(true);
|
||||
kaldoreielitist->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
kaldoreielitist->SetReactState(REACT_PASSIVE);
|
||||
kaldoreielitist->SetFaction(FACTION_ESCORT_H_ACTIVE);
|
||||
CAST_AI(SmartAI, kaldoreielitist->AI())->SetFollow(me, 2.5f, 0.f + i * (M_PI / 2));
|
||||
}
|
||||
}
|
||||
|
||||
me->SetFaction(FACTION_ANDOROV_ESCORT);
|
||||
Endwaypoint = false;
|
||||
_initialAttackTimer = 5 * IN_MILLISECONDS;
|
||||
_paused = false;
|
||||
|
||||
Start(false, true);
|
||||
|
||||
me->SetImmuneToNPC(true);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
_summons.Summon(summon);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_BASH, urand(8, 11) * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_COMMAND_AURA, urand(1, 3) * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_STRIKE, urand(2, 5) * IN_MILLISECONDS);
|
||||
}
|
||||
|
||||
void WaypointReached(uint32 waypointId) override
|
||||
{
|
||||
switch (waypointId)
|
||||
{
|
||||
case 10:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
|
||||
SetEscortPaused(true);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
_paused = true;
|
||||
break;
|
||||
case 14:
|
||||
SetEscortPaused(true);
|
||||
if (!Endwaypoint)
|
||||
{
|
||||
Endwaypoint = true;
|
||||
Talk(SAY_ANDOROV_INTRO);
|
||||
|
||||
me->SetImmuneToNPC(false);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
for (ObjectGuid const& guid : _summons)
|
||||
{
|
||||
if (Creature* kaldoreielitist = ObjectAccessor::GetCreature(*me, guid))
|
||||
{
|
||||
kaldoreielitist->SetImmuneToNPC(false);
|
||||
kaldoreielitist->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
kaldoreielitist->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_summons.DespawnAll();
|
||||
|
||||
if (Creature* rajaxx = instance->GetCreature(DATA_RAJAXX))
|
||||
{
|
||||
rajaxx->AI()->Talk(SAY_KILLS_ANDOROV);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetEntry() == NPC_RAJAXX)
|
||||
{
|
||||
Talk(SAY_ANDOROV_ATTACK);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
// If Rajaxx is in range attack him
|
||||
if (who->GetEntry() == NPC_RAJAXX && me->IsWithinDistInMap(who, 50.0f))
|
||||
{
|
||||
AttackStart(who);
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_ANDOROV)
|
||||
{
|
||||
return Endwaypoint;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (Endwaypoint && _initialAttackTimer)
|
||||
{
|
||||
me->SetFacingTo(2.8772139f);
|
||||
|
||||
if (_initialAttackTimer <= diff)
|
||||
{
|
||||
_initialAttackTimer = 0;
|
||||
|
||||
if (Creature* queez = instance->GetCreature(DATA_QUUEZ))
|
||||
{
|
||||
queez->AI()->AttackStart(me);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_initialAttackTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (_paused)
|
||||
{
|
||||
_paused = false;
|
||||
me->SetFacingTo(5.63741350f);
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BASH:
|
||||
DoCastVictim(SPELL_BASH);
|
||||
events.ScheduleEvent(EVENT_BASH, urand(12, 15) * IN_MILLISECONDS);
|
||||
break;
|
||||
case EVENT_COMMAND_AURA:
|
||||
DoCastSelf(SPELL_AURA_OF_COMMAND, true);
|
||||
events.ScheduleEvent(EVENT_COMMAND_AURA, urand(10, 20) * IN_MILLISECONDS);
|
||||
break;
|
||||
case EVENT_STRIKE:
|
||||
DoCastVictim(SPELL_STRIKE);
|
||||
events.ScheduleEvent(EVENT_STRIKE, urand(4, 6) * IN_MILLISECONDS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
SummonList _summons;
|
||||
uint32 _initialAttackTimer;
|
||||
bool Endwaypoint;
|
||||
bool _paused;
|
||||
};
|
||||
|
||||
void AddSC_boss_rajaxx()
|
||||
{
|
||||
RegisterRuinsOfAhnQirajCreatureAI(boss_rajaxx);
|
||||
RegisterSpellScript(spell_rajaxx_thundercrash);
|
||||
RegisterRuinsOfAhnQirajCreatureAI(npc_general_andorov);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "CreatureGroups.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "ruins_of_ahnqiraj.h"
|
||||
@@ -74,6 +75,18 @@ public:
|
||||
SetBossNumber(NUM_ENCOUNTER);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
_rajaxWaveCounter = 0;
|
||||
_buruPhase = 1;
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (GetBossState(DATA_KURINNAXX) == DONE && GetBossState(DATA_RAJAXX) != DONE)
|
||||
{
|
||||
if (!_andorovGUID)
|
||||
{
|
||||
player->SummonCreature(NPC_ANDOROV, -8538.177f, 1486.0956f, 32.39054f, 3.7638654f, TEMPSUMMON_CORPSE_DESPAWN, 600000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
@@ -97,9 +110,8 @@ public:
|
||||
case NPC_OSSIRIAN:
|
||||
_ossirianGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_SAND_VORTEX:
|
||||
_sandVortexes.push_back(creature->GetGUID());
|
||||
creature->SetVisible(false);
|
||||
case NPC_ANDOROV:
|
||||
_andorovGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -135,20 +147,35 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 /*data*/) override
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == DATA_RAJAXX_WAVE_ENGAGED)
|
||||
switch (type)
|
||||
{
|
||||
_scheduler.CancelGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
_scheduler.Schedule(2min, [this](TaskContext context)
|
||||
{
|
||||
CallNextRajaxxLeader();
|
||||
context.SetGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
context.Repeat();
|
||||
});
|
||||
case DATA_RAJAXX_WAVE_ENGAGED:
|
||||
_scheduler.CancelGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
_scheduler.Schedule(2min, [this](TaskContext context)
|
||||
{
|
||||
CallNextRajaxxLeader();
|
||||
context.SetGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
context.Repeat();
|
||||
});
|
||||
break;
|
||||
case DATA_BURU_PHASE:
|
||||
_buruPhase = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_BURU_PHASE)
|
||||
return _buruPhase;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OnUnitDeath(Unit* unit) override
|
||||
{
|
||||
if (Creature* creature = unit->ToCreature())
|
||||
@@ -167,7 +194,8 @@ public:
|
||||
case NPC_PAKKON:
|
||||
case NPC_ZERRAN:
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(1s, [this, formation](TaskContext /*context*/) {
|
||||
_scheduler.Schedule(1s, [this, formation](TaskContext /*context*/)
|
||||
{
|
||||
if (!formation->IsAnyMemberAlive())
|
||||
{
|
||||
CallNextRajaxxLeader(true);
|
||||
@@ -193,31 +221,6 @@ public:
|
||||
_paralyzedGUID = data;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_OSSIRIAN:
|
||||
{
|
||||
for (ObjectGuid const& guid : _sandVortexes)
|
||||
{
|
||||
if (Creature* sandVortex = instance->GetCreature(guid))
|
||||
{
|
||||
sandVortex->SetVisible(state == IN_PROGRESS);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
@@ -234,6 +237,8 @@ public:
|
||||
return _ossirianGUID;
|
||||
case DATA_PARALYZED:
|
||||
return _paralyzedGUID;
|
||||
case DATA_ANDOROV:
|
||||
return _andorovGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
@@ -301,7 +306,15 @@ public:
|
||||
|
||||
if (nextLeader->IsAlive())
|
||||
{
|
||||
nextLeader->SetInCombatWithZone();
|
||||
Creature* generalAndorov = instance->GetCreature(_andorovGUID);
|
||||
if (generalAndorov && generalAndorov->IsAlive() && generalAndorov->AI()->GetData(DATA_ANDOROV))
|
||||
{
|
||||
nextLeader->AI()->AttackStart(generalAndorov);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextLeader->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -333,8 +346,9 @@ public:
|
||||
ObjectGuid _buruGUID;
|
||||
ObjectGuid _ossirianGUID;
|
||||
ObjectGuid _paralyzedGUID;
|
||||
GuidVector _sandVortexes;
|
||||
ObjectGuid _andorovGUID;
|
||||
uint32 _rajaxWaveCounter;
|
||||
uint8 _buruPhase;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,14 +17,22 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ruins_of_ahnqiraj.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_HIVEZARA_CATALYST = 25187,
|
||||
SPELL_STINGER_CHARGE_NORMAL = 25190,
|
||||
SPELL_STINGER_CHARGE_BUFFED = 25191
|
||||
// Hive'Zara Stinger
|
||||
SPELL_HIVEZARA_CATALYST = 25187,
|
||||
SPELL_STINGER_CHARGE_NORMAL = 25190,
|
||||
SPELL_STINGER_CHARGE_BUFFED = 25191,
|
||||
|
||||
// Obsidian Destroyer
|
||||
SPELL_PURGE = 25756,
|
||||
SPELL_DRAIN_MANA = 25755,
|
||||
SPELL_DRAIN_MANA_VISUAL = 26639,
|
||||
SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK = 27627, // Server-side
|
||||
};
|
||||
|
||||
struct npc_hivezara_stinger : public ScriptedAI
|
||||
@@ -80,7 +88,86 @@ private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct npc_obsidian_destroyer : public ScriptedAI
|
||||
{
|
||||
npc_obsidian_destroyer(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
me->SetPower(POWER_MANA, 0);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, [&](Unit* target)
|
||||
{
|
||||
return target && target->IsPlayer() && target->GetPower(POWER_MANA) > 0;
|
||||
}, 6, SelectTargetMethod::Random);
|
||||
|
||||
for (Unit* target : targets)
|
||||
{
|
||||
DoCast(target, SPELL_DRAIN_MANA, true);
|
||||
}
|
||||
|
||||
if (me->GetPowerPct(POWER_MANA) >= 100.f)
|
||||
{
|
||||
DoCastAOE(SPELL_PURGE, true);
|
||||
}
|
||||
|
||||
context.Repeat(6s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK, true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.Update(diff,
|
||||
std::bind(&ScriptedAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
class spell_drain_mana : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_drain_mana);
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
target->CastSpell(caster, SPELL_DRAIN_MANA_VISUAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_drain_mana::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_ruins_of_ahnqiraj()
|
||||
{
|
||||
RegisterRuinsOfAhnQirajCreatureAI(npc_hivezara_stinger);
|
||||
RegisterRuinsOfAhnQirajCreatureAI(npc_obsidian_destroyer);
|
||||
RegisterSpellScript(spell_drain_mana);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ enum DataTypes
|
||||
DATA_YEGGETH = 12,
|
||||
DATA_PAKKON = 13,
|
||||
DATA_ZERRAN = 14,
|
||||
DATA_ANDOROV = 15,
|
||||
|
||||
DATA_BURU_PHASE = 16,
|
||||
|
||||
DATA_ENGAGED_FORMATION = 1
|
||||
};
|
||||
@@ -68,7 +71,9 @@ enum Creatures
|
||||
NPC_XURREM = 15390,
|
||||
NPC_YEGGETH = 15386,
|
||||
NPC_PAKKON = 15388,
|
||||
NPC_ZERRAN = 15385
|
||||
NPC_ZERRAN = 15385,
|
||||
NPC_ANDOROV = 15471,
|
||||
NPC_KALDOREI_ELITE = 15473
|
||||
};
|
||||
|
||||
enum GameObjects
|
||||
|
||||
@@ -142,12 +142,10 @@ public:
|
||||
//Kick out position
|
||||
const Position KickPos = { -8545.0f, 1984.0f, -96.0f, 0.0f};
|
||||
|
||||
struct boss_eye_of_cthun : public ScriptedAI
|
||||
struct boss_eye_of_cthun : public BossAI
|
||||
{
|
||||
boss_eye_of_cthun(Creature* creature) : ScriptedAI(creature), _summons(creature)
|
||||
boss_eye_of_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN), _summons(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
@@ -176,13 +174,18 @@ struct boss_eye_of_cthun : public ScriptedAI
|
||||
|
||||
_summons.DespawnAll();
|
||||
_scheduler.CancelAll();
|
||||
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
void JustDied(Unit* /*killer*/) override { }
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
ScheduleTasks();
|
||||
instance->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM);
|
||||
BossAI::EnterCombat(who);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
@@ -388,8 +391,6 @@ struct boss_eye_of_cthun : public ScriptedAI
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
|
||||
//Dark Glare phase
|
||||
uint32 DarkGlareTick;
|
||||
float DarkGlareAngle;
|
||||
@@ -400,17 +401,13 @@ private:
|
||||
SummonList _summons;
|
||||
};
|
||||
|
||||
struct boss_cthun : public ScriptedAI
|
||||
struct boss_cthun : public BossAI
|
||||
{
|
||||
boss_cthun(Creature* creature) : ScriptedAI(creature)
|
||||
boss_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
//Out of combat whisper timer
|
||||
uint32 WisperTimer;
|
||||
|
||||
@@ -784,9 +781,10 @@ struct boss_cthun : public ScriptedAI
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
|
||||
@@ -15,130 +15,115 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Huhuran
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Temple of Ahn'Qiraj
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
|
||||
enum Huhuran
|
||||
enum Emotes
|
||||
{
|
||||
EMOTE_FRENZY_KILL = 0,
|
||||
EMOTE_BERSERK = 1,
|
||||
|
||||
SPELL_FRENZY = 26051,
|
||||
SPELL_BERSERK = 26068,
|
||||
SPELL_POISONBOLT = 26052,
|
||||
SPELL_NOXIOUSPOISON = 26053,
|
||||
SPELL_WYVERNSTING = 26180,
|
||||
SPELL_ACIDSPIT = 26050,
|
||||
SPELL_WYVERN_STING_DAMAGE = 26233
|
||||
EMOTE_BERSERK = 1
|
||||
};
|
||||
|
||||
struct boss_huhuran : public ScriptedAI
|
||||
enum Spells
|
||||
{
|
||||
boss_huhuran(Creature* creature) : ScriptedAI(creature) { }
|
||||
SPELL_FRENZY = 26051, // triggers SPELL_POISON_BOLT
|
||||
SPELL_BERSERK = 26068, // triggers SPELL_POISON_BOLT
|
||||
SPELL_NOXIOUS_POISON = 26053,
|
||||
SPELL_WYVERN_STING = 26180,
|
||||
SPELL_ACID_SPIT = 26050,
|
||||
SPELL_WYVERN_STING_DAMAGE = 26233,
|
||||
SPELL_POISON_BOLT = 26052,
|
||||
SPELL_HARD_ENRAGE = 26662
|
||||
};
|
||||
|
||||
uint32 Frenzy_Timer;
|
||||
uint32 Wyvern_Timer;
|
||||
uint32 Spit_Timer;
|
||||
uint32 PoisonBolt_Timer;
|
||||
uint32 NoxiousPoison_Timer;
|
||||
uint32 FrenzyBack_Timer;
|
||||
enum Events
|
||||
{
|
||||
EVENT_FRENZY = 1,
|
||||
EVENT_WYVERN_STING = 2,
|
||||
EVENT_ACID_SPIT = 3,
|
||||
EVENT_NOXIOUS_POISON = 4,
|
||||
EVENT_HARD_ENRAGE = 5
|
||||
};
|
||||
|
||||
bool Frenzy;
|
||||
bool Berserk;
|
||||
struct boss_huhuran : public BossAI
|
||||
{
|
||||
boss_huhuran(Creature* creature) : BossAI(creature, DATA_HUHURAN) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Frenzy_Timer = urand(25000, 35000);
|
||||
Wyvern_Timer = urand(18000, 28000);
|
||||
Spit_Timer = 8000;
|
||||
PoisonBolt_Timer = 4000;
|
||||
NoxiousPoison_Timer = urand(10000, 20000);
|
||||
FrenzyBack_Timer = 15000;
|
||||
_Reset();
|
||||
_berserk = false;
|
||||
_hardEnrage = false;
|
||||
}
|
||||
|
||||
Frenzy = false;
|
||||
Berserk = false;
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FRENZY, urand(25000, 35000));
|
||||
events.ScheduleEvent(EVENT_WYVERN_STING, urand(18000, 28000));
|
||||
events.ScheduleEvent(EVENT_ACID_SPIT, 8000);
|
||||
events.ScheduleEvent(EVENT_NOXIOUS_POISON, urand(10000, 20000));
|
||||
events.ScheduleEvent(EVENT_HARD_ENRAGE, 300000);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!_berserk && HealthBelowPct(30))
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
me->TextEmote(EMOTE_BERSERK);
|
||||
_berserk = true;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Frenzy_Timer
|
||||
if (!Frenzy && Frenzy_Timer <= diff)
|
||||
events.Update(diff);
|
||||
while (uint32 eventid = events.ExecuteEvent())
|
||||
{
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
Talk(EMOTE_FRENZY_KILL);
|
||||
Frenzy = true;
|
||||
PoisonBolt_Timer = 3000;
|
||||
Frenzy_Timer = urand(25000, 35000);
|
||||
}
|
||||
else Frenzy_Timer -= diff;
|
||||
|
||||
// Wyvern Timer
|
||||
if (Wyvern_Timer <= diff)
|
||||
{
|
||||
DoCastAOE(SPELL_WYVERNSTING);
|
||||
Wyvern_Timer = urand(15000, 32000);
|
||||
}
|
||||
else Wyvern_Timer -= diff;
|
||||
|
||||
//Spit Timer
|
||||
if (Spit_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_ACIDSPIT);
|
||||
Spit_Timer = urand(5000, 10000);
|
||||
}
|
||||
else Spit_Timer -= diff;
|
||||
|
||||
//NoxiousPoison_Timer
|
||||
if (NoxiousPoison_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_NOXIOUSPOISON);
|
||||
NoxiousPoison_Timer = urand(12000, 24000);
|
||||
}
|
||||
else NoxiousPoison_Timer -= diff;
|
||||
|
||||
//PoisonBolt only if frenzy or berserk
|
||||
if (Frenzy || Berserk)
|
||||
{
|
||||
if (PoisonBolt_Timer <= diff)
|
||||
switch (eventid)
|
||||
{
|
||||
DoCastVictim(SPELL_POISONBOLT);
|
||||
PoisonBolt_Timer = 3000;
|
||||
case EVENT_FRENZY:
|
||||
DoCastSelf(SPELL_FRENZY, true);
|
||||
Talk(EMOTE_FRENZY_KILL);
|
||||
events.RepeatEvent(urand(25000, 35000));
|
||||
break;
|
||||
case EVENT_WYVERN_STING:
|
||||
me->CastCustomSpell(SPELL_WYVERN_STING, SPELLVALUE_MAX_TARGETS, 10, me, true);
|
||||
events.RepeatEvent(urand(15000, 32000));
|
||||
break;
|
||||
case EVENT_ACID_SPIT:
|
||||
DoCastVictim(SPELL_ACID_SPIT);
|
||||
events.RepeatEvent(urand(5000, 10000));
|
||||
break;
|
||||
case EVENT_NOXIOUS_POISON:
|
||||
DoCastRandomTarget(SPELL_NOXIOUS_POISON, 0, 100, true);
|
||||
events.RepeatEvent(urand(12000, 24000));
|
||||
break;
|
||||
case EVENT_HARD_ENRAGE:
|
||||
if (!_hardEnrage)
|
||||
{
|
||||
DoCastSelf(SPELL_HARD_ENRAGE, true);
|
||||
_hardEnrage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastAOE(SPELL_POISON_BOLT);
|
||||
}
|
||||
events.RepeatEvent(3000);
|
||||
break;
|
||||
}
|
||||
else PoisonBolt_Timer -= diff;
|
||||
}
|
||||
|
||||
//FrenzyBack_Timer
|
||||
if (Frenzy && FrenzyBack_Timer <= diff)
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
Frenzy = false;
|
||||
FrenzyBack_Timer = 15000;
|
||||
}
|
||||
else FrenzyBack_Timer -= diff;
|
||||
|
||||
if (!Berserk && HealthBelowPct(31))
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
Talk(EMOTE_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK);
|
||||
Berserk = true;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _berserk;
|
||||
bool _hardEnrage;
|
||||
};
|
||||
|
||||
// 26180 - Wyvern Sting
|
||||
@@ -146,17 +131,20 @@ class spell_huhuran_wyvern_sting : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_huhuran_wyvern_sting);
|
||||
|
||||
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL) // dispelled
|
||||
{
|
||||
caster->CastCustomSpell(SPELL_WYVERN_STING_DAMAGE, SPELLVALUE_BASE_POINT0, 3000, GetUnitOwner(), true);
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
caster->CastCustomSpell(SPELL_WYVERN_STING_DAMAGE, SPELLVALUE_BASE_POINT0, 3000, GetUnitOwner(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_huhuran_wyvern_sting::HandleRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_huhuran_wyvern_sting::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -242,9 +242,6 @@ struct boss_ouro : public BossAI
|
||||
{
|
||||
DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL);
|
||||
me->DespawnOrUnsummon(1000);
|
||||
// Remove after the header file is sorted with the bosses first.
|
||||
if (Creature* ouroSpawner = instance->GetCreature(DATA_OURO_SPAWNER))
|
||||
ouroSpawner->Respawn();
|
||||
instance->SetBossState(DATA_OURO, FAIL);
|
||||
if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f))
|
||||
base->DespawnOrUnsummon();
|
||||
@@ -348,10 +345,6 @@ struct npc_dirt_mound : ScriptedAI
|
||||
if (_instance)
|
||||
{
|
||||
_instance->SetBossState(DATA_OURO, FAIL);
|
||||
|
||||
// Remove after the header file is sorted with the bosses first.
|
||||
if (Creature* ouroSpawner = _instance->GetCreature(DATA_OURO_SPAWNER))
|
||||
ouroSpawner->Respawn();
|
||||
}
|
||||
|
||||
if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f))
|
||||
|
||||
@@ -125,7 +125,7 @@ struct boss_skeram : public BossAI
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 6s, 12s);
|
||||
events.ScheduleEvent(EVENT_FULLFILMENT, 15s);
|
||||
events.ScheduleEvent(EVENT_BLINK, 30s, 45s);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2s);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 1200ms);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
@@ -142,13 +142,13 @@ struct boss_skeram : public BossAI
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_ARCANE_EXPLOSION:
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION, true);
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION, false);
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 8s, 18s);
|
||||
break;
|
||||
case EVENT_FULLFILMENT:
|
||||
/// @todo For some weird reason boss does not cast this
|
||||
// Spell actually works, tested in duel
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, true);
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, false);
|
||||
events.ScheduleEvent(EVENT_FULLFILMENT, 20s, 30s);
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
@@ -159,7 +159,7 @@ struct boss_skeram : public BossAI
|
||||
break;
|
||||
case EVENT_EARTH_SHOCK:
|
||||
DoCastVictim(SPELL_EARTH_SHOCK);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 2s);
|
||||
events.ScheduleEvent(EVENT_EARTH_SHOCK, 1200ms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -173,10 +173,20 @@ struct boss_skeram : public BossAI
|
||||
events.RescheduleEvent(EVENT_BLINK, 2s);
|
||||
}
|
||||
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||
if (Unit* myVictim = me->GetVictim())
|
||||
{
|
||||
events.RescheduleEvent(EVENT_EARTH_SHOCK, 2s);
|
||||
DoMeleeAttackIfReady();
|
||||
if (me->IsWithinMeleeRange(myVictim))
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
|
||||
if (Unit* victimTarget = myVictim->GetVictim())
|
||||
{
|
||||
if (victimTarget->GetGUID() == me->GetGUID())
|
||||
{
|
||||
events.RescheduleEvent(EVENT_EARTH_SHOCK, 1200ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,14 +62,9 @@ enum Misc
|
||||
TELEPORTTIME = 30000
|
||||
};
|
||||
|
||||
struct boss_twinemperorsAI : public ScriptedAI
|
||||
struct boss_twinemperorsAI : public BossAI
|
||||
{
|
||||
boss_twinemperorsAI(Creature* creature): ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
boss_twinemperorsAI(Creature* creature): BossAI(creature, DATA_TWIN_EMPERORS) { }
|
||||
|
||||
uint32 Heal_Timer;
|
||||
uint32 Teleport_Timer;
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Instance_Temple_of_Ahnqiraj
|
||||
SD%Complete: 80
|
||||
SDComment:
|
||||
SDCategory: Temple of Ahn'Qiraj
|
||||
EndScriptData */
|
||||
|
||||
#include "InstanceScript.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
@@ -49,12 +42,12 @@ public:
|
||||
instance_temple_of_ahnqiraj_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
SetBossNumber(MAX_BOSS_NUMBER);
|
||||
}
|
||||
|
||||
//If Vem is dead...
|
||||
bool IsBossDied[3];
|
||||
|
||||
//Storing Skeram, Vem and Kri.
|
||||
ObjectGuid SkeramGUID;
|
||||
ObjectGuid VemGUID;
|
||||
ObjectGuid KriGUID;
|
||||
@@ -62,9 +55,7 @@ public:
|
||||
ObjectGuid VeklorGUID;
|
||||
ObjectGuid VeknilashGUID;
|
||||
ObjectGuid ViscidusGUID;
|
||||
|
||||
uint32 BugTrioDeathCount;
|
||||
|
||||
uint32 CthunPhase;
|
||||
|
||||
void Initialize() override
|
||||
@@ -72,9 +63,7 @@ public:
|
||||
IsBossDied[0] = false;
|
||||
IsBossDied[1] = false;
|
||||
IsBossDied[2] = false;
|
||||
|
||||
BugTrioDeathCount = 0;
|
||||
|
||||
CthunPhase = 0;
|
||||
}
|
||||
|
||||
@@ -154,7 +143,6 @@ public:
|
||||
case DATA_VISCIDUS:
|
||||
return ViscidusGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
@@ -168,15 +156,12 @@ public:
|
||||
else
|
||||
BugTrioDeathCount = 0;
|
||||
break;
|
||||
|
||||
case DATA_VEKLOR_DEATH:
|
||||
IsBossDied[1] = true;
|
||||
break;
|
||||
|
||||
case DATA_VEKNILASH_DEATH:
|
||||
IsBossDied[2] = true;
|
||||
break;
|
||||
|
||||
case DATA_CTHUN_PHASE:
|
||||
CthunPhase = data;
|
||||
break;
|
||||
@@ -193,7 +178,7 @@ public:
|
||||
case DATA_OURO:
|
||||
if (state == FAIL)
|
||||
{
|
||||
if (Creature* ouroSpawner = GetCreature(DATA_OURO))
|
||||
if (Creature* ouroSpawner = GetCreature(DATA_OURO_SPAWNER))
|
||||
ouroSpawner->Respawn();
|
||||
}
|
||||
break;
|
||||
@@ -224,7 +209,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SHADOW_FROST_REFLECT = 19595,
|
||||
SPELL_FIRE_ARCANE_REFLECT = 13022,
|
||||
SPELL_METEOR = 26558,
|
||||
SPELL_PLAGUE = 26556,
|
||||
SPELL_SHADOW_STORM = 26555,
|
||||
SPELL_THUNDERCLAP = 26554,
|
||||
|
||||
SPELL_ENRAGE = 14204,
|
||||
SPELL_EXPLODE = 25699,
|
||||
|
||||
SPELL_SUMMON_WARRIOR = 17431,
|
||||
SPELL_SUMMON_SWARMGUARD = 17430,
|
||||
|
||||
SPELL_SUMMON_LARGE_OBSIDIAN_CHUNK = 27630, // Server-side
|
||||
|
||||
TALK_ENRAGE = 0
|
||||
};
|
||||
|
||||
struct npc_anubisath_defender : public ScriptedAI
|
||||
{
|
||||
npc_anubisath_defender(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_enraged = false;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoCastSelf(urand(0, 1) ? SPELL_SHADOW_FROST_REFLECT : SPELL_FIRE_ARCANE_REFLECT, true);
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
_scheduler.Schedule(6s, 10s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1))
|
||||
DoCast(target, SPELL_METEOR, true);
|
||||
context.Repeat(6s, 10s);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_scheduler.Schedule(6s, 10s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1))
|
||||
DoCast(target, SPELL_PLAGUE, true);
|
||||
context.Repeat(6s, 10s);
|
||||
});
|
||||
}
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
_scheduler.Schedule(5s, 8s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_THUNDERCLAP, true);
|
||||
context.Repeat(5s, 8s);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_scheduler.Schedule(5s, 8s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_SHADOW_STORM, true);
|
||||
context.Repeat(5s, 8s);
|
||||
});
|
||||
}
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
_scheduler.Schedule(3s, 5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_WARRIOR, true);
|
||||
context.Repeat(12s, 16s);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_scheduler.Schedule(3s, 5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_SUMMON_SWARMGUARD, true);
|
||||
context.Repeat(12s, 16s);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_LARGE_OBSIDIAN_CHUNK, true);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
if (!_enraged && me->HealthBelowPctDamaged(10, damage))
|
||||
{
|
||||
_enraged = true;
|
||||
damage = 0;
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
Talk(TALK_ENRAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastSelf(SPELL_EXPLODE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.Update(diff,
|
||||
std::bind(&ScriptedAI::DoMeleeAttackIfReady, this));
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
bool _enraged;
|
||||
};
|
||||
|
||||
void AddSC_temple_of_ahnqiraj()
|
||||
{
|
||||
RegisterTempleOfAhnQirajCreatureAI(npc_anubisath_defender);
|
||||
}
|
||||
@@ -25,25 +25,30 @@
|
||||
enum DataTypes
|
||||
{
|
||||
DATA_SKERAM = 1,
|
||||
DATA_KRI = 2,
|
||||
DATA_VEM = 3,
|
||||
DATA_YAUJ = 4,
|
||||
DATA_BUG_TRIO = 5,
|
||||
DATA_VEKLOR = 6,
|
||||
DATA_VEKLORISDEAD = 7,
|
||||
DATA_VEKLOR_DEATH = 8,
|
||||
DATA_VEKNILASH = 9,
|
||||
DATA_VEKNILASHISDEAD = 10,
|
||||
DATA_VEKNILASH_DEATH = 11,
|
||||
DATA_FANKRISS = 12,
|
||||
DATA_OURO = 13,
|
||||
DATA_OURO_SPAWNER = 14,
|
||||
DATA_BUG_TRIO_DEATH = 15,
|
||||
DATA_CTHUN_PHASE = 20,
|
||||
DATA_VISCIDUS = 21,
|
||||
DATA_SARTURA = 22,
|
||||
DATA_BUG_TRIO = 2,
|
||||
DATA_SARTURA = 3,
|
||||
DATA_FANKRISS = 4,
|
||||
DATA_VISCIDUS = 5,
|
||||
DATA_HUHURAN = 6,
|
||||
DATA_TWIN_EMPERORS = 7,
|
||||
DATA_OURO = 8,
|
||||
DATA_CTHUN = 9,
|
||||
|
||||
DATA_EYE_OF_CTHUN = 23
|
||||
MAX_BOSS_NUMBER = 10,
|
||||
|
||||
DATA_KRI = 10,
|
||||
DATA_VEM = 11,
|
||||
DATA_YAUJ = 12,
|
||||
DATA_BUG_TRIO_DEATH = 13,
|
||||
DATA_OURO_SPAWNER = 14,
|
||||
DATA_VEKLOR = 15,
|
||||
DATA_VEKLORISDEAD = 16,
|
||||
DATA_VEKLOR_DEATH = 17,
|
||||
DATA_VEKNILASH = 18,
|
||||
DATA_VEKNILASHISDEAD = 19,
|
||||
DATA_VEKNILASH_DEATH = 20,
|
||||
DATA_CTHUN_PHASE = 21,
|
||||
DATA_EYE_OF_CTHUN = 22
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
@@ -66,6 +71,7 @@ enum Creatures
|
||||
NPC_VEM = 15544,
|
||||
NPC_KRI = 15511,
|
||||
NPC_YAUJ = 15543,
|
||||
NPC_HUHURAN = 15509,
|
||||
NPC_VEKLOR = 15276,
|
||||
NPC_VEKNILASH = 15275,
|
||||
NPC_OURO = 15517,
|
||||
|
||||
@@ -69,6 +69,7 @@ void AddSC_boss_skeram();
|
||||
void AddSC_boss_twinemperors();
|
||||
void AddSC_boss_ouro();
|
||||
void AddSC_npc_anubisath_sentinel();
|
||||
void AddSC_temple_of_ahnqiraj();
|
||||
void AddSC_instance_temple_of_ahnqiraj();
|
||||
void AddSC_instance_wailing_caverns(); //Wailing caverns
|
||||
void AddSC_zulfarrak();
|
||||
@@ -152,6 +153,7 @@ void AddKalimdorScripts()
|
||||
AddSC_boss_twinemperors();
|
||||
AddSC_boss_ouro();
|
||||
AddSC_npc_anubisath_sentinel();
|
||||
AddSC_temple_of_ahnqiraj();
|
||||
AddSC_instance_temple_of_ahnqiraj();
|
||||
AddSC_instance_wailing_caverns(); //Wailing caverns
|
||||
AddSC_zulfarrak();
|
||||
|
||||
@@ -1877,6 +1877,12 @@ public:
|
||||
uint8 _rings = (local_tm.tm_hour) % 12;
|
||||
_rings = (_rings == 0) ? 12 : _rings; // 00:00 and 12:00
|
||||
|
||||
// Dwarf hourly horn should only play a single time, each time the next hour begins.
|
||||
if (_soundId == BELLTOLLDWARFGNOME)
|
||||
{
|
||||
_rings = 1;
|
||||
}
|
||||
|
||||
// Schedule ring event
|
||||
for (auto i = 0; i < _rings; ++i)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user