mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-24 14:16:31 +00:00
Merge branch 'master' of github.com:azerothcore/azerothcore-wotlk into Playerbot
This commit is contained in:
@@ -290,7 +290,7 @@ public:
|
||||
bool OnGossipHello(Player* player, GameObject* go) override
|
||||
{
|
||||
if (InstanceScript* instance = go->GetInstanceScript())
|
||||
if (instance->GetData(DATA_EGG_EVENT) != DONE && !player->HasAura(SPELL_MIND_EXHAUSTION))
|
||||
if (instance->GetData(DATA_EGG_EVENT) != DONE && !player->HasAura(SPELL_MIND_EXHAUSTION) && !player->GetPet())
|
||||
if (Creature* razor = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_RAZORGORE_THE_UNTAMED)))
|
||||
{
|
||||
razor->AI()->SetGUID(player->GetGUID());
|
||||
|
||||
@@ -54,9 +54,11 @@ struct boss_curator : public BossAI
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_POWER_BURN, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_POWER_BURN, true);
|
||||
ScheduleHealthCheckEvent(15, [&] {
|
||||
DoCastSelf(SPELL_ARCANE_INFUSION, true);
|
||||
Talk(SAY_ENRAGE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
DoCastSelf(SPELL_ARCANE_INFUSION, true);
|
||||
Talk(SAY_ENRAGE);
|
||||
});
|
||||
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA));
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
@@ -85,7 +87,7 @@ struct boss_curator : public BossAI
|
||||
DoCastSelf(SPELL_ASTRAL_DECONSTRUCTION, true);
|
||||
}).Schedule(10s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, 45.0f, true, false))
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 45.0f, true, false))
|
||||
{
|
||||
DoCast(target, SPELL_HATEFUL_BOLT);
|
||||
}
|
||||
|
||||
@@ -218,13 +218,17 @@ struct boss_netherspite : public BossAI
|
||||
}
|
||||
}).Schedule(10s, PORTAL_PHASE, [this](TaskContext context)
|
||||
{
|
||||
UpdatePortals();
|
||||
context.Repeat(1s);
|
||||
UpdatePortals();
|
||||
context.Repeat(1s);
|
||||
}).Schedule(10s, PORTAL_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_EMPOWERMENT);
|
||||
me->AddAura(SPELL_NETHERBURN_AURA, me);
|
||||
context.Repeat(90s);
|
||||
DoCastSelf(SPELL_EMPOWERMENT);
|
||||
me->AddAura(SPELL_NETHERBURN_AURA, me);
|
||||
context.Repeat(90s);
|
||||
}).Schedule(15s, PORTAL_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_VOIDZONE, 1, 45.0f, true, true);
|
||||
context.Repeat(15s);
|
||||
});
|
||||
Talk(EMOTE_PHASE_PORTAL);
|
||||
}
|
||||
@@ -237,13 +241,10 @@ struct boss_netherspite : public BossAI
|
||||
DoCastSelf(SPELL_BANISH_VISUAL, true);
|
||||
DoCastSelf(SPELL_BANISH_ROOT, true);
|
||||
DestroyPortals();
|
||||
scheduler.Schedule(30s, [this](TaskContext /*context*/)
|
||||
scheduler.Schedule(30s, [this](TaskContext)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
SwitchToPortalPhase();
|
||||
return;
|
||||
}
|
||||
SwitchToPortalPhase();
|
||||
return;
|
||||
}).Schedule(10s, VANISH_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_NETHERBREATH, 0, 40.0f, true);
|
||||
@@ -270,11 +271,7 @@ struct boss_netherspite : public BossAI
|
||||
HandleDoors(false);
|
||||
SwitchToPortalPhase();
|
||||
DoZoneInCombat();
|
||||
scheduler.Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_VOIDZONE, 1, 45.0f, true, true);
|
||||
context.Repeat(15s);
|
||||
}).Schedule(9min, [this](TaskContext /*context*/)
|
||||
scheduler.Schedule(9min, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (!berserk)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "karazhan.h"
|
||||
|
||||
enum PrinceSay
|
||||
@@ -47,11 +48,13 @@ enum Spells
|
||||
|
||||
enum creatures
|
||||
{
|
||||
NPC_NETHERSPITE_INFERNAL = 17646,
|
||||
NPC_MALCHEZARS_AXE = 17650,
|
||||
INFERNAL_MODEL_INVISIBLE = 11686,
|
||||
SPELL_INFERNAL_RELAY = 33814, // 30835,
|
||||
EQUIP_ID_AXE = 33542
|
||||
NPC_NETHERSPITE_INFERNAL = 17646,
|
||||
NPC_MALCHEZAARS_AXE = 17650,
|
||||
INFERNAL_MODEL_INVISIBLE = 11686,
|
||||
SPELL_INFERNAL_RELAY = 33814, // 30835,
|
||||
SPELL_INFERNAL_RELAY_ONE = 30834,
|
||||
SPELL_INFERNAL_RELAY_TWO = 30835,
|
||||
EQUIP_ID_AXE = 33542
|
||||
};
|
||||
|
||||
enum EventGroups
|
||||
@@ -68,44 +71,19 @@ enum Phases
|
||||
PHASE_THREE = 3
|
||||
};
|
||||
|
||||
struct InfernalPoint
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
#define INFERNAL_Z 275.5f
|
||||
|
||||
/*static InfernalPoint InfernalPoints[] =
|
||||
{
|
||||
{ -10922.8f, -1985.2f },
|
||||
{ -10916.2f, -1996.2f },
|
||||
{ -10932.2f, -2008.1f },
|
||||
{ -10948.8f, -2022.1f },
|
||||
{ -10958.7f, -1997.7f },
|
||||
{ -10971.5f, -1997.5f },
|
||||
{ -10990.8f, -1995.1f },
|
||||
{ -10989.8f, -1976.5f },
|
||||
{ -10971.6f, -1973.0f },
|
||||
{ -10955.5f, -1974.0f },
|
||||
{ -10939.6f, -1969.8f },
|
||||
{ -10958.0f, -1952.2f },
|
||||
{ -10941.7f, -1954.8f },
|
||||
{ -10943.1f, -1988.5f },
|
||||
{ -10948.8f, -2005.1f },
|
||||
{ -10984.0f, -2019.3f },
|
||||
{ -10932.8f, -1979.6f },
|
||||
{ -10935.7f, -1996.0f }
|
||||
};*/
|
||||
|
||||
struct boss_malchezaar : public BossAI
|
||||
{
|
||||
boss_malchezaar(Creature* creature) : BossAI(creature, DATA_MALCHEZZAR) { }
|
||||
boss_malchezaar(Creature* creature) : BossAI(creature, DATA_MALCHEZAAR) { }
|
||||
|
||||
std::list<Creature*> relays;
|
||||
std::list<Creature*> infernalTargets;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_phase = 1;
|
||||
clearweapons();
|
||||
positions.clear();
|
||||
relays.clear();
|
||||
infernalTargets.clear();
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_GO_NETHER_DOOR), true);
|
||||
}
|
||||
|
||||
@@ -145,7 +123,7 @@ struct boss_malchezaar : public BossAI
|
||||
_phase = PHASE_THREE;
|
||||
clearweapons();
|
||||
|
||||
me->SummonCreature(NPC_MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
|
||||
me->SummonCreature(NPC_MALCHEZAARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
|
||||
|
||||
scheduler.Schedule(20s, 30s, [this](TaskContext context)
|
||||
{
|
||||
@@ -174,15 +152,52 @@ struct boss_malchezaar : public BossAI
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_GO_NETHER_DOOR), true);
|
||||
}
|
||||
|
||||
void SpawnInfernal(Creature* relay, Creature* target)
|
||||
{
|
||||
if (Creature* infernal = relay->SummonCreature(NPC_NETHERSPITE_INFERNAL, target->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 180000))
|
||||
{
|
||||
infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE);
|
||||
relay->CastSpell(infernal, SPELL_INFERNAL_RELAY);
|
||||
infernal->SetFaction(me->GetFaction());
|
||||
infernal->SetControlled(true, UNIT_STATE_ROOT);
|
||||
relay->CastSpell(infernal, SPELL_INFERNAL_RELAY);
|
||||
summons.Summon(infernal);
|
||||
}
|
||||
}
|
||||
|
||||
bool MaxSpawns(std::list<Creature*> spawns)
|
||||
{
|
||||
return spawns.size() == 0;
|
||||
}
|
||||
|
||||
Creature* PickTarget(std::list<Creature*> pickList)
|
||||
{
|
||||
uint8 index = urand(0, pickList.size()-1);
|
||||
uint8 counter = 0;
|
||||
for (Creature* creature : pickList)
|
||||
{
|
||||
if (counter == index)
|
||||
{
|
||||
return creature;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
|
||||
me->GetCreaturesWithEntryInRange(relays, 250.0f, NPC_INFERNAL_RELAY);
|
||||
me->GetCreaturesWithEntryInRange(infernalTargets, 100.0f, NPC_INFERNAL_TARGET);
|
||||
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_GO_NETHER_DOOR), false);
|
||||
|
||||
scheduler.Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
EnfeebleHealthEffect();
|
||||
DoCastAOE(SPELL_ENFEEBLE);
|
||||
|
||||
scheduler.Schedule(9s, [this](TaskContext)
|
||||
{
|
||||
@@ -199,23 +214,30 @@ struct boss_malchezaar : public BossAI
|
||||
context.Repeat();
|
||||
}).Schedule(40s, [this](TaskContext context)
|
||||
{
|
||||
Position pos = me->GetRandomNearPosition(40.0);;
|
||||
|
||||
if (Creature* RELAY = me->FindNearestCreature(NPC_RELAY, 100.0f))
|
||||
if (!MaxSpawns(infernalTargets)) // only spawn infernal when the area is not full
|
||||
{
|
||||
if (Creature* infernal = RELAY->SummonCreature(NPC_NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000))
|
||||
Talk(SAY_SUMMON);
|
||||
if (Creature* infernalRelayOne = relays.back())
|
||||
{
|
||||
infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE);
|
||||
infernal->SetFaction(me->GetFaction());
|
||||
infernal->SetControlled(true, UNIT_STATE_ROOT);
|
||||
RELAY->AI()->DoCast(infernal, SPELL_INFERNAL_RELAY);
|
||||
summons.Summon(infernal);
|
||||
if (Creature* infernalRelayTwo = relays.front())
|
||||
{
|
||||
infernalRelayOne->CastSpell(infernalRelayTwo, SPELL_INFERNAL_RELAY_ONE, true);
|
||||
|
||||
if (Creature* infernalTarget = PickTarget(infernalTargets))
|
||||
{
|
||||
infernalTargets.remove(infernalTarget);
|
||||
SpawnInfernal(infernalRelayTwo, infernalTarget);
|
||||
|
||||
scheduler.Schedule(3min, [this, infernalTarget](TaskContext)
|
||||
{
|
||||
infernalTargets.push_back(infernalTarget); //adds to list again
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.Repeat(_phase == PHASE_THREE ? 15s : 45s);
|
||||
|
||||
Talk(SAY_SUMMON);
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_WORD_PAIN);
|
||||
@@ -224,23 +246,12 @@ struct boss_malchezaar : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
void EnfeebleHealthEffect()
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||
{
|
||||
std::list<Unit*> targetList;
|
||||
SelectTargetList(targetList, 5, SelectTargetMethod::Random, 1, [&](Unit* u) { return u->IsAlive() && u->IsPlayer(); });
|
||||
|
||||
if (targetList.empty())
|
||||
return;
|
||||
|
||||
for (auto const& target : targetList)
|
||||
if (spell->Id == SPELL_ENFEEBLE)
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
_enfeebleTargets[target->GetGUID()] = target->GetHealth();
|
||||
|
||||
me->CastSpell(target, SPELL_ENFEEBLE, true);
|
||||
target->SetHealth(1);
|
||||
}
|
||||
_enfeebleTargets[target->GetGUID()] = target->GetHealth();
|
||||
target->SetHealth(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +272,6 @@ struct boss_malchezaar : public BossAI
|
||||
private:
|
||||
uint32 _phase;
|
||||
std::map<ObjectGuid, uint32> _enfeebleTargets;
|
||||
std::vector<InfernalPoint*> positions;
|
||||
};
|
||||
|
||||
struct npc_netherspite_infernal : public ScriptedAI
|
||||
@@ -357,9 +367,43 @@ struct npc_malchezaar_axe : public ScriptedAI
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
// 30843 - Enfeeble
|
||||
class spell_malchezaar_enfeeble : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_malchezaar_enfeeble);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetCaster()->ToCreature();
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
uint8 maxSize = 5;
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
targets.remove_if([caster](WorldObject const* target) -> bool
|
||||
{
|
||||
// Should not target current victim.
|
||||
return caster->GetVictim() == target;
|
||||
});
|
||||
|
||||
if (targets.size() > maxSize)
|
||||
{
|
||||
Acore::Containers::RandomResize(targets, maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malchezaar_enfeeble::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_malchezaar()
|
||||
{
|
||||
RegisterKarazhanCreatureAI(boss_malchezaar);
|
||||
RegisterKarazhanCreatureAI(npc_malchezaar_axe);
|
||||
RegisterKarazhanCreatureAI(npc_netherspite_infernal);
|
||||
RegisterSpellScript(spell_malchezaar_enfeeble);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ enum ShadeOfAran
|
||||
|
||||
//Creature Spells
|
||||
SPELL_CIRCULAR_BLIZZARD = 29951,
|
||||
SPELL_WATERBOLT = 31012,
|
||||
SPELL_SHADOW_PYRO = 29978,
|
||||
|
||||
//Creatures
|
||||
@@ -77,6 +76,8 @@ enum Groups
|
||||
GROUP_DRINKING = 1
|
||||
};
|
||||
|
||||
Position const roomCenter = {-11158.f, -1920.f};
|
||||
|
||||
Position const elementalPos[4] =
|
||||
{
|
||||
{-11168.1f, -1939.29f, 232.092f, 1.46f},
|
||||
@@ -103,12 +104,10 @@ struct boss_shade_of_aran : public BossAI
|
||||
|
||||
uint32 CurrentNormalSpell;
|
||||
|
||||
bool Drinking;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
drinkScheduler.CancelAll();
|
||||
_drinkScheduler.CancelAll();
|
||||
LastSuperSpell = rand() % 3;
|
||||
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
@@ -120,7 +119,7 @@ struct boss_shade_of_aran : public BossAI
|
||||
_fireCooledDown = true;
|
||||
_frostCooledDown = true;
|
||||
|
||||
Drinking = false;
|
||||
_drinking = false;
|
||||
|
||||
// Not in progress
|
||||
instance->SetData(DATA_ARAN, NOT_STARTED);
|
||||
@@ -149,6 +148,23 @@ struct boss_shade_of_aran : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
bool CheckAranInRoom()
|
||||
{
|
||||
return me->GetDistance2d(roomCenter.GetPositionX(), roomCenter.GetPositionY()) < 45.0f;
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (who && who->isTargetableForAttack() && me->GetReactState() != REACT_PASSIVE)
|
||||
{
|
||||
if (me->Attack(who, false))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(who, 45.0f, 0);
|
||||
me->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
@@ -207,9 +223,9 @@ struct boss_shade_of_aran : public BossAI
|
||||
libraryDoor->SetGoState(GO_STATE_READY);
|
||||
libraryDoor->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}).Schedule(1ms, [this](TaskContext context)
|
||||
}).Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
if (!me->IsNonMeleeSpellCast(false) && !_drinking)
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
|
||||
if (!target)
|
||||
@@ -242,93 +258,144 @@ struct boss_shade_of_aran : public BossAI
|
||||
DoCast(target, CurrentNormalSpell);
|
||||
}
|
||||
}
|
||||
context.Repeat(10s);
|
||||
context.Repeat(2s);
|
||||
}).Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
switch (urand(0, 1))
|
||||
if (!_drinking)
|
||||
{
|
||||
case 0:
|
||||
DoCastSelf(SPELL_AOE_CS);
|
||||
break;
|
||||
case 1:
|
||||
DoCastRandomTarget(SPELL_CHAINSOFICE);
|
||||
break;
|
||||
switch (urand(0, 1))
|
||||
{
|
||||
case 0:
|
||||
DoCastSelf(SPELL_AOE_CS);
|
||||
break;
|
||||
case 1:
|
||||
DoCastRandomTarget(SPELL_CHAINSOFICE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
context.Repeat(5s, 20s);
|
||||
}).Schedule(35s, [this](TaskContext context)
|
||||
{
|
||||
uint8 Available[2];
|
||||
|
||||
switch (LastSuperSpell)
|
||||
if (!_drinking)
|
||||
{
|
||||
case SUPER_AE:
|
||||
Available[0] = SUPER_FLAME;
|
||||
Available[1] = SUPER_BLIZZARD;
|
||||
break;
|
||||
case SUPER_FLAME:
|
||||
Available[0] = SUPER_AE;
|
||||
Available[1] = SUPER_BLIZZARD;
|
||||
break;
|
||||
case SUPER_BLIZZARD:
|
||||
Available[0] = SUPER_FLAME;
|
||||
Available[1] = SUPER_AE;
|
||||
break;
|
||||
}
|
||||
uint8 Available[2];
|
||||
|
||||
LastSuperSpell = Available[urand(0, 1)];
|
||||
switch (LastSuperSpell)
|
||||
{
|
||||
case SUPER_AE:
|
||||
Available[0] = SUPER_FLAME;
|
||||
Available[1] = SUPER_BLIZZARD;
|
||||
break;
|
||||
case SUPER_FLAME:
|
||||
Available[0] = SUPER_AE;
|
||||
Available[1] = SUPER_BLIZZARD;
|
||||
break;
|
||||
case SUPER_BLIZZARD:
|
||||
Available[0] = SUPER_FLAME;
|
||||
Available[1] = SUPER_AE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (LastSuperSpell)
|
||||
{
|
||||
case SUPER_AE:
|
||||
Talk(SAY_EXPLOSION);
|
||||
LastSuperSpell = Available[urand(0, 1)];
|
||||
|
||||
DoCastSelf(SPELL_BLINK_CENTER, true);
|
||||
DoCastSelf(SPELL_PLAYERPULL, true);
|
||||
DoCastSelf(SPELL_MASSSLOW, true);
|
||||
DoCastSelf(SPELL_AEXPLOSION, false);
|
||||
break;
|
||||
switch (LastSuperSpell)
|
||||
{
|
||||
case SUPER_AE:
|
||||
Talk(SAY_EXPLOSION);
|
||||
|
||||
case SUPER_FLAME:
|
||||
Talk(SAY_FLAMEWREATH);
|
||||
DoCastSelf(SPELL_BLINK_CENTER, true);
|
||||
DoCastSelf(SPELL_PLAYERPULL, true);
|
||||
DoCastSelf(SPELL_MASSSLOW, true);
|
||||
DoCastSelf(SPELL_AEXPLOSION, false);
|
||||
break;
|
||||
|
||||
scheduler.Schedule(20s, GROUP_FLAMEWREATH, [this](TaskContext)
|
||||
{
|
||||
scheduler.CancelGroup(GROUP_FLAMEWREATH);
|
||||
}).Schedule(500ms, GROUP_FLAMEWREATH, [this](TaskContext context)
|
||||
{
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
case SUPER_FLAME:
|
||||
Talk(SAY_FLAMEWREATH);
|
||||
|
||||
scheduler.Schedule(20s, GROUP_FLAMEWREATH, [this](TaskContext)
|
||||
{
|
||||
if (!FlameWreathTarget[i])
|
||||
continue;
|
||||
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, FlameWreathTarget[i]);
|
||||
if (unit && !unit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
|
||||
scheduler.CancelGroup(GROUP_FLAMEWREATH);
|
||||
}).Schedule(500ms, GROUP_FLAMEWREATH, [this](TaskContext context)
|
||||
{
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
{
|
||||
unit->CastSpell(unit, 20476, true, 0, 0, me->GetGUID());
|
||||
FlameWreathTarget[i].Clear();
|
||||
if (!FlameWreathTarget[i])
|
||||
continue;
|
||||
|
||||
Unit* unit = ObjectAccessor::GetUnit(*me, FlameWreathTarget[i]);
|
||||
if (unit && !unit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3))
|
||||
{
|
||||
unit->CastSpell(unit, 20476, true, 0, 0, me->GetGUID());
|
||||
FlameWreathTarget[i].Clear();
|
||||
}
|
||||
}
|
||||
context.Repeat(500ms);
|
||||
});
|
||||
|
||||
FlameWreathTarget[0].Clear();
|
||||
FlameWreathTarget[1].Clear();
|
||||
FlameWreathTarget[2].Clear();
|
||||
|
||||
FlameWreathEffect();
|
||||
break;
|
||||
|
||||
case SUPER_BLIZZARD:
|
||||
Talk(SAY_BLIZZARD);
|
||||
|
||||
if (Creature* pSpawn = me->SummonCreature(NPC_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000))
|
||||
{
|
||||
pSpawn->SetFaction(me->GetFaction());
|
||||
pSpawn->CastSpell(me, SPELL_CIRCULAR_BLIZZARD, false);
|
||||
}
|
||||
context.Repeat(500ms);
|
||||
});
|
||||
|
||||
FlameWreathTarget[0].Clear();
|
||||
FlameWreathTarget[1].Clear();
|
||||
FlameWreathTarget[2].Clear();
|
||||
|
||||
FlameWreathEffect();
|
||||
break;
|
||||
|
||||
case SUPER_BLIZZARD:
|
||||
Talk(SAY_BLIZZARD);
|
||||
|
||||
if (Creature* pSpawn = me->SummonCreature(NPC_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000))
|
||||
{
|
||||
pSpawn->SetFaction(me->GetFaction());
|
||||
pSpawn->CastSpell(me, SPELL_CIRCULAR_BLIZZARD, false);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
context.Repeat(35s, 40s);
|
||||
}).Schedule(1s, [this](TaskContext context){
|
||||
if (me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA) * 100 / me->GetMaxPower(POWER_MANA)) < 20)
|
||||
{
|
||||
_drinking = true;
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
Talk(SAY_DRINK);
|
||||
DoCastSelf(SPELL_MASS_POLY, true);
|
||||
DoCastSelf(SPELL_CONJURE, false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
DoCastSelf(SPELL_DRINK, true);
|
||||
_currentHealth = me->GetHealth();
|
||||
_drinkScheduler.Schedule(500ms, GROUP_DRINKING, [this](TaskContext context)
|
||||
{
|
||||
//check for damage to interrupt
|
||||
if (me->GetHealth() < _currentHealth)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_DRINK);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000);
|
||||
DoCastSelf(SPELL_POTION, false);
|
||||
DoCastSelf(SPELL_AOE_PYROBLAST, false);
|
||||
_drinkScheduler.CancelGroup(GROUP_DRINKING);
|
||||
_drinking = false;
|
||||
} else
|
||||
{
|
||||
context.Repeat(500ms);
|
||||
}
|
||||
}).Schedule(10s, GROUP_DRINKING, [this](TaskContext)
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000);
|
||||
DoCastSelf(SPELL_POTION, true);
|
||||
DoCastSelf(SPELL_AOE_PYROBLAST, false);
|
||||
_drinkScheduler.CancelGroup(GROUP_DRINKING);
|
||||
_drinking = false;
|
||||
});
|
||||
context.Repeat(12s); //semi-arbitrary duration to envelop drinking duration
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat(1s);
|
||||
}
|
||||
}).Schedule(12min, [this](TaskContext context)
|
||||
{
|
||||
for (uint32 i = 0; i < 5; ++i)
|
||||
@@ -384,70 +451,21 @@ struct boss_shade_of_aran : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
drinkScheduler.Update(diff);
|
||||
_drinkScheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA) * 100 / me->GetMaxPower(POWER_MANA)) < 20)
|
||||
if (!CheckAranInRoom())
|
||||
{
|
||||
Drinking = true;
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
Talk(SAY_DRINK);
|
||||
|
||||
scheduler.DelayAll(10s);
|
||||
DoCastSelf(SPELL_MASS_POLY, true);
|
||||
DoCastSelf(SPELL_CONJURE, false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
DoCastSelf(SPELL_DRINK, true);
|
||||
_currentHealth = me->GetHealth();
|
||||
drinkScheduler.Schedule(500ms, GROUP_DRINKING, [this](TaskContext context)
|
||||
{
|
||||
//check for damage to interrupt
|
||||
if(CheckDamageDuringDrinking(_currentHealth))
|
||||
{
|
||||
Drinking = false;
|
||||
me->RemoveAurasDueToSpell(SPELL_DRINK);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000);
|
||||
DoCastSelf(SPELL_POTION, false);
|
||||
DoCastSelf(SPELL_AOE_PYROBLAST, false);
|
||||
drinkScheduler.CancelGroup(GROUP_DRINKING);
|
||||
} else {
|
||||
context.Repeat(500ms);
|
||||
}
|
||||
}).Schedule(10s, GROUP_DRINKING, [this](TaskContext)
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA) - 32000);
|
||||
DoCastSelf(SPELL_POTION, true);
|
||||
DoCastSelf(SPELL_AOE_PYROBLAST, false);
|
||||
|
||||
Drinking = false;
|
||||
drinkScheduler.CancelGroup(GROUP_DRINKING);
|
||||
});
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_arcaneCooledDown && _fireCooledDown && _frostCooledDown && !Drinking)
|
||||
if (_arcaneCooledDown && _fireCooledDown && _frostCooledDown && !_drinking)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool CheckDamageDuringDrinking(uint32 oldHealth)
|
||||
{
|
||||
if (Drinking)
|
||||
{
|
||||
if (me->GetHealth() < oldHealth)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*pAttacker*/, SpellInfo const* Spell) override
|
||||
{
|
||||
//We only care about interrupt effects and only if they are durring a spell currently being cast
|
||||
@@ -476,52 +494,16 @@ struct boss_shade_of_aran : public BossAI
|
||||
}
|
||||
}
|
||||
private:
|
||||
TaskScheduler drinkScheduler;
|
||||
TaskScheduler _drinkScheduler;
|
||||
|
||||
bool _arcaneCooledDown;
|
||||
bool _fireCooledDown;
|
||||
bool _frostCooledDown;
|
||||
bool _drinking;
|
||||
uint32 _currentHealth;
|
||||
};
|
||||
|
||||
struct npc_aran_elemental : public ScriptedAI
|
||||
{
|
||||
npc_aran_elemental(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(2s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_WATERBOLT);
|
||||
context.Repeat(2s);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
void AddSC_boss_shade_of_aran()
|
||||
{
|
||||
RegisterKarazhanCreatureAI(boss_shade_of_aran);
|
||||
RegisterKarazhanCreatureAI(npc_aran_elemental);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ enum Spells
|
||||
enum Creatures
|
||||
{
|
||||
NPC_DEMONCHAINS = 17248,
|
||||
NPC_FIENDISHIMP = 17267,
|
||||
NPC_PORTAL = 17265
|
||||
};
|
||||
|
||||
@@ -146,64 +145,6 @@ private:
|
||||
ObjectGuid sacrificeGUID;
|
||||
};
|
||||
|
||||
struct npc_fiendish_portal : public PassiveAI
|
||||
{
|
||||
npc_fiendish_portal(Creature* creature) : PassiveAI(creature), summons(me) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
DespawnAllImp();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
|
||||
void DespawnAllImp()
|
||||
{
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
private:
|
||||
SummonList summons;
|
||||
};
|
||||
|
||||
struct npc_fiendish_imp : public ScriptedAI
|
||||
{
|
||||
npc_fiendish_imp(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(2s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_FIREBOLT);
|
||||
context.Repeat(2200ms);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct boss_terestian_illhoof : public BossAI
|
||||
{
|
||||
boss_terestian_illhoof(Creature* creature) : BossAI(creature, DATA_TERESTIAN)
|
||||
@@ -218,20 +159,6 @@ struct boss_terestian_illhoof : public BossAI
|
||||
{
|
||||
_Reset();
|
||||
SummonKilrek();
|
||||
portalsCount = 0;
|
||||
berserk = false;
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (portalGUID[i])
|
||||
{
|
||||
if (Creature* pPortal = ObjectAccessor::GetCreature(*me, portalGUID[i]))
|
||||
{
|
||||
pPortal->AI()->Reset();
|
||||
pPortal->DespawnOrUnsummon();
|
||||
}
|
||||
portalGUID[i].Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonKilrek()
|
||||
@@ -256,10 +183,13 @@ struct boss_terestian_illhoof : public BossAI
|
||||
DoZoneInCombat();
|
||||
scheduler.Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit * target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, false))
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, false))
|
||||
{
|
||||
DoCast(target, SPELL_SACRIFICE, true);
|
||||
target->CastSpell(target, SPELL_SUMMON_DEMONCHAINS, true);
|
||||
target->m_Events.AddEventAtOffset([target] {
|
||||
target->CastSpell(target, SPELL_SUMMON_DEMONCHAINS, true);
|
||||
}, 1s);
|
||||
|
||||
Talk(SAY_SACRIFICE);
|
||||
context.Repeat(30s);
|
||||
}
|
||||
@@ -267,31 +197,15 @@ struct boss_terestian_illhoof : public BossAI
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT);
|
||||
context.Repeat(10s);
|
||||
}).Schedule(10s, [this](TaskContext context)
|
||||
}).Schedule(10s, [this](TaskContext)
|
||||
{
|
||||
if (!portalGUID[0])
|
||||
{
|
||||
DoCastVictim(SPELL_FIENDISH_PORTAL);
|
||||
}
|
||||
if (!portalGUID[1])
|
||||
{
|
||||
DoCastVictim(SPELL_FIENDISH_PORTAL_1);
|
||||
}
|
||||
if (portalGUID[0] && portalGUID[1])
|
||||
{
|
||||
if (Creature* pPortal = ObjectAccessor::GetCreature(*me, portalGUID[urand(0, 1)]))
|
||||
{
|
||||
pPortal->CastSpell(me->GetVictim(), SPELL_SUMMON_FIENDISIMP);
|
||||
}
|
||||
context.Repeat(5s);
|
||||
}
|
||||
DoCastAOE(SPELL_FIENDISH_PORTAL);
|
||||
}).Schedule(11s, [this](TaskContext)
|
||||
{
|
||||
DoCastAOE(SPELL_FIENDISH_PORTAL_1);
|
||||
}).Schedule(10min, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (!berserk)
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK);
|
||||
berserk = true;
|
||||
}
|
||||
DoCastSelf(SPELL_BERSERK);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -299,13 +213,14 @@ struct boss_terestian_illhoof : public BossAI
|
||||
{
|
||||
if (summoned->GetEntry() == NPC_PORTAL)
|
||||
{
|
||||
portalGUID[portalsCount] = summoned->GetGUID();
|
||||
++portalsCount;
|
||||
summoned->SetReactState(REACT_PASSIVE);
|
||||
if (summoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1)
|
||||
{
|
||||
Talk(SAY_SUMMON);
|
||||
}
|
||||
}
|
||||
|
||||
summons.Summon(summoned);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
@@ -318,44 +233,14 @@ struct boss_terestian_illhoof : public BossAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (portalGUID[i])
|
||||
{
|
||||
if (Creature* pPortal = ObjectAccessor::GetCreature((*me), portalGUID[i]))
|
||||
{
|
||||
pPortal->AI()->Reset();
|
||||
pPortal->DespawnOrUnsummon();
|
||||
}
|
||||
portalGUID[i].Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool berserk;
|
||||
ObjectGuid portalGUID[2];
|
||||
uint8 portalsCount;
|
||||
};
|
||||
|
||||
void AddSC_boss_terestian_illhoof()
|
||||
{
|
||||
RegisterKarazhanCreatureAI(boss_terestian_illhoof);
|
||||
RegisterKarazhanCreatureAI(npc_fiendish_imp);
|
||||
RegisterKarazhanCreatureAI(npc_fiendish_portal);
|
||||
RegisterKarazhanCreatureAI(npc_kilrek);
|
||||
RegisterKarazhanCreatureAI(npc_demon_chain);
|
||||
}
|
||||
|
||||
@@ -508,7 +508,7 @@ struct boss_strawman : public ScriptedAI
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* Spell) override
|
||||
{
|
||||
if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand() % 10)))
|
||||
if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && roll_chance_i(10))
|
||||
{
|
||||
/*
|
||||
if (not direct damage(aoe, dot))
|
||||
|
||||
@@ -44,6 +44,7 @@ ObjectData const creatureData[] =
|
||||
{ NPC_ROMULO, DATA_ROMULO },
|
||||
{ NPC_JULIANNE, DATA_JULIANNE },
|
||||
{ NPC_NIGHTBANE, DATA_NIGHTBANE },
|
||||
{ NPC_TERESTIAN_ILLHOOF, DATA_TERESTIAN },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -122,6 +123,16 @@ public:
|
||||
case NPC_ECHO_OF_MEDIVH:
|
||||
_echoOfMedivhGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_FIENDISH_IMP:
|
||||
if (Creature* terestrian = GetCreature(DATA_TERESTIAN))
|
||||
{
|
||||
if (terestrian->AI())
|
||||
{
|
||||
terestrian->AI()->JustSummoned(creature);
|
||||
creature->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -252,7 +263,6 @@ public:
|
||||
piece->NearTeleportTo(x, y, z, o);
|
||||
piece->AI()->DoAction(ACTION_CHESS_PIECE_RESET_ORIENTATION);
|
||||
piece->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
piece->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
piece->AI()->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ enum KZDataTypes
|
||||
DATA_TERESTIAN = 7,
|
||||
DATA_NETHERSPITE = 8,
|
||||
DATA_CHESS_EVENT = 9,
|
||||
DATA_MALCHEZZAR = 10,
|
||||
DATA_MALCHEZAAR = 10,
|
||||
DATA_NIGHTBANE = 11,
|
||||
DATA_SERVANT_QUARTERS = 12,
|
||||
DATA_OPERA_OZ_DEATHCOUNT = 13,
|
||||
@@ -117,6 +117,7 @@ enum KZCreatures
|
||||
NPC_ROAR = 17546,
|
||||
NPC_STRAWMAN = 17543,
|
||||
NPC_TINHEAD = 17547,
|
||||
NPC_FIENDISH_IMP = 17267,
|
||||
|
||||
// Chess Event
|
||||
NPC_ECHO_OF_MEDIVH = 16816,
|
||||
@@ -132,7 +133,12 @@ enum KZCreatures
|
||||
NPC_ROOK_A = 21160,
|
||||
NPC_KING_H = 21752,
|
||||
NPC_KING_A = 21684,
|
||||
NPC_CHESS_EVENT_MEDIVH_CHEAT_FIRES = 22521
|
||||
NPC_CHESS_EVENT_MEDIVH_CHEAT_FIRES = 22521,
|
||||
|
||||
// Malchezaar Helpers
|
||||
NPC_INFERNAL_TARGET = 17644,
|
||||
NPC_INFERNAL_RELAY = 17645
|
||||
|
||||
};
|
||||
|
||||
enum KZGameObjectIds
|
||||
|
||||
@@ -16,9 +16,18 @@
|
||||
*/
|
||||
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "magisters_terrace.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_KALECGOS, DATA_KALECGOS },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
Position const KalecgosSpawnPos = { 164.3747f, -397.1197f, 2.151798f, 1.66219f };
|
||||
|
||||
class instance_magisters_terrace : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -29,6 +38,7 @@ public:
|
||||
instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
}
|
||||
|
||||
uint32 Encounter[MAX_ENCOUNTER];
|
||||
@@ -69,6 +79,24 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) override
|
||||
{
|
||||
if (eventId == EVENT_SPAWN_KALECGOS)
|
||||
{
|
||||
if (!GetCreature(DATA_KALECGOS) && !scheduler.IsGroupScheduled(DATA_KALECGOS))
|
||||
{
|
||||
scheduler.Schedule(1min, 1min, DATA_KALECGOS,[this](TaskContext)
|
||||
{
|
||||
if (Creature* kalecgos = instance->SummonCreature(NPC_KALECGOS, KalecgosSpawnPos))
|
||||
{
|
||||
kalecgos->GetMotionMaster()->MovePath(PATH_KALECGOS_FLIGHT, false);
|
||||
kalecgos->AI()->Talk(SAY_KALECGOS_SPAWN);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 identifier, uint32 data) override
|
||||
{
|
||||
switch (identifier)
|
||||
@@ -116,6 +144,8 @@ public:
|
||||
kael->AI()->JustSummoned(creature);
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
@@ -184,7 +214,53 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_KALECGOS_TRANSFORM = 44670,
|
||||
SPELL_TRANSFORM_VISUAL = 24085,
|
||||
SPELL_CAMERA_SHAKE = 44762,
|
||||
SPELL_ORB_KILL_CREDIT = 46307
|
||||
};
|
||||
|
||||
enum MovementPoints
|
||||
{
|
||||
POINT_ID_PREPARE_LANDING = 6
|
||||
};
|
||||
|
||||
struct npc_kalecgos : public ScriptedAI
|
||||
{
|
||||
npc_kalecgos(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type != WAYPOINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (pointId == POINT_ID_PREPARE_LANDING)
|
||||
{
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetHover(false);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
DoCastAOE(SPELL_CAMERA_SHAKE);
|
||||
me->SetObjectScale(0.6f);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
DoCastSelf(SPELL_ORB_KILL_CREDIT, true);
|
||||
DoCastSelf(SPELL_TRANSFORM_VISUAL);
|
||||
DoCastSelf(SPELL_KALECGOS_TRANSFORM);
|
||||
me->UpdateEntry(NPC_HUMAN_KALECGOS);
|
||||
}, 1s);
|
||||
}, 2s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_magisters_terrace()
|
||||
{
|
||||
new instance_magisters_terrace();
|
||||
RegisterMagistersTerraceCreatureAI(npc_kalecgos);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ enum MTData
|
||||
DATA_VEXALLUS_EVENT = 1,
|
||||
DATA_DELRISSA_EVENT = 2,
|
||||
DATA_KAELTHAS_EVENT = 3,
|
||||
MAX_ENCOUNTER = 4
|
||||
MAX_ENCOUNTER = 4,
|
||||
|
||||
DATA_KALECGOS = 5
|
||||
};
|
||||
|
||||
enum MTCreatures
|
||||
@@ -41,7 +43,9 @@ enum MTCreatures
|
||||
NPC_FEL_CRYSTAL = 24722,
|
||||
NPC_KAEL_THAS = 24664,
|
||||
NPC_PHOENIX = 21362,
|
||||
NPC_PHOENIX_EGG = 21364
|
||||
NPC_PHOENIX_EGG = 21364,
|
||||
NPC_KALECGOS = 24844,
|
||||
NPC_HUMAN_KALECGOS = 24848
|
||||
};
|
||||
|
||||
enum MTGameObjects
|
||||
@@ -54,10 +58,27 @@ enum MTGameObjects
|
||||
GO_ESCAPE_ORB = 188173
|
||||
};
|
||||
|
||||
enum InstanceEventIds
|
||||
{
|
||||
EVENT_SPAWN_KALECGOS = 16547
|
||||
};
|
||||
|
||||
enum InstanceText
|
||||
{
|
||||
SAY_KALECGOS_SPAWN = 0
|
||||
};
|
||||
|
||||
enum MovementData
|
||||
{
|
||||
PATH_KALECGOS_FLIGHT = 248440
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetMagistersTerraceAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, MTScriptName);
|
||||
}
|
||||
|
||||
#define RegisterMagistersTerraceCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetMagistersTerraceAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -695,106 +695,6 @@ class npc_fairbanks : public CreatureScript
|
||||
public:
|
||||
npc_fairbanks() : CreatureScript("npc_fairbanks") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
AddGossipItemFor(player, 0, "Curse? What's going on here, Fairbanks?", GOSSIP_SENDER_MAIN, 1);
|
||||
SendGossipMenuFor(player, 100100, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*Sender*/, uint32 uiAction) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
|
||||
switch (uiAction)
|
||||
{
|
||||
case 1:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "Mograine?", GOSSIP_SENDER_MAIN, 2);
|
||||
SendGossipMenuFor(player, 100101, creature->GetGUID());
|
||||
return true;
|
||||
case 2:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "What do you mean?", GOSSIP_SENDER_MAIN, 3);
|
||||
SendGossipMenuFor(player, 100102, creature->GetGUID());
|
||||
return true;
|
||||
case 3:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "I still do not fully understand.", GOSSIP_SENDER_MAIN, 4);
|
||||
SendGossipMenuFor(player, 100103, creature->GetGUID());
|
||||
return true;
|
||||
case 4:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "Incredible story. So how did he die?", GOSSIP_SENDER_MAIN, 5);
|
||||
SendGossipMenuFor(player, 100104, creature->GetGUID());
|
||||
return true;
|
||||
case 5:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "You mean...", GOSSIP_SENDER_MAIN, 6);
|
||||
SendGossipMenuFor(player, 100105, creature->GetGUID());
|
||||
return true;
|
||||
case 6:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "How do you know all of this?", GOSSIP_SENDER_MAIN, 7);
|
||||
SendGossipMenuFor(player, 100106, creature->GetGUID());
|
||||
return true;
|
||||
case 7:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "A thousand? For one man?", GOSSIP_SENDER_MAIN, 8);
|
||||
SendGossipMenuFor(player, 100107, creature->GetGUID());
|
||||
return true;
|
||||
case 8:
|
||||
creature->HandleEmoteCommand(5);
|
||||
AddGossipItemFor(player, 0, "Yet? Yet what?", GOSSIP_SENDER_MAIN, 9);
|
||||
SendGossipMenuFor(player, 100108, creature->GetGUID());
|
||||
return true;
|
||||
case 9:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "And did he?", GOSSIP_SENDER_MAIN, 10);
|
||||
SendGossipMenuFor(player, 100109, creature->GetGUID());
|
||||
return true;
|
||||
case 10:
|
||||
creature->HandleEmoteCommand(274);
|
||||
AddGossipItemFor(player, 0, "Continue please, Fairbanks.", GOSSIP_SENDER_MAIN, 11);
|
||||
SendGossipMenuFor(player, 100110, creature->GetGUID());
|
||||
return true;
|
||||
case 11:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "You mean...", GOSSIP_SENDER_MAIN, 12);
|
||||
SendGossipMenuFor(player, 100111, creature->GetGUID());
|
||||
return true;
|
||||
case 12:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "You were right, Fairbanks. That is tragic.", GOSSIP_SENDER_MAIN, 13);
|
||||
SendGossipMenuFor(player, 100112, creature->GetGUID());
|
||||
return true;
|
||||
case 13:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "And you did...", GOSSIP_SENDER_MAIN, 14);
|
||||
SendGossipMenuFor(player, 100113, creature->GetGUID());
|
||||
return true;
|
||||
case 14:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "You tell an incredible tale, Fairbanks. What of the blade? Is it beyond redemption?", GOSSIP_SENDER_MAIN, 15);
|
||||
SendGossipMenuFor(player, 100114, creature->GetGUID());
|
||||
return true;
|
||||
case 15:
|
||||
creature->HandleEmoteCommand(1);
|
||||
AddGossipItemFor(player, 0, "But his son is dead.", GOSSIP_SENDER_MAIN, 16);
|
||||
SendGossipMenuFor(player, 100115, creature->GetGUID());
|
||||
return true;
|
||||
case 16:
|
||||
SendGossipMenuFor(player, 100116, creature->GetGUID());
|
||||
/// @todo: we need to play these 3 emote in sequence, we play only the last one right now.
|
||||
creature->HandleEmoteCommand(274);
|
||||
creature->HandleEmoteCommand(1);
|
||||
creature->HandleEmoteCommand(397);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct npc_fairbanksAI : public SmartAI
|
||||
{
|
||||
npc_fairbanksAI(Creature* creature) : SmartAI(creature) { }
|
||||
@@ -812,7 +712,6 @@ public:
|
||||
{
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetSheath(SHEATH_STATE_UNARMED);
|
||||
me->CastSpell(me, 57767, true);
|
||||
me->SetDisplayId(16179);
|
||||
me->SetFacingToObject(player);
|
||||
|
||||
@@ -154,8 +154,8 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case DATA_RAJAXX_WAVE_ENGAGED:
|
||||
_scheduler.CancelGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
_scheduler.Schedule(2min, [this](TaskContext context)
|
||||
scheduler.CancelGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
scheduler.Schedule(2min, [this](TaskContext context)
|
||||
{
|
||||
CallNextRajaxxLeader();
|
||||
context.SetGroup(GROUP_RAJAXX_WAVE_TIMER);
|
||||
@@ -195,8 +195,8 @@ public:
|
||||
case NPC_YEGGETH:
|
||||
case NPC_PAKKON:
|
||||
case NPC_ZERRAN:
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(1s, [this, formation](TaskContext /*context*/)
|
||||
scheduler.CancelAll();
|
||||
scheduler.Schedule(1s, [this, formation](TaskContext /*context*/)
|
||||
{
|
||||
if (!formation->IsAnyMemberAlive())
|
||||
{
|
||||
@@ -212,11 +212,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void Update(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void SetGuidData(uint32 type, ObjectGuid data) override
|
||||
{
|
||||
if (type == DATA_PARALYZED)
|
||||
@@ -285,7 +280,7 @@ public:
|
||||
void ResetRajaxxWaves()
|
||||
{
|
||||
_rajaxWaveCounter = 0;
|
||||
_scheduler.CancelAll();
|
||||
scheduler.CancelAll();
|
||||
for (auto const& data : RajaxxWavesData)
|
||||
{
|
||||
if (Creature* creature = GetCreature(data.at(0)))
|
||||
@@ -308,7 +303,6 @@ public:
|
||||
ObjectGuid _andorovGUID;
|
||||
uint32 _rajaxWaveCounter;
|
||||
uint8 _buruPhase;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
|
||||
@@ -210,15 +210,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Update(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
GuidVector CThunGraspGUIDs;
|
||||
uint32 BugTrioDeathCount;
|
||||
TaskScheduler scheduler;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
* 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
|
||||
|
||||
@@ -175,6 +175,7 @@ enum Kerlonian
|
||||
|
||||
SPELL_SLEEP_VISUAL = 25148,
|
||||
SPELL_AWAKEN = 17536,
|
||||
SPELL_BEAR_FORM = 18309,
|
||||
QUEST_SLEEPER_AWAKENED = 5321,
|
||||
NPC_LILADRIS = 11219 //attackers entries unknown
|
||||
};
|
||||
@@ -194,6 +195,8 @@ public:
|
||||
void Reset() override
|
||||
{
|
||||
FallAsleepTimer = urand(10000, 45000);
|
||||
|
||||
DoCastSelf(SPELL_BEAR_FORM);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
@@ -69,219 +69,185 @@ enum Misc
|
||||
{
|
||||
GROUP_ABILITIES = 1,
|
||||
NPC_PURE_SPAWN_OF_HYDROSS = 22035,
|
||||
|
||||
EVENT_SPELL_MARK_OF_CORRUPTION1 = 1,
|
||||
EVENT_SPELL_MARK_OF_CORRUPTION2 = 2,
|
||||
EVENT_SPELL_MARK_OF_CORRUPTION3 = 3,
|
||||
EVENT_SPELL_MARK_OF_CORRUPTION4 = 4,
|
||||
EVENT_SPELL_MARK_OF_CORRUPTION5 = 5,
|
||||
EVENT_SPELL_MARK_OF_CORRUPTION6 = 6,
|
||||
EVENT_SPELL_MARK_OF_HYDROSS1 = 7,
|
||||
EVENT_SPELL_MARK_OF_HYDROSS2 = 8,
|
||||
EVENT_SPELL_MARK_OF_HYDROSS3 = 9,
|
||||
EVENT_SPELL_MARK_OF_HYDROSS4 = 10,
|
||||
EVENT_SPELL_MARK_OF_HYDROSS5 = 11,
|
||||
EVENT_SPELL_MARK_OF_HYDROSS6 = 12,
|
||||
EVENT_SPELL_WATER_TOMB = 13,
|
||||
EVENT_SPELL_VILE_SLUDGE = 14,
|
||||
EVENT_SPELL_ENRAGE = 15,
|
||||
EVENT_CHECK_AURA = 16,
|
||||
EVENT_KILL_TALK = 17
|
||||
};
|
||||
|
||||
class boss_hydross_the_unstable : public CreatureScript
|
||||
struct boss_hydross_the_unstable : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_hydross_the_unstable() : CreatureScript("boss_hydross_the_unstable") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_hydross_the_unstable(Creature* creature) : BossAI(creature, DATA_HYDROSS_THE_UNSTABLE)
|
||||
{
|
||||
return GetSerpentShrineAI<boss_hydross_the_unstableAI>(creature);
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
struct boss_hydross_the_unstableAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_hydross_the_unstableAI(Creature* creature) : BossAI(creature, DATA_HYDROSS_THE_UNSTABLE)
|
||||
BossAI::Reset();
|
||||
|
||||
_recentlySpoken = false;
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
if (!me->HasAura(SPELL_BLUE_BEAM))
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_CLEANSING_FIELD_AURA);
|
||||
}
|
||||
}
|
||||
|
||||
void SetForm(bool corrupt, bool initial)
|
||||
{
|
||||
scheduler.CancelGroup(GROUP_ABILITIES);
|
||||
DoResetThreatList();
|
||||
|
||||
if (corrupt)
|
||||
{
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
DoCastSelf(SPELL_CORRUPTION, true);
|
||||
|
||||
scheduler.Schedule(0s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_CORRUPTION1);
|
||||
}).Schedule(15s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_CORRUPTION2);
|
||||
}).Schedule(30s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_CORRUPTION3);
|
||||
}).Schedule(45s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_CORRUPTION4);
|
||||
}).Schedule(60s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_CORRUPTION5);
|
||||
}).Schedule(75s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_CORRUPTION6);
|
||||
}).Schedule(12150ms, GROUP_ABILITIES, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_VILE_SLUDGE, true);
|
||||
context.Repeat(9700ms, 32800ms);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false);
|
||||
me->RemoveAurasDueToSpell(SPELL_CORRUPTION);
|
||||
|
||||
scheduler.Schedule(0s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_HYDROSS1);
|
||||
}).Schedule(15s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_HYDROSS2);
|
||||
}).Schedule(30s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_HYDROSS3);
|
||||
}).Schedule(45s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_HYDROSS4);
|
||||
}).Schedule(60s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_HYDROSS5);
|
||||
}).Schedule(75s, GROUP_ABILITIES, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_MARK_OF_HYDROSS6);
|
||||
}).Schedule(12150ms, GROUP_ABILITIES, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_WATER_TOMB, true);
|
||||
context.Repeat(9700ms, 32800ms);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
if (initial)
|
||||
{
|
||||
BossAI::Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
if (corrupt)
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
if (!me->HasAura(SPELL_BLUE_BEAM))
|
||||
me->RemoveAurasDueToSpell(SPELL_CLEANSING_FIELD_AURA);
|
||||
}
|
||||
|
||||
void SetForm(bool corrupt, bool initial)
|
||||
{
|
||||
events.CancelEventGroup(GROUP_ABILITIES);
|
||||
DoResetThreatList();
|
||||
|
||||
if (corrupt)
|
||||
Talk(SAY_SWITCH_TO_CORRUPT);
|
||||
for (uint32 spellId = SPELL_SUMMON_CORRUPTED1; spellId <= SPELL_SUMMON_CORRUPTED4; ++spellId)
|
||||
{
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
me->CastSpell(me, SPELL_CORRUPTION, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION1, 0, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION2, 15000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION3, 30000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION4, 45000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION5, 60000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION6, 75000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_VILE_SLUDGE, 7000, GROUP_ABILITIES);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false);
|
||||
me->RemoveAurasDueToSpell(SPELL_CORRUPTION);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS1, 0, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS2, 15000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS3, 30000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS4, 45000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS5, 60000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS6, 75000, GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SPELL_WATER_TOMB, 7000, GROUP_ABILITIES);
|
||||
}
|
||||
|
||||
if (initial)
|
||||
return;
|
||||
|
||||
if (corrupt)
|
||||
{
|
||||
Talk(SAY_SWITCH_TO_CORRUPT);
|
||||
for (uint32 i = SPELL_SUMMON_CORRUPTED1; i <= SPELL_SUMMON_CORRUPTED4; ++i)
|
||||
me->CastSpell(me, i, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_SWITCH_TO_CLEAN);
|
||||
for (uint32 i = SPELL_SUMMON_PURIFIED1; i <= SPELL_SUMMON_PURIFIED4; ++i)
|
||||
me->CastSpell(me, i, true);
|
||||
DoCastSelf(spellId, true);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
else
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 600000);
|
||||
events.ScheduleEvent(EVENT_CHECK_AURA, 1000);
|
||||
SetForm(false, true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
Talk(SAY_SWITCH_TO_CLEAN);
|
||||
for (uint32 spellId = SPELL_SUMMON_PURIFIED1; spellId <= SPELL_SUMMON_PURIFIED4; ++spellId)
|
||||
{
|
||||
Talk(me->HasAura(SPELL_CORRUPTION) ? SAY_CORRUPT_SLAY : SAY_CLEAN_SLAY);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
|
||||
DoCastSelf(spellId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
SetForm(false, true);
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->CastSpell(summon, SPELL_ELEMENTAL_SPAWNIN, true);
|
||||
summon->SetInCombatWithZone();
|
||||
|
||||
if (summon->GetEntry() == NPC_PURE_SPAWN_OF_HYDROSS)
|
||||
summon->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
else
|
||||
summon->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(me->HasAura(SPELL_CORRUPTION) ? SAY_CORRUPT_DEATH : SAY_CLEAN_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
if (me->HasAura(SPELL_BLUE_BEAM) == me->HasAura(SPELL_CORRUPTION))
|
||||
{
|
||||
case EVENT_CHECK_AURA:
|
||||
if (me->HasAura(SPELL_BLUE_BEAM) == me->HasAura(SPELL_CORRUPTION))
|
||||
SetForm(!me->HasAura(SPELL_BLUE_BEAM), false);
|
||||
events.ScheduleEvent(EVENT_CHECK_AURA, 1000);
|
||||
break;
|
||||
case EVENT_SPELL_ENRAGE:
|
||||
me->CastSpell(me, SPELL_ENRAGE, true);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_HYDROSS1:
|
||||
me->CastSpell(me, SPELL_MARK_OF_HYDROSS1, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_HYDROSS2:
|
||||
me->CastSpell(me, SPELL_MARK_OF_HYDROSS2, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_HYDROSS3:
|
||||
me->CastSpell(me, SPELL_MARK_OF_HYDROSS3, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_HYDROSS4:
|
||||
me->CastSpell(me, SPELL_MARK_OF_HYDROSS4, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_HYDROSS5:
|
||||
me->CastSpell(me, SPELL_MARK_OF_HYDROSS5, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_HYDROSS6:
|
||||
me->CastSpell(me, SPELL_MARK_OF_HYDROSS6, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_HYDROSS6, 15000, GROUP_ABILITIES);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_CORRUPTION1:
|
||||
me->CastSpell(me, SPELL_MARK_OF_CORRUPTION1, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_CORRUPTION2:
|
||||
me->CastSpell(me, SPELL_MARK_OF_CORRUPTION2, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_CORRUPTION3:
|
||||
me->CastSpell(me, SPELL_MARK_OF_CORRUPTION3, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_CORRUPTION4:
|
||||
me->CastSpell(me, SPELL_MARK_OF_CORRUPTION4, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_CORRUPTION5:
|
||||
me->CastSpell(me, SPELL_MARK_OF_CORRUPTION5, false);
|
||||
break;
|
||||
case EVENT_SPELL_MARK_OF_CORRUPTION6:
|
||||
me->CastSpell(me, SPELL_MARK_OF_CORRUPTION6, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK_OF_CORRUPTION6, 15000, GROUP_ABILITIES);
|
||||
break;
|
||||
case EVENT_SPELL_WATER_TOMB:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
||||
me->CastSpell(target, SPELL_WATER_TOMB, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_WATER_TOMB, 7000, GROUP_ABILITIES);
|
||||
break;
|
||||
case EVENT_SPELL_VILE_SLUDGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
||||
me->CastSpell(target, SPELL_VILE_SLUDGE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_VILE_SLUDGE, 15000, GROUP_ABILITIES);
|
||||
break;
|
||||
SetForm(!me->HasAura(SPELL_BLUE_BEAM), false);
|
||||
}
|
||||
context.Repeat(1s);
|
||||
}).Schedule(10min, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
});
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (!_recentlySpoken)
|
||||
{
|
||||
Talk(me->HasAura(SPELL_CORRUPTION) ? SAY_CORRUPT_SLAY : SAY_CLEAN_SLAY);
|
||||
_recentlySpoken = true;
|
||||
}
|
||||
};
|
||||
scheduler.Schedule(6s, [this](TaskContext)
|
||||
{
|
||||
_recentlySpoken = false;
|
||||
});
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->CastSpell(summon, SPELL_ELEMENTAL_SPAWNIN, true);
|
||||
summon->SetInCombatWithZone();
|
||||
|
||||
if (summon->GetEntry() == NPC_PURE_SPAWN_OF_HYDROSS)
|
||||
{
|
||||
summon->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
summon->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(me->HasAura(SPELL_CORRUPTION) ? SAY_CORRUPT_DEATH : SAY_CLEAN_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
private:
|
||||
bool _recentlySpoken;
|
||||
};
|
||||
|
||||
class spell_hydross_cleansing_field_aura : public SpellScriptLoader
|
||||
@@ -377,7 +343,7 @@ public:
|
||||
|
||||
void AddSC_boss_hydross_the_unstable()
|
||||
{
|
||||
new boss_hydross_the_unstable();
|
||||
RegisterSerpentShrineAI(boss_hydross_the_unstable);
|
||||
new spell_hydross_cleansing_field_aura();
|
||||
new spell_hydross_cleansing_field_command();
|
||||
new spell_hydross_mark_of_hydross();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* 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 General Public License for
|
||||
* 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
|
||||
|
||||
@@ -55,8 +55,10 @@ enum Spells
|
||||
SPELL_QUAKE_KNOCKBACK = 30571,
|
||||
SPELL_COLLAPSE_DAMAGE = 36449,
|
||||
SPELL_CAMERA_SHAKE = 36455,
|
||||
SPELL_DEBRIS_TARGET = 30629,
|
||||
SPELL_DEBRIS_SPAWN = 30630,
|
||||
SPELL_DEBRIS_DAMAGE = 30631,
|
||||
SPELL_DEBRIS_VISUAL = 30632,
|
||||
SPELL_DEBRIS_DAMAGE = 30631
|
||||
};
|
||||
|
||||
enum Groups
|
||||
@@ -70,26 +72,9 @@ enum Actions
|
||||
ACTION_INCREASE_HELLFIRE_CHANNELER_DEATH_COUNT = 1
|
||||
};
|
||||
|
||||
class DealDebrisDamage : public BasicEvent
|
||||
{
|
||||
public:
|
||||
DealDebrisDamage(Creature& creature, ObjectGuid targetGUID) : _owner(creature), _targetGUID(targetGUID) { }
|
||||
|
||||
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(_owner, _targetGUID))
|
||||
target->CastSpell(target, SPELL_DEBRIS_DAMAGE, true, nullptr, nullptr, _owner.GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Creature& _owner;
|
||||
ObjectGuid _targetGUID;
|
||||
};
|
||||
|
||||
struct boss_magtheridon : public BossAI
|
||||
{
|
||||
boss_magtheridon(Creature* creature) : BossAI(creature, TYPE_MAGTHERIDON)
|
||||
boss_magtheridon(Creature* creature) : BossAI(creature, DATA_MAGTHERIDON)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
@@ -137,11 +122,7 @@ struct boss_magtheridon : public BossAI
|
||||
_currentPhase = 0;
|
||||
scheduler.Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
||||
{
|
||||
target->CastSpell(target, SPELL_DEBRIS_VISUAL, true, nullptr, nullptr, me->GetGUID());
|
||||
me->m_Events.AddEvent(new DealDebrisDamage(*me, target->GetGUID()), me->m_Events.CalculateTime(5000));
|
||||
}
|
||||
DoCastAOE(SPELL_DEBRIS_TARGET);
|
||||
context.Repeat(20s);
|
||||
});
|
||||
});
|
||||
@@ -170,7 +151,7 @@ struct boss_magtheridon : public BossAI
|
||||
|
||||
void ScheduleCombatEvents()
|
||||
{
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
DoResetThreatList();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
@@ -248,7 +229,7 @@ struct boss_magtheridon : public BossAI
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_EMOTE_BEGIN);
|
||||
|
||||
instance->DoForAllMinions(TYPE_MAGTHERIDON, [&](Creature* creature) {
|
||||
instance->DoForAllMinions(DATA_MAGTHERIDON, [&](Creature* creature) {
|
||||
creature->SetInCombatWithZone();
|
||||
});
|
||||
|
||||
@@ -289,6 +270,37 @@ private:
|
||||
TaskScheduler _interruptScheduler;
|
||||
};
|
||||
|
||||
struct npc_target_trigger : public ScriptedAI
|
||||
{
|
||||
npc_target_trigger(Creature* creature) : ScriptedAI(creature), _cast(false)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (!_cast)
|
||||
{
|
||||
DoCastSelf(SPELL_DEBRIS_VISUAL);
|
||||
_cast = true;
|
||||
_scheduler.Schedule(5s, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastSelf(SPELL_DEBRIS_DAMAGE);
|
||||
me->DespawnOrUnsummon(6000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
protected:
|
||||
TaskScheduler _scheduler;
|
||||
bool _cast;
|
||||
};
|
||||
|
||||
class spell_magtheridon_blaze : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_magtheridon_blaze);
|
||||
@@ -348,6 +360,33 @@ class spell_magtheridon_quake : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class spell_magtheridon_debris_target_selector : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_magtheridon_debris_target_selector);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if([&](WorldObject* target) -> bool
|
||||
{
|
||||
return target->GetEntry() != NPC_TARGET_TRIGGER;
|
||||
});
|
||||
|
||||
Acore::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
|
||||
void HandleHit()
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->CastSpell(target, SPELL_DEBRIS_SPAWN);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_magtheridon_debris_target_selector::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnHit += SpellHitFn(spell_magtheridon_debris_target_selector::HandleHit);
|
||||
}
|
||||
};
|
||||
|
||||
class go_manticron_cube : public GameObjectScript
|
||||
{
|
||||
public:
|
||||
@@ -369,8 +408,10 @@ public:
|
||||
void AddSC_boss_magtheridon()
|
||||
{
|
||||
RegisterMagtheridonsLairCreatureAI(boss_magtheridon);
|
||||
RegisterMagtheridonsLairCreatureAI(npc_target_trigger);
|
||||
RegisterSpellScript(spell_magtheridon_blaze);
|
||||
RegisterSpellScript(spell_magtheridon_shadow_grasp);
|
||||
RegisterSpellScript(spell_magtheridon_quake);
|
||||
RegisterSpellScript(spell_magtheridon_debris_target_selector);
|
||||
new go_manticron_cube();
|
||||
}
|
||||
|
||||
@@ -21,18 +21,18 @@
|
||||
|
||||
BossBoundaryData const boundaries =
|
||||
{
|
||||
{ TYPE_MAGTHERIDON, new CircleBoundary(Position(-18.70f, 2.24f), 52.30) }
|
||||
{ DATA_MAGTHERIDON, new CircleBoundary(Position(-18.70f, 2.24f), 52.30) }
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_MAGTHERIDON_DOORS, TYPE_MAGTHERIDON, DOOR_TYPE_ROOM },
|
||||
{ GO_MAGTHERIDON_DOORS, DATA_MAGTHERIDON, DOOR_TYPE_ROOM },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
};
|
||||
|
||||
MinionData const minionData[] =
|
||||
{
|
||||
{ NPC_HELLFIRE_CHANNELER, TYPE_MAGTHERIDON }
|
||||
{ NPC_HELLFIRE_CHANNELER, DATA_MAGTHERIDON }
|
||||
};
|
||||
|
||||
class instance_magtheridons_lair : public InstanceMapScript
|
||||
@@ -133,7 +133,7 @@ public:
|
||||
if (!InstanceScript::SetBossState(id, state))
|
||||
return false;
|
||||
|
||||
if (id == TYPE_MAGTHERIDON)
|
||||
if (id == DATA_MAGTHERIDON)
|
||||
{
|
||||
if (state == IN_PROGRESS)
|
||||
{
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case DATA_CHANNELER_COMBAT:
|
||||
if (GetBossState(TYPE_MAGTHERIDON) != IN_PROGRESS)
|
||||
if (GetBossState(DATA_MAGTHERIDON) != IN_PROGRESS)
|
||||
if (Creature* magtheridon = instance->GetCreature(_magtheridonGUID))
|
||||
magtheridon->SetInCombatWithZone();
|
||||
break;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
TYPE_MAGTHERIDON = 0,
|
||||
DATA_MAGTHERIDON = 0,
|
||||
MAX_ENCOUNTER = 1,
|
||||
|
||||
DATA_CHANNELER_COMBAT = 10,
|
||||
@@ -41,6 +41,7 @@ enum NpcIds
|
||||
NPC_HELLFIRE_CHANNELER = 17256,
|
||||
NPC_HELLFIRE_WARDER = 18829,
|
||||
NPC_HELLFIRE_RAID_TRIGGER = 17376,
|
||||
NPC_TARGET_TRIGGER = 17474
|
||||
};
|
||||
|
||||
enum GoIds
|
||||
|
||||
@@ -29,107 +29,94 @@ enum voidReaver
|
||||
SPELL_POUNDING = 34162,
|
||||
SPELL_ARCANE_ORB = 34172,
|
||||
SPELL_KNOCK_AWAY = 25778,
|
||||
SPELL_BERSERK = 26662,
|
||||
|
||||
EVENT_SPELL_POUNDING = 1,
|
||||
EVENT_SPELL_ARCANEORB = 2,
|
||||
EVENT_SPELL_KNOCK_AWAY = 3,
|
||||
EVENT_SPELL_BERSERK = 4
|
||||
SPELL_BERSERK = 26662
|
||||
};
|
||||
|
||||
class boss_void_reaver : public CreatureScript
|
||||
enum Groups
|
||||
{
|
||||
public:
|
||||
boss_void_reaver() : CreatureScript("boss_void_reaver") { }
|
||||
GROUP_ARCANE_ORB = 1
|
||||
};
|
||||
|
||||
struct boss_void_reaverAI : public BossAI
|
||||
struct boss_void_reaver : public BossAI
|
||||
{
|
||||
boss_void_reaver(Creature* creature) : BossAI(creature, DATA_REAVER)
|
||||
{
|
||||
boss_void_reaverAI(Creature* creature) : BossAI(creature, DATA_REAVER)
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
me->ApplySpellImmune(0, IMMUNITY_DISPEL, DISPEL_POISON, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEALTH_LEECH, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_POWER_DRAIN, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_PERIODIC_LEECH, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_PERIODIC_MANA_LEECH, true);
|
||||
}
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && roll_chance_i(50))
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_POUNDING, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_ARCANEORB, 3000);
|
||||
events.ScheduleEvent(EVENT_SPELL_KNOCK_AWAY, 30000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BERSERK, 600000);
|
||||
me->CallForHelp(105.0f);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_BERSERK:
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
case EVENT_SPELL_POUNDING:
|
||||
Talk(SAY_POUNDING);
|
||||
me->CastSpell(me, SPELL_POUNDING, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_POUNDING, 15000);
|
||||
break;
|
||||
case EVENT_SPELL_ARCANEORB:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, -18.0f, true))
|
||||
me->CastSpell(target, SPELL_ARCANE_ORB, false);
|
||||
else if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 20.0f, true))
|
||||
me->CastSpell(target, SPELL_ARCANE_ORB, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_ARCANEORB, 4000);
|
||||
break;
|
||||
case EVENT_SPELL_KNOCK_AWAY:
|
||||
me->CastSpell(me->GetVictim(), SPELL_KNOCK_AWAY, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_POUNDING, 25000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool CheckEvadeIfOutOfCombatArea() const override
|
||||
{
|
||||
return me->GetDistance2d(432.59f, 371.93f) > 105.0f;
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetTheEyeAI<boss_void_reaverAI>(creature);
|
||||
me->ApplySpellImmune(0, IMMUNITY_DISPEL, DISPEL_POISON, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEALTH_LEECH, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_POWER_DRAIN, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_PERIODIC_LEECH, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_PERIODIC_MANA_LEECH, true);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_recentlySpoken = false;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (!_recentlySpoken)
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
_recentlySpoken = true;
|
||||
scheduler.Schedule(5s, [this](TaskContext)
|
||||
{
|
||||
_recentlySpoken = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
me->CallForHelp(105.0f);
|
||||
|
||||
scheduler.Schedule(10min, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
Talk(SAY_POUNDING);
|
||||
DoCastSelf(SPELL_POUNDING);
|
||||
scheduler.DelayGroup(GROUP_ARCANE_ORB, 3s);
|
||||
context.Repeat(15s);
|
||||
}).Schedule(3s, GROUP_ARCANE_ORB, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, -18.0f, true))
|
||||
me->CastSpell(target, SPELL_ARCANE_ORB, false);
|
||||
else if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 20.0f, true))
|
||||
me->CastSpell(target, SPELL_ARCANE_ORB, false);
|
||||
context.Repeat(3s);
|
||||
}).Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCK_AWAY);
|
||||
context.Repeat(25s);
|
||||
});
|
||||
}
|
||||
|
||||
bool CheckEvadeIfOutOfCombatArea() const override
|
||||
{
|
||||
return me->GetDistance2d(432.59f, 371.93f) > 105.0f;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _recentlySpoken;
|
||||
};
|
||||
|
||||
void AddSC_boss_void_reaver()
|
||||
{
|
||||
new boss_void_reaver();
|
||||
RegisterTheEyeAI(boss_void_reaver);
|
||||
}
|
||||
|
||||
@@ -65,4 +65,6 @@ inline AI* GetTheEyeAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, TheEyeScriptName);
|
||||
}
|
||||
|
||||
#define RegisterTheEyeAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetTheEyeAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
// Ours
|
||||
enum saeed
|
||||
@@ -697,9 +699,6 @@ public:
|
||||
{
|
||||
Drained = true;
|
||||
int32 uHpPct = int32(me->GetHealthPct());
|
||||
|
||||
me->UpdateEntry(NPC_DRAINED_PHASE_HUNTER_ENTRY);
|
||||
|
||||
me->SetHealth(me->CountPctFromMaxHealth(uHpPct));
|
||||
me->LowerPlayerDamageReq(me->GetMaxHealth() - me->GetHealth());
|
||||
me->SetInCombatWith(player);
|
||||
@@ -911,6 +910,45 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_q10190_battery_recharging_blaster : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_q10190_battery_recharging_blaster);
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
if (Unit* target = GetExplTargetUnit())
|
||||
if (target->GetHealthPct() <= 25.0f)
|
||||
return SPELL_CAST_OK;
|
||||
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_q10190_battery_recharging_blaster::CheckCast);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_q10190_battery_recharging_blaster_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_q10190_battery_recharging_blaster_aura);
|
||||
|
||||
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
|
||||
return;
|
||||
|
||||
if (Creature* phasehunter = GetTarget()->ToCreature())
|
||||
if (phasehunter->GetEntry() == NPC_PHASE_HUNTER_ENTRY)
|
||||
phasehunter->UpdateEntry(NPC_DRAINED_PHASE_HUNTER_ENTRY);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_q10190_battery_recharging_blaster_aura::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_netherstorm()
|
||||
{
|
||||
// Ours
|
||||
@@ -922,5 +960,5 @@ void AddSC_netherstorm()
|
||||
new npc_phase_hunter();
|
||||
new npc_bessy();
|
||||
new npc_maxx_a_million_escort();
|
||||
|
||||
RegisterSpellAndAuraScriptPair(spell_q10190_battery_recharging_blaster, spell_q10190_battery_recharging_blaster_aura);
|
||||
}
|
||||
|
||||
@@ -146,6 +146,18 @@ class spell_dk_raise_ally : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_dk_raise_ally);
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
Player* unitTarget = GetHitPlayer();
|
||||
if (!unitTarget)
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
if (unitTarget->IsAlive()) // not discovered attributeEx5?
|
||||
return SPELL_FAILED_TARGET_NOT_DEAD;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Player* unitTarget = GetHitPlayer())
|
||||
@@ -237,6 +249,7 @@ class spell_dk_raise_ally : public SpellScript
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_dk_raise_ally::CheckCast);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_dk_raise_ally::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -302,7 +302,8 @@ private:
|
||||
|
||||
enum Spell
|
||||
{
|
||||
PAL_SPELL_ARDENT_DEFENDER_HEAL = 66235
|
||||
PAL_SPELL_ARDENT_DEFENDER_DEBUFF = 66233,
|
||||
PAL_SPELL_ARDENT_DEFENDER_HEAL = 66235
|
||||
};
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
@@ -329,7 +330,7 @@ private:
|
||||
int32 remainingHealth = victim->GetHealth() - dmgInfo.GetDamage();
|
||||
uint32 allowedHealth = victim->CountPctFromMaxHealth(35);
|
||||
// If damage kills us
|
||||
if (remainingHealth <= 0 && !victim->ToPlayer()->HasSpellCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL))
|
||||
if (remainingHealth <= 0 && !victim->ToPlayer()->HasAura(PAL_SPELL_ARDENT_DEFENDER_DEBUFF))
|
||||
{
|
||||
// Cast healing spell, completely avoid damage
|
||||
absorbAmount = dmgInfo.GetDamage();
|
||||
@@ -344,7 +345,6 @@ private:
|
||||
|
||||
int32 healAmount = int32(victim->CountPctFromMaxHealth(uint32(healPct * pctFromDefense)));
|
||||
victim->CastCustomSpell(PAL_SPELL_ARDENT_DEFENDER_HEAL, SPELLVALUE_BASE_POINT0, healAmount, victim, true, nullptr, aurEff);
|
||||
victim->ToPlayer()->AddSpellCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL, 0, 120000);
|
||||
}
|
||||
else if (remainingHealth < int32(allowedHealth))
|
||||
{
|
||||
|
||||
@@ -19,12 +19,7 @@
|
||||
#include "Group.h"
|
||||
#include "Guild.h"
|
||||
#include "ScriptMgr.h"
|
||||
|
||||
#define LOG_CHAT(TYPE, ...) \
|
||||
if (lang != LANG_ADDON) \
|
||||
LOG_DEBUG("chat.log." TYPE, __VA_ARGS__); \
|
||||
else \
|
||||
LOG_DEBUG("chat.log.addon." TYPE, __VA_ARGS__);
|
||||
#include "Log.h"
|
||||
|
||||
class ChatLogScript : public PlayerScript
|
||||
{
|
||||
@@ -36,66 +31,67 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case CHAT_MSG_SAY:
|
||||
LOG_CHAT("say", "Player {} says (language {}): {}",
|
||||
LOG_INFO("chat.say", "Player {} says (language {}): {}",
|
||||
player->GetName(), lang, msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_EMOTE:
|
||||
LOG_CHAT("emote", "Player {} emotes: {}",
|
||||
LOG_INFO("chat.emote", "Player {} emotes: {}",
|
||||
player->GetName(), msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_YELL:
|
||||
LOG_CHAT("yell", "Player {} yells (language {}): {}",
|
||||
LOG_INFO("chat.yell", "Player {} yells (language {}): {}",
|
||||
player->GetName(), lang, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnChat(Player* player, uint32 /*type*/, uint32 lang, std::string& msg, Player* receiver) override
|
||||
void OnChat(Player* player, uint32 /*type*/, uint32 /*lang*/, std::string& msg, Player* receiver) override
|
||||
{
|
||||
LOG_CHAT("whisper", "Player {} tells {}: {}",
|
||||
LOG_INFO("chat.whisper", "Player {} tells {}: {}",
|
||||
player->GetName(), receiver ? receiver->GetName() : "<unknown>", msg);
|
||||
}
|
||||
|
||||
void OnChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override
|
||||
{
|
||||
std::string str = lang != LANG_ADDON ? "chat." : "chat.addon.";
|
||||
//! NOTE:
|
||||
//! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER"
|
||||
switch (type)
|
||||
{
|
||||
case CHAT_MSG_PARTY:
|
||||
LOG_CHAT("party", "Player {} tells group with leader {}: {}",
|
||||
LOG_INFO(str + "party", "Player {} tells group with leader {}: {}",
|
||||
player->GetName(), group ? group->GetLeaderName() : "<unknown>", msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_PARTY_LEADER:
|
||||
LOG_CHAT("party", "Leader {} tells group: {}",
|
||||
LOG_INFO(str + "party", "Leader {} tells group: {}",
|
||||
player->GetName(), msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_RAID:
|
||||
LOG_CHAT("raid", "Player {} tells raid with leader {}: {}",
|
||||
LOG_INFO(str + "raid", "Player {} tells raid with leader {}: {}",
|
||||
player->GetName(), group ? group->GetLeaderName() : "<unknown>", msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_RAID_LEADER:
|
||||
LOG_CHAT("raid", "Leader player {} tells raid: {}",
|
||||
LOG_INFO(str + "raid", "Leader player {} tells raid: {}",
|
||||
player->GetName(), msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_RAID_WARNING:
|
||||
LOG_CHAT("raid", "Leader player {} warns raid with: {}",
|
||||
LOG_INFO(str + "raid", "Leader player {} sends raid warning: {}",
|
||||
player->GetName(), msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_BATTLEGROUND:
|
||||
LOG_CHAT("bg", "Player {} tells battleground with leader {}: {}",
|
||||
LOG_INFO(str + "bg", "Player {} tells battleground with leader {}: {}",
|
||||
player->GetName(), group ? group->GetLeaderName() : "<unknown>", msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_BATTLEGROUND_LEADER:
|
||||
LOG_CHAT("bg", "Leader player {} tells battleground: {}",
|
||||
LOG_INFO(str + "bg", "Leader player {} tells battleground: {}",
|
||||
player->GetName(), msg);
|
||||
break;
|
||||
}
|
||||
@@ -103,21 +99,22 @@ public:
|
||||
|
||||
void OnChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override
|
||||
{
|
||||
std::string str = lang != LANG_ADDON ? "chat." : "chat.addon.";
|
||||
switch (type)
|
||||
{
|
||||
case CHAT_MSG_GUILD:
|
||||
LOG_CHAT("guild", "Player {} tells guild {}: {}",
|
||||
LOG_INFO(str + "guild", "Player {} tells guild {}: {}",
|
||||
player->GetName(), guild ? guild->GetName() : "<unknown>", msg);
|
||||
break;
|
||||
|
||||
case CHAT_MSG_OFFICER:
|
||||
LOG_CHAT("guild.officer", "Player {} tells guild {} officers: {}",
|
||||
LOG_INFO(str + "guild.officer", "Player {} tells guild {} officers: {}",
|
||||
player->GetName(), guild ? guild->GetName() : "<unknown>", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnChat(Player* player, uint32 /*type*/, uint32 lang, std::string& msg, Channel* channel) override
|
||||
void OnChat(Player* player, uint32 /*type*/, uint32 /*lang*/, std::string& msg, Channel* channel) override
|
||||
{
|
||||
bool isSystem = channel &&
|
||||
(channel->HasFlag(CHANNEL_FLAG_TRADE) ||
|
||||
@@ -127,13 +124,15 @@ public:
|
||||
|
||||
if (isSystem)
|
||||
{
|
||||
LOG_CHAT("system", "Player {} tells channel {}: {}",
|
||||
LOG_INFO("chat.channel", "Player {} tells channel {}: {}",
|
||||
player->GetName(), channel->GetName(), msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allow to log custom channels. i.e. world channel
|
||||
// in that case set config: Logger.channel.world=6,Chat
|
||||
std::string channelName = channel ? channel->GetName() : "<unknown>";
|
||||
LOG_CHAT("channel." + channelName, "Player {} tells channel {}: {}",
|
||||
LOG_INFO("chat.channel." + channelName, "Player {} tells channel {}: {}",
|
||||
player->GetName(), channelName, msg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user