mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 22:56:24 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -15,330 +15,446 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: boss_kri, boss_yauj, boss_vem : The Bug Trio
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Temple of Ahn'Qiraj
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_CLEAVE = 26350,
|
||||
SPELL_TOXIC_VOLLEY = 25812,
|
||||
SPELL_POISON_CLOUD = 38718, //Only Spell with right dmg.
|
||||
SPELL_ENRAGE = 34624, //Changed cause 25790 is cast on gamers too. Same prob with old explosion of twin emperors.
|
||||
SPELL_BLOODY_DEATH = 25770,
|
||||
SPELL_FULL_HEAL = 17683,
|
||||
|
||||
SPELL_CHARGE = 26561,
|
||||
SPELL_KNOCKBACK = 26027,
|
||||
// Kri
|
||||
SPELL_CLEAVE = 26350,
|
||||
SPELL_THRASH = 3391,
|
||||
SPELL_TOXIC_VOLLEY = 25812,
|
||||
SPELL_POISON_CLOUD = 26590,
|
||||
|
||||
SPELL_HEAL = 25807,
|
||||
SPELL_FEAR = 19408
|
||||
// Vem
|
||||
SPELL_CHARGE = 26561,
|
||||
SPELL_KNOCKBACK = 18670,
|
||||
SPELL_KNOCKDOWN = 19128,
|
||||
SPELL_VENGEANCE = 25790,
|
||||
|
||||
// Yauj
|
||||
SPELL_HEAL = 25807,
|
||||
SPELL_FEAR = 26580,
|
||||
SPELL_RAVAGE = 3242,
|
||||
SPELL_DISPEL = 25808,
|
||||
|
||||
NPC_YAUJ_BROOD = 15621
|
||||
};
|
||||
|
||||
class boss_kri : public CreatureScript
|
||||
enum Misc
|
||||
{
|
||||
public:
|
||||
boss_kri() : CreatureScript("boss_kri") { }
|
||||
ACTION_CONSUME = 0,
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetTempleOfAhnQirajAI<boss_kriAI>(creature);
|
||||
}
|
||||
EMOTE_DEVOURED = 0,
|
||||
|
||||
struct boss_kriAI : public ScriptedAI
|
||||
{
|
||||
boss_kriAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
POINT_CONSUME = 0,
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 Cleave_Timer;
|
||||
uint32 ToxicVolley_Timer;
|
||||
uint32 Check_Timer;
|
||||
|
||||
bool VemDead;
|
||||
bool Death;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Cleave_Timer = urand(4000, 8000);
|
||||
ToxicVolley_Timer = urand(6000, 12000);
|
||||
Check_Timer = 2000;
|
||||
|
||||
VemDead = false;
|
||||
Death = false;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance->GetData(DATA_BUG_TRIO_DEATH) < 2)// Unlootable if death
|
||||
me->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
|
||||
|
||||
instance->SetData(DATA_BUG_TRIO_DEATH, 1);
|
||||
}
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Cleave_Timer
|
||||
if (Cleave_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
Cleave_Timer = urand(5000, 12000);
|
||||
}
|
||||
else Cleave_Timer -= diff;
|
||||
|
||||
//ToxicVolley_Timer
|
||||
if (ToxicVolley_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_TOXIC_VOLLEY);
|
||||
ToxicVolley_Timer = urand(10000, 15000);
|
||||
}
|
||||
else ToxicVolley_Timer -= diff;
|
||||
|
||||
if (!HealthAbovePct(5) && !Death)
|
||||
{
|
||||
DoCastVictim(SPELL_POISON_CLOUD);
|
||||
Death = true;
|
||||
}
|
||||
|
||||
if (!VemDead)
|
||||
{
|
||||
//Checking if Vem is dead. If yes we will enrage.
|
||||
if (Check_Timer <= diff)
|
||||
{
|
||||
if (instance->GetData(DATA_VEMISDEAD))
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
VemDead = true;
|
||||
}
|
||||
Check_Timer = 2000;
|
||||
}
|
||||
else Check_Timer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
VEM_WAYPOINT_PATH = 876030
|
||||
};
|
||||
|
||||
class boss_vem : public CreatureScript
|
||||
const Position resetPoint = { -8582.0f, 2047.0f, -1.62f }; // Taken from CMangos
|
||||
|
||||
struct boss_bug_trio : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_vem() : CreatureScript("boss_vem") { }
|
||||
boss_bug_trio(Creature* creature) : BossAI(creature, DATA_BUG_TRIO) { Reset(); }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool CheckInRoom() override
|
||||
{
|
||||
return GetTempleOfAhnQirajAI<boss_vemAI>(creature);
|
||||
if (me->GetExactDist2d(resetPoint) <= 10.f)
|
||||
{
|
||||
EnterEvadeMode(EVADE_REASON_BOUNDARY);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct boss_vemAI : public ScriptedAI
|
||||
void EnterCombatWithTrio(Unit* who)
|
||||
{
|
||||
boss_vemAI(Creature* creature) : ScriptedAI(creature)
|
||||
if (Creature* vem = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VEM)))
|
||||
if (vem->GetGUID() != me->GetGUID())
|
||||
vem->GetAI()->AttackStart(who);
|
||||
if (Creature* kri = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KRI)))
|
||||
if (kri->GetGUID() != me->GetGUID())
|
||||
kri->GetAI()->AttackStart(who);
|
||||
if (Creature* yauj = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_YAUJ)))
|
||||
if (yauj->GetGUID() != me->GetGUID())
|
||||
yauj->GetAI()->AttackStart(who);
|
||||
}
|
||||
|
||||
void EvadeAllBosses(EvadeReason why)
|
||||
{
|
||||
if (Creature* vem = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VEM)))
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
if (vem->GetGUID() != me->GetGUID())
|
||||
{
|
||||
if (vem->IsAlive() && !vem->IsInEvadeMode())
|
||||
vem->AI()->EnterEvadeMode(why);
|
||||
else
|
||||
vem->Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 Charge_Timer;
|
||||
uint32 KnockBack_Timer;
|
||||
uint32 Enrage_Timer;
|
||||
|
||||
bool Enraged;
|
||||
|
||||
void Reset() override
|
||||
if (Creature* kri = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KRI)))
|
||||
{
|
||||
Charge_Timer = urand(15000, 27000);
|
||||
KnockBack_Timer = urand(8000, 20000);
|
||||
Enrage_Timer = 120000;
|
||||
|
||||
Enraged = false;
|
||||
if (kri->GetGUID() != me->GetGUID())
|
||||
{
|
||||
if (kri->IsAlive() && !kri->IsInEvadeMode())
|
||||
kri->AI()->EnterEvadeMode(why);
|
||||
else
|
||||
kri->Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
if (Creature* yauj = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_YAUJ)))
|
||||
{
|
||||
instance->SetData(DATA_VEM_DEATH, 0);
|
||||
if (instance->GetData(DATA_BUG_TRIO_DEATH) < 2)// Unlootable if death
|
||||
me->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
|
||||
instance->SetData(DATA_BUG_TRIO_DEATH, 1);
|
||||
if (yauj->GetGUID() != me->GetGUID())
|
||||
{
|
||||
if (yauj->IsAlive() && !yauj->IsInEvadeMode())
|
||||
yauj->AI()->EnterEvadeMode(why);
|
||||
else
|
||||
yauj->Respawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action != ACTION_CONSUME || dying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
}
|
||||
isEating = true;
|
||||
me->SetSpeed(MOVE_RUN, 45.f/7.f); // From sniffs
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->SetSpeed(MOVE_RUN, 15.f/7.f); // From sniffs
|
||||
DoCastSelf(SPELL_FULL_HEAL, true);
|
||||
DoResetThreat();
|
||||
isEating = false;
|
||||
|
||||
_scheduler.Schedule(4s, [this](TaskContext /*context*/)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
if (Unit* target = me->GetVictim())
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(target);
|
||||
AttackStart(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
BossAI::EnterEvadeMode(why);
|
||||
EvadeAllBosses(why);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_scheduler.CancelAll();
|
||||
dying = false;
|
||||
isEating = false;
|
||||
instance->SetData(DATA_BUG_TRIO_DEATH, 0);
|
||||
me->SetSpeed(MOVE_RUN, 15.f / 7.f); // From sniffs
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
|
||||
if (me->GetEntry() == NPC_VEM)
|
||||
{
|
||||
me->GetMotionMaster()->MovePath(VEM_WAYPOINT_PATH, true);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() || isEating || !CheckInRoom())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(1, damage) && instance->GetData(DATA_BUG_TRIO_DEATH) < 2 && who->GetGUID() != me->GetGUID())
|
||||
{
|
||||
damage = 0;
|
||||
if (isEating)
|
||||
return;
|
||||
|
||||
//Charge_Timer
|
||||
if (Charge_Timer <= diff)
|
||||
_scheduler.CancelAll();
|
||||
me->SetStandState(UNIT_STAND_STATE_DEAD);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
|
||||
DoFinalSpell();
|
||||
|
||||
// Move the other bugs to this bug position
|
||||
if (Creature* vem = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VEM)))
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0);
|
||||
if (target)
|
||||
if (vem->GetGUID() != me->GetGUID())
|
||||
{
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
//me->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true, 1);
|
||||
AttackStart(target);
|
||||
vem->AI()->DoAction(ACTION_CONSUME);
|
||||
vem->GetMotionMaster()->MovePoint(POINT_CONSUME, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
|
||||
}
|
||||
|
||||
Charge_Timer = urand(8000, 16000);
|
||||
}
|
||||
else Charge_Timer -= diff;
|
||||
|
||||
//KnockBack_Timer
|
||||
if (KnockBack_Timer <= diff)
|
||||
if (Creature* kri = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KRI)))
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -80);
|
||||
KnockBack_Timer = urand(15000, 25000);
|
||||
if (kri->GetGUID() != me->GetGUID())
|
||||
{
|
||||
kri->AI()->DoAction(ACTION_CONSUME);
|
||||
kri->GetMotionMaster()->MovePoint(POINT_CONSUME, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
|
||||
}
|
||||
}
|
||||
else KnockBack_Timer -= diff;
|
||||
|
||||
//Enrage_Timer
|
||||
if (!Enraged && Enrage_Timer <= diff)
|
||||
if (Creature* yauj = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_YAUJ)))
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
Enraged = true;
|
||||
if (yauj->GetGUID() != me->GetGUID())
|
||||
{
|
||||
yauj->AI()->DoAction(ACTION_CONSUME);
|
||||
yauj->GetMotionMaster()->MovePoint(POINT_CONSUME, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
|
||||
}
|
||||
}
|
||||
else Charge_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
_scheduler.Schedule(4s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (!me->IsInEvadeMode())
|
||||
{
|
||||
DoCastSelf(SPELL_BLOODY_DEATH, true);
|
||||
Talk(EMOTE_DEVOURED);
|
||||
me->DespawnOrUnsummon(1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void DoFinalSpell()
|
||||
{
|
||||
switch (me->GetEntry())
|
||||
{
|
||||
case NPC_KRI:
|
||||
DoCastSelf(SPELL_POISON_CLOUD, true);
|
||||
break;
|
||||
case NPC_VEM:
|
||||
DoCastSelf(SPELL_VENGEANCE, true);
|
||||
break;
|
||||
case NPC_YAUJ:
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
{
|
||||
Position randomPos;
|
||||
me->GetRandomContactPoint(me, randomPos.m_positionX, randomPos.m_positionY, randomPos.m_positionZ);
|
||||
if (Creature* summon = me->SummonCreature(NPC_YAUJ_BROOD, randomPos))
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (killer->GetGUID() == me->GetGUID())
|
||||
{
|
||||
instance->SetData(DATA_BUG_TRIO_DEATH, 1);
|
||||
me->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
TaskScheduler _scheduler;
|
||||
bool dying;
|
||||
bool isEating;
|
||||
};
|
||||
|
||||
class boss_yauj : public CreatureScript
|
||||
struct boss_kri : public boss_bug_trio
|
||||
{
|
||||
public:
|
||||
boss_yauj() : CreatureScript("boss_yauj") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_kri(Creature* creature) : boss_bug_trio(creature)
|
||||
{
|
||||
return GetTempleOfAhnQirajAI<boss_yaujAI>(creature);
|
||||
}
|
||||
|
||||
struct boss_yaujAI : public ScriptedAI
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
boss_yaujAI(Creature* creature) : ScriptedAI(creature)
|
||||
EnterCombatWithTrio(who);
|
||||
|
||||
_scheduler.Schedule(4s, 8s, [this](TaskContext context)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 Heal_Timer;
|
||||
uint32 Fear_Timer;
|
||||
uint32 Check_Timer;
|
||||
|
||||
bool VemDead;
|
||||
|
||||
void Reset() override
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
context.Repeat(5s, 12s);
|
||||
})
|
||||
.Schedule(6s, 30s, [this](TaskContext context)
|
||||
{
|
||||
Heal_Timer = urand(25000, 40000);
|
||||
Fear_Timer = urand(12000, 24000);
|
||||
Check_Timer = 2000;
|
||||
|
||||
VemDead = false;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
DoCastVictim(SPELL_TOXIC_VOLLEY);
|
||||
context.Repeat(10s, 25s);
|
||||
})
|
||||
.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
if (instance->GetData(DATA_BUG_TRIO_DEATH) < 2)// Unlootable if death
|
||||
me->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
|
||||
instance->SetData(DATA_BUG_TRIO_DEATH, 1);
|
||||
DoCastVictim(SPELL_THRASH);
|
||||
context.Repeat(2s, 6s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
struct boss_vem : public boss_bug_trio
|
||||
{
|
||||
boss_vem(Creature* creature) : boss_bug_trio(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
EnterCombatWithTrio(who);
|
||||
|
||||
_scheduler.Schedule(15s, 27s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [this](Unit* target) -> bool
|
||||
{
|
||||
if (Creature* Summoned = me->SummonCreature(15621, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000))
|
||||
Summoned->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
return false;
|
||||
if (me->IsWithinMeleeRange(target) || target == me->GetVictim())
|
||||
return false;
|
||||
if (!me->IsWithinLOS(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()))
|
||||
return false;
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
return true;
|
||||
}))
|
||||
{
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
}
|
||||
context.Repeat(8s, 16s);
|
||||
})
|
||||
.Schedule(10s, 20s, [this](TaskContext context)
|
||||
{
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
context.Repeat(10s, 20s);
|
||||
})
|
||||
.Schedule(5s, 8s, [this](TaskContext context)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Fear_Timer
|
||||
if (Fear_Timer <= diff)
|
||||
DoCastVictim(SPELL_KNOCKDOWN);
|
||||
context.Repeat(15s, 20s);
|
||||
})
|
||||
.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (instance->GetData(DATA_BUG_TRIO_DEATH) == 2 && !me->HasAura(SPELL_VENGEANCE)) // Vem is the only one left.
|
||||
{
|
||||
DoCastVictim(SPELL_FEAR);
|
||||
DoResetThreat();
|
||||
Fear_Timer = 20000;
|
||||
DoCastSelf(SPELL_VENGEANCE, true);
|
||||
}
|
||||
else Fear_Timer -= diff;
|
||||
context.Repeat(1s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//Casting Heal to other twins or herself.
|
||||
if (Heal_Timer <= diff)
|
||||
struct boss_yauj : public boss_bug_trio
|
||||
{
|
||||
boss_yauj(Creature* creature) : boss_bug_trio(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
EnterCombatWithTrio(who);
|
||||
|
||||
_scheduler.Schedule(20s, 30s, [this](TaskContext context)
|
||||
{
|
||||
if (me->GetHealthPct() <= 93.f)
|
||||
{
|
||||
switch (urand(0, 2))
|
||||
{
|
||||
case 0:
|
||||
if (Creature* kri = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KRI)))
|
||||
DoCast(kri, SPELL_HEAL);
|
||||
break;
|
||||
case 1:
|
||||
if (Creature* vem = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VEM)))
|
||||
DoCast(vem, SPELL_HEAL);
|
||||
break;
|
||||
case 2:
|
||||
DoCast(me, SPELL_HEAL);
|
||||
break;
|
||||
}
|
||||
|
||||
Heal_Timer = 15000 + rand() % 15000;
|
||||
DoCastSelf(SPELL_HEAL);
|
||||
}
|
||||
else Heal_Timer -= diff;
|
||||
|
||||
//Checking if Vem is dead. If yes we will enrage.
|
||||
if (Check_Timer <= diff)
|
||||
else if (Unit* friendly = DoSelectLowestHpFriendly(100.f))
|
||||
{
|
||||
if (!VemDead)
|
||||
{
|
||||
if (instance->GetData(DATA_VEMISDEAD))
|
||||
{
|
||||
DoCast(me, SPELL_ENRAGE);
|
||||
VemDead = true;
|
||||
}
|
||||
}
|
||||
Check_Timer = 2000;
|
||||
DoCast(friendly, SPELL_HEAL);
|
||||
}
|
||||
else Check_Timer -= diff;
|
||||
context.Repeat(10s, 30s);
|
||||
})
|
||||
.Schedule(12s, 24s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_FEAR);
|
||||
DoResetThreat();
|
||||
context.Repeat(20s);
|
||||
})
|
||||
.Schedule(12s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_RAVAGE);
|
||||
context.Repeat(10s, 15s);
|
||||
})
|
||||
.Schedule(10s, 30s, [this](TaskContext context)
|
||||
{
|
||||
std::list<Creature*> targets = DoFindFriendlyCC(50.f);
|
||||
if (!targets.empty())
|
||||
{
|
||||
if (Creature* target = *(targets.begin()))
|
||||
me->CastSpell(target, SPELL_DISPEL);
|
||||
}
|
||||
context.Repeat(10s, 15s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
class spell_vem_knockback : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_vem_knockback);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
if (Creature* cCaster = GetCaster()->ToCreature())
|
||||
{
|
||||
cCaster->getThreatMgr().modifyThreatPercent(target, -80);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vem_knockback::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_vem_vengeance : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_vem_vengeance);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if([&](WorldObject const* target) -> bool
|
||||
{
|
||||
return target->GetEntry() != NPC_YAUJ && target->GetEntry() != NPC_VEM && target->GetEntry() != NPC_KRI;
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_vem_vengeance::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_bug_trio()
|
||||
{
|
||||
new boss_kri();
|
||||
new boss_vem();
|
||||
new boss_yauj();
|
||||
RegisterCreatureAI(boss_kri);
|
||||
RegisterCreatureAI(boss_vem);
|
||||
RegisterCreatureAI(boss_yauj);
|
||||
RegisterSpellScript(spell_vem_knockback);
|
||||
RegisterSpellScript(spell_vem_vengeance);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
ObjectGuid SkeramGUID;
|
||||
ObjectGuid VemGUID;
|
||||
ObjectGuid KriGUID;
|
||||
ObjectGuid YaujGUID;
|
||||
ObjectGuid VeklorGUID;
|
||||
ObjectGuid VeknilashGUID;
|
||||
ObjectGuid ViscidusGUID;
|
||||
@@ -88,6 +89,9 @@ public:
|
||||
case NPC_KRI:
|
||||
KriGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_YAUJ:
|
||||
YaujGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_VEKLOR:
|
||||
VeklorGUID = creature->GetGUID();
|
||||
break;
|
||||
@@ -106,11 +110,6 @@ public:
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_VEMISDEAD:
|
||||
if (IsBossDied[0])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case DATA_VEKLORISDEAD:
|
||||
if (IsBossDied[1])
|
||||
return 1;
|
||||
@@ -140,6 +139,8 @@ public:
|
||||
return VemGUID;
|
||||
case DATA_KRI:
|
||||
return KriGUID;
|
||||
case DATA_YAUJ:
|
||||
return YaujGUID;
|
||||
case DATA_VEKLOR:
|
||||
return VeklorGUID;
|
||||
case DATA_VEKNILASH:
|
||||
@@ -155,12 +156,11 @@ public:
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_VEM_DEATH:
|
||||
IsBossDied[0] = true;
|
||||
break;
|
||||
|
||||
case DATA_BUG_TRIO_DEATH:
|
||||
++BugTrioDeathCount;
|
||||
if (data != 0)
|
||||
++BugTrioDeathCount;
|
||||
else
|
||||
BugTrioDeathCount = 0;
|
||||
break;
|
||||
|
||||
case DATA_VEKLOR_DEATH:
|
||||
|
||||
@@ -27,8 +27,8 @@ enum DataTypes
|
||||
DATA_SKERAM = 1,
|
||||
DATA_KRI = 2,
|
||||
DATA_VEM = 3,
|
||||
DATA_VEMISDEAD = 4,
|
||||
DATA_VEM_DEATH = 5,
|
||||
DATA_YAUJ = 4,
|
||||
DATA_BUG_TRIO = 5,
|
||||
DATA_VEKLOR = 6,
|
||||
DATA_VEKLORISDEAD = 7,
|
||||
DATA_VEKLOR_DEATH = 8,
|
||||
@@ -60,6 +60,7 @@ enum Creatures
|
||||
NPC_SKERAM = 15263,
|
||||
NPC_VEM = 15544,
|
||||
NPC_KRI = 15511,
|
||||
NPC_YAUJ = 15543,
|
||||
NPC_VEKLOR = 15276,
|
||||
NPC_VEKNILASH = 15275,
|
||||
NPC_OURO = 15517,
|
||||
|
||||
@@ -80,14 +80,14 @@ enum AuriayaEvents
|
||||
EVENT_ENRAGE = 10,
|
||||
};
|
||||
|
||||
enum AuriayaSounds
|
||||
enum Texts
|
||||
{
|
||||
SOUND_AGGRO = 15473,
|
||||
SOUND_SLAY1 = 15474,
|
||||
SOUND_SLAY2 = 15475,
|
||||
SOUND_DEATH = 15476,
|
||||
SOUND_BERSERK = 15477,
|
||||
SOUND_WOUND = 15478,
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_BERSERK = 2,
|
||||
EMOTE_DEATH = 3,
|
||||
EMOTE_FEAR = 4,
|
||||
EMOTE_DEFFENDER = 5,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
@@ -186,26 +186,16 @@ public:
|
||||
|
||||
summons.DoZoneInCombat(NPC_SANCTUM_SENTRY);
|
||||
|
||||
me->Yell("Some things are better left alone!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_AGGRO);
|
||||
Talk(SAY_AGGRO);
|
||||
me->setActive(true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (urand(0, 2))
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER || urand(0, 2))
|
||||
return;
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
me->Yell("The secret dies with you!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAY1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("There is no escape!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAY2);
|
||||
}
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -216,8 +206,7 @@ public:
|
||||
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
|
||||
summons.DoAction(ACTION_DESPAWN_ADDS, pred);
|
||||
summons.DespawnAll();
|
||||
me->TextEmote("Auriaya screams in agony.", nullptr, true);
|
||||
me->PlayDirectSound(SOUND_DEATH);
|
||||
Talk(EMOTE_DEATH);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
@@ -240,7 +229,7 @@ public:
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SUMMON_FERAL_DEFENDER:
|
||||
me->TextEmote("Auriaya begins to activate Feral Defender.", nullptr, true);
|
||||
Talk(EMOTE_DEFFENDER);
|
||||
me->CastSpell(me, SPELL_ACTIVATE_FERAL_DEFENDER, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
|
||||
events.ScheduleEvent(EVENT_REMOVE_IMMUNE, 3000);
|
||||
@@ -249,7 +238,7 @@ public:
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
|
||||
break;
|
||||
case EVENT_TERRIFYING_SCREECH:
|
||||
me->TextEmote("Auriaya begins to cast Terrifying Screech.", nullptr, true);
|
||||
Talk(EMOTE_FEAR);
|
||||
me->CastSpell(me, SPELL_TERRIFYING_SCREECH, false);
|
||||
events.RepeatEvent(35000);
|
||||
break;
|
||||
@@ -273,8 +262,7 @@ public:
|
||||
break;
|
||||
}
|
||||
case EVENT_ENRAGE:
|
||||
me->TextEmote("You waste my time!", nullptr, true);
|
||||
me->PlayDirectSound(SOUND_BERSERK);
|
||||
Talk(SAY_BERSERK);
|
||||
me->CastSpell(me, SPELL_ENRAGE, true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -183,25 +183,26 @@ enum FreyaEvents
|
||||
EVENT_DETONATING_LASHER_FLAME_LASH = 55,
|
||||
};
|
||||
|
||||
enum FreyaSounds
|
||||
enum Texts
|
||||
{
|
||||
// STONEBARK
|
||||
SOUND_STONEBARK_AGGRO = 15500,
|
||||
SOUND_STONEBARK_SLAY1 = 15501,
|
||||
SOUND_STONEBARK_SLAY2 = 15502,
|
||||
SOUND_STONEBARK_DEATH = 15503,
|
||||
// Elder Brightleaf / Elder Ironbranch / Elder Stonebark
|
||||
SAY_ELDER_AGGRO = 0,
|
||||
SAY_ELDER_SLAY = 1,
|
||||
SAY_ELDER_DEATH = 2,
|
||||
|
||||
// IRONBRANCH
|
||||
SOUND_IRONBRANCH_AGGRO = 15493,
|
||||
SOUND_IRONBRANCH_SLAY1 = 15494,
|
||||
SOUND_IRONBRANCH_SLAY2 = 15495,
|
||||
SOUND_IRONBRANCH_DEATH = 15496,
|
||||
|
||||
// BRIGHTLEAF
|
||||
SOUND_BRIGHTLEAF_AGGRO = 15483,
|
||||
SOUND_BRIGHTLEAF_SLAY1 = 15485,
|
||||
SOUND_BRIGHTLEAF_SLAY2 = 15486,
|
||||
SOUND_BRIGHTLEAF_DEATH = 15487,
|
||||
// Freya
|
||||
SAY_AGGRO = 0,
|
||||
SAY_AGGRO_WITH_ELDER = 1,
|
||||
SAY_SLAY = 2,
|
||||
SAY_DEATH = 3,
|
||||
SAY_BERSERK = 4,
|
||||
SAY_SUMMON_CONSERVATOR = 5,
|
||||
SAY_SUMMON_TRIO = 6,
|
||||
SAY_SUMMON_LASHERS = 7,
|
||||
EMOTE_LIFEBINDERS_GIFT = 8,
|
||||
EMOTE_ALLIES_OF_NATURE = 9,
|
||||
EMOTE_GROUND_TREMOR = 10,
|
||||
EMOTE_IRON_ROOTS = 11,
|
||||
};
|
||||
|
||||
enum FreyaNPCs
|
||||
@@ -224,20 +225,6 @@ enum FreyaNPCs
|
||||
NPC_DETONATING_LASHER = 32918,
|
||||
};
|
||||
|
||||
enum FreyaSouns
|
||||
{
|
||||
SOUND_AGGRO = 15526,
|
||||
SOUND_ELDERS = 15527,
|
||||
SOUND_CONSERVATOR = 15528,
|
||||
SOUND_SLAY1 = 15529,
|
||||
SOUND_SLAY2 = 15530,
|
||||
SOUND_DEATH = 15531,
|
||||
SOUND_BERSERK = 15532,
|
||||
SOUND_TRIO = 15533,
|
||||
SOUND_DETONATING = 15534,
|
||||
SOUND_ASKHELP = 15535,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
ACTION_REMOVE_10_STACK = 10,
|
||||
@@ -322,32 +309,21 @@ public:
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER || urand(0, 2))
|
||||
return;
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
me->Yell("Forgive me.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAY1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("From your death springs life anew!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAY2);
|
||||
}
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
// kaboom!
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
me->Yell("His hold on me dissipates. I can see clearly once more. Thank you, heroes.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_DEATH);
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
damage = 0;
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetHealth(me->GetMaxHealth());
|
||||
me->CombatStop();
|
||||
me->RemoveAllAuras();
|
||||
me->AttackStop();
|
||||
events.Reset();
|
||||
|
||||
summons.DespawnAll();
|
||||
@@ -360,7 +336,7 @@ public:
|
||||
continue;
|
||||
|
||||
if (Creature* e = ObjectAccessor::GetCreature(*me, _elderGUID[i]))
|
||||
Unit::Kill(e, e);
|
||||
e->DespawnOrUnsummon();
|
||||
|
||||
++_elderCount;
|
||||
}
|
||||
@@ -397,12 +373,12 @@ public:
|
||||
void SpawnWave()
|
||||
{
|
||||
_waveNumber = _waveNumber == 1 ? 3 : _waveNumber - 1;
|
||||
Talk(EMOTE_ALLIES_OF_NATURE);
|
||||
|
||||
// Wave of three
|
||||
if (_waveNumber == 1)
|
||||
{
|
||||
me->Yell("Children, assist me!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_TRIO);
|
||||
Talk(SAY_SUMMON_TRIO);
|
||||
me->SummonCreature(NPC_ANCIENT_WATER_SPIRIT, me->GetPositionX() + urand(5, 15), me->GetPositionY() + urand(5, 15), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
|
||||
me->SummonCreature(NPC_STORM_LASHER, me->GetPositionX() + urand(5, 15), me->GetPositionY() + urand(5, 15), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
|
||||
me->SummonCreature(NPC_SNAPLASHER, me->GetPositionX() + urand(5, 15), me->GetPositionY() + urand(5, 15), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
|
||||
@@ -410,15 +386,13 @@ public:
|
||||
// Ancient Conservator
|
||||
else if (_waveNumber == 2)
|
||||
{
|
||||
me->Yell("Eonar, your servant requires aid!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_CONSERVATOR);
|
||||
Talk(SAY_SUMMON_CONSERVATOR);
|
||||
me->SummonCreature(NPC_ANCIENT_CONSERVATOR, me->GetPositionX() + urand(5, 15), me->GetPositionY() + urand(5, 15), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()), 0, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
}
|
||||
// Detonating Lashers
|
||||
else if (_waveNumber == 3)
|
||||
{
|
||||
me->Yell("The swarm of the elements shall overtake you!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_DETONATING);
|
||||
Talk(SAY_SUMMON_LASHERS);
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
me->SummonCreature(NPC_DETONATING_LASHER, me->GetPositionX() + urand(5, 20), me->GetPositionY() + urand(5, 20), me->GetMapHeight(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()), 0, TEMPSUMMON_CORPSE_DESPAWN);
|
||||
}
|
||||
@@ -553,13 +527,11 @@ public:
|
||||
|
||||
if (_elderGUID[0] || _elderGUID[1] || _elderGUID[2])
|
||||
{
|
||||
me->Yell("Elders, grant me your strength!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_ELDERS);
|
||||
Talk(SAY_AGGRO_WITH_ELDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("The Conservatory must be protected!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_AGGRO);
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,6 +567,7 @@ public:
|
||||
break;
|
||||
case EVENT_FREYA_LIFEBINDER:
|
||||
{
|
||||
Talk(EMOTE_LIFEBINDERS_GIFT);
|
||||
events.RepeatEvent(45000);
|
||||
float x, y, z;
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
@@ -643,15 +616,16 @@ public:
|
||||
break;
|
||||
}
|
||||
case EVENT_FREYA_BERSERK:
|
||||
me->Yell("You have strayed too far, wasted too much time!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_BERSERK);
|
||||
Talk(SAY_BERSERK);
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
case EVENT_FREYA_GROUND_TREMOR:
|
||||
Talk(EMOTE_GROUND_TREMOR);
|
||||
me->CastSpell(me, SPELL_GROUND_TREMOR_FREYA, false);
|
||||
events.RepeatEvent(25000 + urand(0, 10000));
|
||||
break;
|
||||
case EVENT_FREYA_IRON_ROOT:
|
||||
Talk(EMOTE_IRON_ROOTS);
|
||||
me->CastCustomSpell(SPELL_IRON_ROOTS_FREYA, SPELLVALUE_MAX_TARGETS, 1, me, false);
|
||||
events.RepeatEvent(45000 + urand(0, 10000));
|
||||
break;
|
||||
@@ -706,24 +680,14 @@ public:
|
||||
if (urand(0, 1))
|
||||
return;
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
me->TextEmote("Angry roar");
|
||||
me->PlayDirectSound(SOUND_STONEBARK_SLAY1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("Such a waste.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_STONEBARK_SLAY2);
|
||||
}
|
||||
Talk(SAY_ELDER_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (killer && me->GetEntry() == killer->GetEntry())
|
||||
return;
|
||||
me->Yell("Matron, flee! They are ruthless....", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_STONEBARK_DEATH);
|
||||
Talk(SAY_ELDER_DEATH);
|
||||
|
||||
// Lumberjacked
|
||||
if (me->GetInstanceScript())
|
||||
@@ -737,8 +701,8 @@ public:
|
||||
events.ScheduleEvent(EVENT_STONEBARK_GROUND_TREMOR, 5000);
|
||||
events.ScheduleEvent(EVENT_STONEBARK_PETRIFIED_BARK, 20000);
|
||||
|
||||
me->Yell("This place will serve as your graveyard.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_STONEBARK_AGGRO);
|
||||
if (!me->HasAura(SPELL_DRAINED_OF_POWER)) // Prevents speech if combat is initiated by hardmode activation
|
||||
Talk(SAY_ELDER_AGGRO);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType damageType, SpellSchoolMask damageSchoolMask) override
|
||||
@@ -812,24 +776,14 @@ public:
|
||||
if (urand(0, 1))
|
||||
return;
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
me->Yell("Fertilizer.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_BRIGHTLEAF_SLAY1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("Your corpse will nourish the soil!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_BRIGHTLEAF_SLAY2);
|
||||
}
|
||||
Talk(SAY_ELDER_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (killer && me->GetEntry() == killer->GetEntry())
|
||||
return;
|
||||
me->Yell("Matron, one has fallen!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_BRIGHTLEAF_DEATH);
|
||||
Talk(SAY_ELDER_DEATH);
|
||||
|
||||
// Lumberjacked
|
||||
if (me->GetInstanceScript())
|
||||
@@ -843,8 +797,8 @@ public:
|
||||
events.ScheduleEvent(EVENT_BRIGHTLEAF_SOLAR_FLARE, 5000);
|
||||
events.ScheduleEvent(EVENT_BRIGHTLEAF_UNSTABLE_SUN_BEAM, 8000);
|
||||
|
||||
me->Yell("Matron, the Conservatory has been breached!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_BRIGHTLEAF_AGGRO);
|
||||
if (!me->HasAura(SPELL_DRAINED_OF_POWER)) // Prevents speech if combat is initiated by hardmode activation
|
||||
Talk(SAY_ELDER_AGGRO);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -933,24 +887,14 @@ public:
|
||||
if (urand(0, 1))
|
||||
return;
|
||||
|
||||
if (urand(0, 1))
|
||||
{
|
||||
me->Yell("I return you whence you came!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_IRONBRANCH_SLAY1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("BEGONE!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_IRONBRANCH_SLAY2);
|
||||
}
|
||||
Talk(SAY_ELDER_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
if (killer && me->GetEntry() == killer->GetEntry())
|
||||
return;
|
||||
me->Yell("Freya! They come for you.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_IRONBRANCH_DEATH);
|
||||
Talk(SAY_ELDER_DEATH);
|
||||
|
||||
// Lumberjacked
|
||||
if (me->GetInstanceScript())
|
||||
@@ -964,8 +908,8 @@ public:
|
||||
events.ScheduleEvent(EVENT_IRONBRANCH_IRON_ROOT, 15000);
|
||||
events.ScheduleEvent(EVENT_IRONBRANCH_THORN_SWARM, 3000);
|
||||
|
||||
me->Yell("Mortals have no place here!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_IRONBRANCH_AGGRO);
|
||||
if (!me->HasAura(SPELL_DRAINED_OF_POWER)) // Prevents speech if combat is initiated by hardmode activation
|
||||
Talk(SAY_ELDER_AGGRO);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
|
||||
@@ -57,26 +57,17 @@
|
||||
#define NPC_SCORCHED_GROUND 33123
|
||||
#define NPC_WATER_TRIGGER 22515
|
||||
|
||||
#define TEXT_AGGRO "Insolent whelps! Your blood will temper the weapons used to reclaim this world!"
|
||||
#define TEXT_ACTIVATE_CONSTRUCT "Arise, soldiers of the Iron Crucible! The Makers' will be done!"
|
||||
#define TEXT_SCORCH_1 "Let the inferno consume you!"
|
||||
#define TEXT_SCORCH_2 "BURN! Burn in the makers fire!"
|
||||
#define TEXT_SLAG_POT "I will burn away your impurities!"
|
||||
#define TEXT_SLAY_1 "More scraps for the scrapheap!"
|
||||
#define TEXT_SLAY_2 "Your bones will serve as kindling!"
|
||||
#define TEXT_BERSERK "Let it be finished!"
|
||||
#define TEXT_DEATH "I. Have. Failed."
|
||||
#define TEXT_FLAME_JETS "Ignis The Furnace Master begins to cast Flame Jets!"
|
||||
|
||||
#define SOUND_AGGRO 15564
|
||||
#define SOUND_ACTIVATE_CONSTRUCT 15565
|
||||
#define SOUND_SLAG_POT 15566
|
||||
#define SOUND_SCORCH_1 15567
|
||||
#define SOUND_SCORCH_2 15568
|
||||
#define SOUND_SLAY_1 15569
|
||||
#define SOUND_SLAY_2 15570
|
||||
#define SOUND_BERSERK 15571
|
||||
#define SOUND_DEATH 15572
|
||||
enum Texts
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SUMMON = 1,
|
||||
SAY_SLAG_POT = 2,
|
||||
SAY_SCORCH = 3,
|
||||
SAY_SLAY = 4,
|
||||
SAY_BERSERK = 5,
|
||||
SAY_DEATH = 6,
|
||||
EMOTE_JETS = 7,
|
||||
};
|
||||
|
||||
#define ACHIEV_STOKIN_THE_FURNACE_EVENT 20951
|
||||
|
||||
@@ -260,8 +251,7 @@ public:
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAME_JETS, 32000);
|
||||
events.ScheduleEvent(EVENT_GRAB, 25000);
|
||||
|
||||
me->Yell(TEXT_AGGRO, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_AGGRO);
|
||||
Talk(SAY_AGGRO);
|
||||
DoZoneInCombat();
|
||||
|
||||
if( InstanceScript* m_pInstance = me->GetInstanceScript() )
|
||||
@@ -296,24 +286,15 @@ public:
|
||||
me->setActive(false);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if( rand() % 2 )
|
||||
{
|
||||
me->Yell(TEXT_SLAY_1, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAY_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell(TEXT_SLAY_2, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAY_2);
|
||||
}
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->Yell(TEXT_DEATH, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_DEATH);
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
if( me->GetInstanceScript() )
|
||||
me->GetInstanceScript()->SetData(TYPE_IGNIS, DONE);
|
||||
@@ -357,27 +338,18 @@ public:
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_ACTIVATE_CONSTRUCT:
|
||||
Talk(SAY_SUMMON);
|
||||
me->CastCustomSpell(SPELL_ACTIVATE_CONSTRUCT, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
|
||||
if (++counter >= 20)
|
||||
{
|
||||
me->Yell(TEXT_BERSERK, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_BERSERK);
|
||||
Talk(SAY_BERSERK);
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
}
|
||||
events.RepeatEvent(RAID_MODE(40000, 30000));
|
||||
break;
|
||||
case EVENT_SPELL_SCORCH:
|
||||
if( rand() % 2 )
|
||||
{
|
||||
me->Yell(TEXT_SCORCH_1, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SCORCH_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell(TEXT_SCORCH_2, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SCORCH_2);
|
||||
}
|
||||
Talk(SAY_SCORCH);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
@@ -390,7 +362,7 @@ public:
|
||||
me->DisableRotate(false);
|
||||
break;
|
||||
case EVENT_SPELL_FLAME_JETS:
|
||||
me->TextEmote(TEXT_FLAME_JETS, nullptr, true);
|
||||
Talk(EMOTE_JETS);
|
||||
me->CastSpell(me->GetVictim(), S_FLAME_JETS, false);
|
||||
events.RepeatEvent(25000);
|
||||
break;
|
||||
@@ -429,8 +401,7 @@ public:
|
||||
int8 pos = urand(0, playerGUIDs.size() - 1);
|
||||
if( Player* pTarget = ObjectAccessor::GetPlayer(*me, playerGUIDs.at(pos)) )
|
||||
{
|
||||
me->Yell(TEXT_SLAG_POT, LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(SOUND_SLAG_POT);
|
||||
Talk(SAY_SLAG_POT);
|
||||
me->CastSpell(pTarget, SPELL_GRAB, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,72 +25,68 @@
|
||||
#include "WaypointMgr.h"
|
||||
#include "ulduar.h"
|
||||
|
||||
#define SPELL_FLAMEBUFFET_10 64016
|
||||
#define SPELL_FLAMEBUFFET_25 64023
|
||||
#define S_FLAMEBUFFET RAID_MODE(SPELL_FLAMEBUFFET_10, SPELL_FLAMEBUFFET_25)
|
||||
#define SPELL_FIREBALL 63815
|
||||
#define SPELL_WINGBUFFET 62666
|
||||
#define SPELL_FLAMEBREATH_10 63317
|
||||
#define SPELL_FLAMEBREATH_25 64021
|
||||
#define S_FLAMEBREATH RAID_MODE(SPELL_FLAMEBREATH_10, SPELL_FLAMEBREATH_25)
|
||||
#define SPELL_FUSEARMOR 64771
|
||||
#define SPELL_DEVOURINGFLAME 63236
|
||||
#define SPELL_BERSERK 47008
|
||||
enum Spells
|
||||
{
|
||||
// Razorscale
|
||||
SPELL_FLAMEBUFFET_10 = 64016,
|
||||
SPELL_FLAMEBUFFET_25 = 64023,
|
||||
SPELL_FIREBALL = 63815,
|
||||
SPELL_WINGBUFFET = 62666,
|
||||
SPELL_FLAMEBREATH_10 = 63317,
|
||||
SPELL_FLAMEBREATH_25 = 64021,
|
||||
SPELL_FUSEARMOR = 64771,
|
||||
SPELL_FUSED_ARMOR = 64774, // Applied on 5th stack of SPELL_FUSEARMOR
|
||||
SPELL_DEVOURINGFLAME = 63236,
|
||||
SPELL_BERSERK = 47008,
|
||||
|
||||
#define SPELL_CHAIN_1 49679
|
||||
#define SPELL_CHAIN_2 49682
|
||||
#define SPELL_CHAIN_3 49683
|
||||
#define SPELL_CHAIN_4 49684
|
||||
#define SPELL_LAUNCH_CHAIN 62505
|
||||
//#define SPELL_HARPOON_SHOT_BUFF 62509
|
||||
//#define SPELL_HARPOON_FIRE_STATE 62696
|
||||
// Haproons
|
||||
SPELL_CHAIN_1 = 49679,
|
||||
SPELL_CHAIN_2 = 49682,
|
||||
SPELL_CHAIN_3 = 49683,
|
||||
SPELL_CHAIN_4 = 49684,
|
||||
SPELL_LAUNCH_CHAIN = 62505,
|
||||
|
||||
// Dark Rune Sentinel
|
||||
SPELL_WHIRLWIND = 63808,
|
||||
SPELL_BATTLE_SHOUT_10 = 46763,
|
||||
SPELL_BATTLE_SHOUT_25 = 64062,
|
||||
|
||||
// Dark Rune Guardian
|
||||
SPELL_STORMSTRIKE_DMG = 65971,
|
||||
SPELL_STORMSTRIKE_DEBUFF = 64757,
|
||||
|
||||
// Dark Rune Watcher
|
||||
SPELL_LIGHTINGBOLT_10 = 63809,
|
||||
SPELL_LIGHTINGBOLT_25 = 64696,
|
||||
SPELL_CHAINLIGHTNING_10 = 64758,
|
||||
SPELL_CHAINLIGHTNING_25 = 64759,
|
||||
};
|
||||
|
||||
#define SPELL_FLAMEBUFFET RAID_MODE(SPELL_FLAMEBUFFET_10, SPELL_FLAMEBUFFET_25)
|
||||
#define SPELL_FLAMEBREATH RAID_MODE(SPELL_FLAMEBREATH_10, SPELL_FLAMEBREATH_25)
|
||||
#define SPELL_BATTLE_SHOUT RAID_MODE(SPELL_BATTLE_SHOUT_10, SPELL_BATTLE_SHOUT_25)
|
||||
#define SPELL_LIGHTINGBOLT RAID_MODE(SPELL_LIGHTINGBOLT_10, SPELL_LIGHTINGBOLT_25)
|
||||
#define SPELL_CHAINLIGHTNING RAID_MODE(SPELL_CHAINLIGHTNING_10, SPELL_CHAINLIGHTNING_25)
|
||||
#define REQ_CHAIN_COUNT RAID_MODE(2, 4)
|
||||
|
||||
#define SPELL_DEVOURINGFLAME_SUMMON 63308
|
||||
//#define SPELL_DEVOURINGFLAME_GROUNDAURA_10 64709
|
||||
//#define SPELL_DEVOURINGFLAME_GROUNDAURA_25 64734
|
||||
//#define S_DEVOURINGFLAME_GROUNDAURA RAID_MODE(SPELL_DEVOURINGFLAME_GROUNDAURA_10, SPELL_DEVOURINGFLAME_GROUNDAURA_25)
|
||||
//#define NPC_DEVOURINGFLAME 34188
|
||||
#define SPELL_STORMSTRIKE 51876
|
||||
#define SPELL_WHIRLWIND 63808
|
||||
#define SPELL_LIGHTINGBOLT 63809
|
||||
#define SPELL_CHAINLIGHTNING 64758
|
||||
|
||||
#define NPC_DARK_RUNE_SENTINEL 33846
|
||||
#define NPC_DARK_RUNE_GUARDIAN 33388
|
||||
#define NPC_DARK_RUNE_WATCHER 33453
|
||||
#define NPC_EXPEDITION_ENGINEER 33287
|
||||
#define NPC_EXPEDITION_COMMANDER 33210
|
||||
//#define NPC_EXPEDITION_DEFENDER 33816
|
||||
//#define NPC_EXPEDITION_TRAPPER 33259
|
||||
#define NPC_RAZORSCALE 33186
|
||||
//#define NPC_HARPOON_FIRE_STATE 33282
|
||||
|
||||
#define GO_DRILL 195305
|
||||
#define GO_HARPOON_GUN_1 194519
|
||||
#define GO_HARPOON_GUN_2 194541
|
||||
#define GO_HARPOON_GUN_3 194542
|
||||
#define GO_HARPOON_GUN_4 194543
|
||||
#define GO_BROKEN_HARPOON 194565
|
||||
|
||||
#define TEXT_GOSSIP_ACTION "We are ready to help!"
|
||||
#define TEXT_EE_AGGRO "Give us a moment to prepare to build the turrets."
|
||||
#define TEXT_EE_MOVE_OUT "Ready to move out, keep those dwarves off of our backs!"
|
||||
#define TEXT_EE_FIRES_OUT "Fires out! Let's rebuild those turrets!"
|
||||
|
||||
#define TEXT_TURRET_READY "Harpoon Turret is ready for use!"
|
||||
#define TEXT_DEEP_BREATH "Razorscale takes a deep breath..."
|
||||
#define TEXT_GROUNDED_PERMANENTLY "Razorscale grounded permanently!"
|
||||
|
||||
#define CORDS_GROUND 588.0f, -166.0f, 391.1f
|
||||
#define CORDS_AIR 588.0f, -178.0f, 490.0f
|
||||
#define REPAIR_POINTS 25
|
||||
|
||||
enum eSay
|
||||
enum NPCs
|
||||
{
|
||||
SAY_COMMANDER_INTRO = 0,
|
||||
SAY_COMMANDER_GROUND = 1,
|
||||
SAY_COMMANDER_AGGRO = 2
|
||||
NPC_DARK_RUNE_SENTINEL = 33846,
|
||||
NPC_DARK_RUNE_GUARDIAN = 33388,
|
||||
NPC_DARK_RUNE_WATCHER = 33453,
|
||||
NPC_EXPEDITION_ENGINEER = 33287,
|
||||
NPC_EXPEDITION_COMMANDER = 33210,
|
||||
NPC_RAZORSCALE_CONTROLLER = 33233, // Trigger Creature
|
||||
};
|
||||
|
||||
enum GOs
|
||||
{
|
||||
GO_DRILL = 195305,
|
||||
GO_HARPOON_GUN_1 = 194519,
|
||||
GO_HARPOON_GUN_2 = 194541,
|
||||
GO_HARPOON_GUN_3 = 194542,
|
||||
GO_HARPOON_GUN_4 = 194543,
|
||||
GO_BROKEN_HARPOON = 194565,
|
||||
};
|
||||
|
||||
enum eEvents
|
||||
@@ -113,11 +109,40 @@ enum eEvents
|
||||
EVENT_SPELL_FLAME_BUFFET,
|
||||
};
|
||||
|
||||
enum eMisc
|
||||
enum Texts
|
||||
{
|
||||
POINT_RAZORSCALE_INIT = 1
|
||||
// Razorscale
|
||||
EMOTE_PERMA_GROUND = 0,
|
||||
EMOTE_BREATH = 1,
|
||||
EMOTE_BERSERK = 2,
|
||||
|
||||
// Expedition Commander
|
||||
SAY_COMMANDER_AGGRO = 0,
|
||||
SAY_COMMANDER_GROUND_PHASE = 1,
|
||||
SAY_COMMANDER_ENGINEERS_DEAD = 2, // Should be called when all engineers are dead, currently unused
|
||||
|
||||
// Expedition Engineer
|
||||
SAY_EE_AGGRO = 0,
|
||||
SAY_EE_START_REPAIR = 1,
|
||||
SAY_EE_REBUILD_TURRETS = 2,
|
||||
|
||||
// Harpoon
|
||||
EMOTE_HARPOON = 0,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
POINT_RAZORSCALE_INIT = 1,
|
||||
REPAIR_POINTS = 25,
|
||||
|
||||
// Expedition Commander Gossip
|
||||
GOSSIP_MENU_START_ENCOUNTER = 10314,
|
||||
NPC_TEXT_COMMANDER = 40100,
|
||||
};
|
||||
|
||||
const Position CORDS_GROUND = {588.0f, -166.0f, 391.1f};
|
||||
const Position CORDS_AIR = {588.0f, -178.0f, 490.0f};
|
||||
|
||||
class boss_razorscale : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -161,6 +186,11 @@ public:
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
ExpeditionEngineerGUIDs[i].Clear();
|
||||
|
||||
// Show gossip icon if previously hidden
|
||||
if (Creature* commander = ObjectAccessor::GetCreature(*me, CommanderGUID))
|
||||
if (!commander->HasNpcFlag(UNIT_NPC_FLAG_GOSSIP))
|
||||
commander->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
CommanderGUID.Clear();
|
||||
bGroundPhase = false;
|
||||
flyTimes = 0;
|
||||
@@ -195,7 +225,7 @@ public:
|
||||
break;
|
||||
ExpeditionEngineerGUIDs[i] = (*itr)->GetGUID();
|
||||
if (!i)
|
||||
(*itr)->Yell(TEXT_EE_AGGRO, LANG_UNIVERSAL);
|
||||
(*itr)->AI()->Talk(SAY_EE_AGGRO);
|
||||
++i;
|
||||
}
|
||||
if (Creature* c = me->FindNearestCreature(NPC_EXPEDITION_COMMANDER, 300.0f, true))
|
||||
@@ -260,7 +290,7 @@ public:
|
||||
if( count >= REQ_CHAIN_COUNT )
|
||||
{
|
||||
if (Creature* commander = ObjectAccessor::GetCreature(*me, CommanderGUID))
|
||||
commander->AI()->Talk(SAY_COMMANDER_GROUND);
|
||||
commander->AI()->Talk(SAY_COMMANDER_GROUND_PHASE);
|
||||
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
events.CancelEvent(EVENT_SPELL_FIREBALL);
|
||||
@@ -348,8 +378,8 @@ public:
|
||||
case 0:
|
||||
break;
|
||||
case EVENT_ENRAGE:
|
||||
Talk(EMOTE_BERSERK);
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
events.RepeatEvent(600000);
|
||||
break;
|
||||
case EVENT_COMMANDER_SAY_AGGRO:
|
||||
if (Creature* commander = ObjectAccessor::GetCreature(*me, CommanderGUID))
|
||||
@@ -360,7 +390,7 @@ public:
|
||||
if (Creature* c = ObjectAccessor::GetCreature(*me, ExpeditionEngineerGUIDs[i]))
|
||||
{
|
||||
if (!i)
|
||||
c->Yell(TEXT_EE_MOVE_OUT, LANG_UNIVERSAL);
|
||||
c->AI()->Talk(SAY_EE_START_REPAIR);
|
||||
c->AI()->SetData(1, 0); // start repairing
|
||||
}
|
||||
break;
|
||||
@@ -454,12 +484,12 @@ public:
|
||||
}
|
||||
break;
|
||||
case EVENT_WARN_DEEP_BREATH:
|
||||
me->TextEmote(TEXT_DEEP_BREATH, nullptr, true);
|
||||
Talk(EMOTE_BREATH);
|
||||
me->RemoveAura(62794);
|
||||
events.ScheduleEvent(EVENT_PHASE2_FLAME_BREATH, 2500);
|
||||
break;
|
||||
case EVENT_PHASE2_FLAME_BREATH:
|
||||
me->CastSpell(me, S_FLAMEBREATH, true);
|
||||
me->CastSpell(me, SPELL_FLAMEBREATH, true);
|
||||
events.ScheduleEvent(EVENT_FLY_UP, 2000);
|
||||
break;
|
||||
case EVENT_FLY_UP:
|
||||
@@ -485,6 +515,7 @@ public:
|
||||
|
||||
if( (me->GetHealth() * 100) / me->GetMaxHealth() < 50 ) // start phase 3
|
||||
{
|
||||
Talk(EMOTE_PERMA_GROUND);
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(false);
|
||||
DoResetThreat();
|
||||
@@ -527,12 +558,12 @@ public:
|
||||
if (Creature* c = ObjectAccessor::GetCreature(*me, ExpeditionEngineerGUIDs[i]))
|
||||
{
|
||||
if (!i)
|
||||
c->Yell(TEXT_EE_FIRES_OUT, LANG_UNIVERSAL);
|
||||
c->AI()->Talk(SAY_EE_REBUILD_TURRETS);
|
||||
c->AI()->SetData(1, 0); // start repairing
|
||||
}
|
||||
break;
|
||||
case EVENT_SPELL_FLAME_BREATH:
|
||||
me->CastSpell(me->GetVictim(), S_FLAMEBREATH, false);
|
||||
me->CastSpell(me->GetVictim(), SPELL_FLAMEBREATH, false);
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
case EVENT_SPELL_DEVOURING_FLAME_GROUND:
|
||||
@@ -546,14 +577,14 @@ public:
|
||||
me->CastSpell(victim, SPELL_FUSEARMOR, false);
|
||||
if (Aura* aur = victim->GetAura(SPELL_FUSEARMOR))
|
||||
if (aur->GetStackAmount() == 5)
|
||||
victim->CastSpell(victim, 64774, true);
|
||||
victim->CastSpell(victim, SPELL_FUSED_ARMOR, true);
|
||||
events.RepeatEvent(10000);
|
||||
break;
|
||||
}
|
||||
events.RepeatEvent(2000);
|
||||
break;
|
||||
case EVENT_SPELL_FLAME_BUFFET:
|
||||
me->CastSpell(me->GetVictim(), S_FLAMEBUFFET, false);
|
||||
me->CastSpell(me->GetVictim(), SPELL_FLAMEBUFFET, false);
|
||||
events.RepeatEvent(7000);
|
||||
break;
|
||||
}
|
||||
@@ -619,8 +650,8 @@ public:
|
||||
if (!razorscale || razorscale->IsInCombat())
|
||||
return true;
|
||||
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, TEXT_GOSSIP_ACTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, 40100, creature);
|
||||
AddGossipItemFor(player, GOSSIP_MENU_START_ENCOUNTER, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, NPC_TEXT_COMMANDER, creature);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -638,6 +669,9 @@ public:
|
||||
Creature* razorscale = ObjectAccessor::GetCreature(*creature, instance->GetGuidData(TYPE_RAZORSCALE));
|
||||
if (razorscale && !razorscale->IsInCombat())
|
||||
{
|
||||
// Do not show gossip icon if encounter is in progress
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
// reset npcs NPC_HARPOON_FIRE_STATE
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
if (Creature* hfs = ObjectAccessor::GetCreature(*creature, instance->GetGuidData(DATA_HARPOON_FIRE_STATE_1 + i)))
|
||||
@@ -679,7 +713,7 @@ public:
|
||||
return;
|
||||
|
||||
_introSpoken = true;
|
||||
Talk(SAY_COMMANDER_INTRO);
|
||||
//Talk(SAY_COMMANDER_INTRO); // No source leads to showing any text messages, perhaps only SOUND ID 15647 is played?
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -758,7 +792,8 @@ public:
|
||||
if( GameObject* wh = me->SummonGameObject(GetHarpoonGunIdForThisHFS(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 3 * M_PI / 2, 0.0f, 0.0f, 0.0f, 0.0f, 0) )
|
||||
{
|
||||
me->RemoveGameObject(wh, false);
|
||||
me->TextEmote(TEXT_TURRET_READY, nullptr, true);
|
||||
if (Creature* cr = me->SummonCreature(NPC_RAZORSCALE_CONTROLLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 5000))
|
||||
cr->AI()->Talk(EMOTE_HARPOON);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -987,9 +1022,9 @@ public:
|
||||
else timer2 -= diff;
|
||||
if (timer2 == 0 && me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), 65971, true);
|
||||
me->CastSpell(me->GetVictim(), 65971, true); // me->CastSpell(me->GetVictim(), 65972, true); // cast the same twice cus second one requires setting offhand damage
|
||||
me->CastSpell(me->GetVictim(), 64757, true);
|
||||
me->CastSpell(me->GetVictim(), SPELL_STORMSTRIKE_DMG, true);
|
||||
me->CastSpell(me->GetVictim(), SPELL_STORMSTRIKE_DMG, true); // cast the same twice cus second one requires setting offhand damage
|
||||
me->CastSpell(me->GetVictim(), SPELL_STORMSTRIKE_DEBUFF, true);
|
||||
timer2 = urand(8000, 10000);
|
||||
return;
|
||||
}
|
||||
@@ -1034,7 +1069,7 @@ public:
|
||||
|
||||
if( timer1 <= diff )
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), RAID_MODE(64758, 64759), false);
|
||||
me->CastSpell(me->GetVictim(), SPELL_CHAINLIGHTNING, false);
|
||||
timer1 = urand(10000, 12000);
|
||||
return;
|
||||
}
|
||||
@@ -1043,7 +1078,7 @@ public:
|
||||
|
||||
if (timer2 <= diff)
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), RAID_MODE(63809, 64696), false);
|
||||
me->CastSpell(me->GetVictim(), SPELL_LIGHTINGBOLT, false);
|
||||
timer2 = 4000;
|
||||
return;
|
||||
}
|
||||
@@ -1090,7 +1125,7 @@ public:
|
||||
|
||||
if( timer1 <= diff )
|
||||
{
|
||||
me->CastSpell(me, RAID_MODE(46763, 64062), false);
|
||||
me->CastSpell(me, SPELL_BATTLE_SHOUT, false);
|
||||
timer1 = urand(15000, 20000);
|
||||
}
|
||||
else
|
||||
@@ -1100,7 +1135,7 @@ public:
|
||||
else timer2 -= diff;
|
||||
if (timer2 == 0 && me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->CastSpell(me, 63808, false);
|
||||
me->CastSpell(me, SPELL_WHIRLWIND, false);
|
||||
timer2 = urand(10000, 12000);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,17 +91,20 @@ enum NPCs
|
||||
NPC_PILE_TRIGGER = 33337,
|
||||
};
|
||||
|
||||
enum Sounds
|
||||
enum Texts
|
||||
{
|
||||
XT_SOUND_AGGRO = 15724,
|
||||
XT_SOUND_HEART_OPEN = 15725,
|
||||
XT_SOUND_HEART_CLOSED = 15726,
|
||||
XT_SOUND_TANTARUM = 15727,
|
||||
XT_SOUND_SLAY1 = 15728,
|
||||
XT_SOUND_SLAY2 = 15729,
|
||||
XT_SOUND_ENRAGE = 15730,
|
||||
XT_SOUND_DEATH = 15731,
|
||||
XT_SOUND_SUMMON = 15732,
|
||||
SAY_AGGRO = 0,
|
||||
SAY_HEART_OPENED = 1,
|
||||
SAY_HEART_CLOSED = 2,
|
||||
SAY_TYMPANIC_TANTRUM = 3,
|
||||
SAY_SLAY = 4,
|
||||
SAY_BERSERK = 5,
|
||||
SAY_DEATH = 6,
|
||||
SAY_SUMMON = 7,
|
||||
EMOTE_HEART_OPENED = 8,
|
||||
EMOTE_HEART_CLOSED = 9,
|
||||
EMOTE_TYMPANIC_TANTRUM = 10,
|
||||
EMOTE_SCRAPBOT = 11,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
@@ -203,8 +206,7 @@ public:
|
||||
RescheduleEvents(); // Other events are scheduled here
|
||||
|
||||
me->setActive(true);
|
||||
me->Yell("New toys? For me? I promise I won't break them this time!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_AGGRO);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
if (m_pInstance)
|
||||
{
|
||||
@@ -223,23 +225,13 @@ public:
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && !urand(0, 2))
|
||||
{
|
||||
if (urand(0, 1))
|
||||
{
|
||||
me->Yell("I... I think I broke it.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_SLAY1);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Yell("I guess it doesn't bend that way.", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_SLAY2);
|
||||
}
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->Yell("You are bad... Toys... Very... Baaaaad!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_DEATH);
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
if (m_pInstance)
|
||||
{
|
||||
@@ -279,7 +271,7 @@ public:
|
||||
|
||||
me->CastSpell(me, SPELL_HEARTBREAK, true);
|
||||
|
||||
me->TextEmote("XT-002 Deconstructor's heart is severed from his body.", nullptr, true);
|
||||
Talk(EMOTE_HEART_CLOSED);
|
||||
events.ScheduleEvent(EVENT_REMOVE_EMOTE, 4000);
|
||||
return;
|
||||
}
|
||||
@@ -329,8 +321,7 @@ public:
|
||||
me->SetControlled(true, UNIT_STATE_STUNNED);
|
||||
me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_SUBMERGED); // submerge with animation
|
||||
|
||||
me->Yell("So tired. I will rest for just a moment!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_HEART_OPEN);
|
||||
Talk(SAY_HEART_OPENED);
|
||||
|
||||
events.CancelEventGroup(1);
|
||||
events.ScheduleEvent(EVENT_START_SECOND_PHASE, 5000);
|
||||
@@ -355,21 +346,19 @@ public:
|
||||
events.ScheduleEvent(EVENT_GRAVITY_BOMB, 10000, 1);
|
||||
break;
|
||||
case EVENT_TYMPANIC_TANTARUM:
|
||||
me->TextEmote("XT-002 Deconstructor begins to cause the earth to quake.", nullptr, true);
|
||||
me->Yell("NO! NO! NO! NO! NO!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_TANTARUM);
|
||||
Talk(EMOTE_TYMPANIC_TANTRUM);
|
||||
Talk(SAY_TYMPANIC_TANTRUM);
|
||||
me->CastSpell(me, SPELL_TYMPANIC_TANTARUM, true);
|
||||
events.RepeatEvent(60000);
|
||||
return;
|
||||
case EVENT_ENRAGE:
|
||||
me->Yell("I'm tired of these toys. I don't want to play anymore!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_ENRAGE);
|
||||
Talk(SAY_BERSERK);
|
||||
me->CastSpell(me, SPELL_XT002_ENRAGE, true);
|
||||
break;
|
||||
|
||||
// Animation events
|
||||
case EVENT_START_SECOND_PHASE:
|
||||
me->TextEmote("XT-002 Deconstructor's heart is exposed and leaking energy.", nullptr, true);
|
||||
Talk(EMOTE_HEART_OPENED);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : nullptr)
|
||||
heart->GetAI()->DoAction(ACTION_AWAKEN_HEART);
|
||||
@@ -383,8 +372,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
me->Yell("I'm ready to play!", LANG_UNIVERSAL);
|
||||
me->PlayDirectSound(XT_SOUND_HEART_CLOSED);
|
||||
Talk(SAY_HEART_CLOSED);
|
||||
|
||||
me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_STAND); // emerge
|
||||
// Hide heart
|
||||
@@ -619,7 +607,7 @@ public:
|
||||
}
|
||||
|
||||
if (!urand(0, 2))
|
||||
me->TextEmote("XT-002 Deconstructor consumes scrap bot to repair himself.", nullptr, true);
|
||||
pXT002->AI()->Talk(EMOTE_SCRAPBOT);
|
||||
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
@@ -28,11 +28,14 @@ enum Misc
|
||||
// TEXTS
|
||||
SAY_AGGRO = 0,
|
||||
SAY_KILL = 1,
|
||||
EMOTE_RANGE = 2,
|
||||
SAY_DEATH = 3,
|
||||
SAY_DRAKE_DEATH = 5,
|
||||
SAY_DRAKE_BREATH = 6,
|
||||
|
||||
// EMOTES
|
||||
EMOTE_DEEP_BREATH = 0,
|
||||
EMOTE_RANGE = 1,
|
||||
|
||||
// SPELLS
|
||||
SPELL_CRUSH_N = 50234,
|
||||
SPELL_CRUSH_H = 59330,
|
||||
@@ -41,9 +44,9 @@ enum Misc
|
||||
SPELL_WHIRLWIND_N = 50228,
|
||||
SPELL_WHIRLWIND_H = 50228,
|
||||
|
||||
SPELL_FLAME_VISUAL = 47592,
|
||||
SPELL_FLAME_BREATH_N = 47579,
|
||||
SPELL_FLAME_BREATH_H = 60020,
|
||||
SPELL_FREEZING_CLOUD_VISUAL = 47592,
|
||||
SPELL_FREEZING_CLOUD_N = 47579,
|
||||
SPELL_FREEZING_CLOUD_H = 60020,
|
||||
|
||||
SPELL_LAUNCH_HARPOON = 48642,
|
||||
|
||||
@@ -95,8 +98,6 @@ static Position SkadiPosition[] =
|
||||
{490.76f, -517.389f, 123.368f, 0.0f}
|
||||
};
|
||||
|
||||
#define EMOTE_IN_RANGE "Skadi the Ruthless is within range of the harpoon launchers"
|
||||
|
||||
enum phase
|
||||
{
|
||||
PHASE_NONE,
|
||||
@@ -323,8 +324,8 @@ public:
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id == 47593) // SPELL_FLAME_VISUAL trigger
|
||||
target->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
|
||||
if (spellInfo->Id == 47593) // SPELL_FREEZING_CLOUD_VISUAL trigger
|
||||
target->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_FREEZING_CLOUD_H : SPELL_FREEZING_CLOUD_N, true);
|
||||
}
|
||||
|
||||
void SpawnFlameTriggers(uint8 point)
|
||||
@@ -341,13 +342,13 @@ public:
|
||||
{
|
||||
Creature* cr;
|
||||
if ((cr = me->SummonCreature(NPC_BREATH_TRIGGER, 483, -484.9f, 105, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)))
|
||||
cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
|
||||
cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FREEZING_CLOUD_H : SPELL_FREEZING_CLOUD_N, true);
|
||||
if ((cr = me->SummonCreature(NPC_BREATH_TRIGGER, 471.0f, -484.7f, 105, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)))
|
||||
cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
|
||||
cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FREEZING_CLOUD_H : SPELL_FREEZING_CLOUD_N, true);
|
||||
|
||||
for (uint8 j = 0; j < 7; j++)
|
||||
if ((cr = me->SummonCreature(NPC_BREATH_TRIGGER, 477.0f, -507.0f + (j * 3), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)))
|
||||
cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FLAME_BREATH_H : SPELL_FLAME_BREATH_N, true);
|
||||
cr->CastSpell(cr, cr->GetMap()->IsHeroic() ? SPELL_FREEZING_CLOUD_H : SPELL_FREEZING_CLOUD_N, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,15 +358,14 @@ public:
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
me->RemoveAurasDueToSpell(SPELL_FLAME_VISUAL);
|
||||
me->RemoveAurasDueToSpell(SPELL_FREEZING_CLOUD_VISUAL);
|
||||
me->SetFacingTo(M_PI * 2);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
if (m_pInstance)
|
||||
m_pInstance->SetData(SKADI_IN_RANGE, 1);
|
||||
|
||||
me->TextEmote(EMOTE_IN_RANGE, nullptr, true);
|
||||
Talk(EMOTE_RANGE);
|
||||
me->SetFacingTo(M_PI);
|
||||
break;
|
||||
}
|
||||
@@ -466,8 +466,9 @@ public:
|
||||
me->GetMotionMaster()->MovePoint(targetPoint, SkadiPosition[targetPoint].GetPositionX(), SkadiPosition[targetPoint].GetPositionY(), SkadiPosition[targetPoint].GetPositionZ());
|
||||
if (targetPoint <= 1)
|
||||
{
|
||||
Talk(EMOTE_DEEP_BREATH);
|
||||
SpawnFlameTriggers(targetPoint);
|
||||
me->CastSpell(me, SPELL_FLAME_VISUAL, false);
|
||||
me->CastSpell(me, SPELL_FREEZING_CLOUD_VISUAL, false);
|
||||
}
|
||||
|
||||
if (m_pInstance)
|
||||
|
||||
@@ -1472,6 +1472,48 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum OnslaughtGryphon
|
||||
{
|
||||
SPELL_DELIVER_GRYPHON = 54420,
|
||||
SPELL_ONSLAUGHT_GRYPHON = 49641,
|
||||
|
||||
NPC_CAPTURED_ONSLAUGHT_GRYPHON = 29415,
|
||||
|
||||
SEAT_PLAYER = 0
|
||||
};
|
||||
|
||||
class spell_deliver_gryphon : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_deliver_gryphon);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_DELIVER_GRYPHON, SPELL_ONSLAUGHT_GRYPHON });
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Vehicle* gryphon = caster->GetVehicleKit())
|
||||
{
|
||||
if (Unit* player = gryphon->GetPassenger(SEAT_PLAYER))
|
||||
{
|
||||
player->ExitVehicle();
|
||||
player->RemoveAurasDueToSpell(VEHICLE_SPELL_PARACHUTE);
|
||||
player->RemoveAurasDueToSpell(SPELL_ONSLAUGHT_GRYPHON);
|
||||
player->SummonCreature(NPC_CAPTURED_ONSLAUGHT_GRYPHON, 7434.7f, 4213.3f, 316.52f, 3.88f, TEMPSUMMON_TIMED_DESPAWN, 1 * MINUTE * IN_MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_deliver_gryphon::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
// Theirs
|
||||
/*######
|
||||
## npc_guardian_pavilion
|
||||
@@ -2159,6 +2201,7 @@ void AddSC_icecrown()
|
||||
new spell_anti_air_rocket_bomber();
|
||||
new npc_infra_green_bomber_generic();
|
||||
new spell_onslaught_or_call_bone_gryphon();
|
||||
RegisterSpellScript(spell_deliver_gryphon);
|
||||
|
||||
// Theirs
|
||||
new npc_guardian_pavilion();
|
||||
|
||||
@@ -28,13 +28,17 @@
|
||||
#define QUEST_SUMMON_AHUNE 11691
|
||||
#define ITEM_MAGMA_TOTEM 34953
|
||||
#define AHUNE_DEFAULT_MODEL 23344
|
||||
#define TEXT_RETREAT "Ahune Retreats. His defenses diminish."
|
||||
#define TEXT_RESURFACE "Ahune will soon resurface."
|
||||
|
||||
const Position AhuneSummonPos = {-97.3473f, -233.139f, -1.27587f, M_PI / 2};
|
||||
const Position TotemPos[3] = { {-115.141f, -143.317f, -2.09467f, 4.92772f}, {-120.178f, -144.398f, -2.23786f, 4.92379f}, {-125.277f, -145.463f, -1.95209f, 4.97877f} };
|
||||
const Position MinionSummonPos = {-97.154404f, -204.382675f, -1.19f, M_PI / 2};
|
||||
|
||||
enum Text
|
||||
{
|
||||
EMOTE_RETREAT = 0,
|
||||
EMOTE_RESURFACE = 1,
|
||||
};
|
||||
|
||||
enum EventSpells
|
||||
{
|
||||
SPELL_STARTING_BEAM = 46593,
|
||||
@@ -192,7 +196,7 @@ public:
|
||||
events.RescheduleEvent(EVENT_SUBMERGE, 10000);
|
||||
break;
|
||||
case EVENT_SUBMERGE:
|
||||
me->TextEmote(TEXT_RETREAT, nullptr, true);
|
||||
Talk(EMOTE_RETREAT);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->CastSpell(me, SPELL_SUBMERGE_0, true);
|
||||
me->CastSpell(me, SPELL_SELF_STUN, true);
|
||||
@@ -205,7 +209,7 @@ public:
|
||||
events.RescheduleEvent(EVENT_EMERGE_WARNING, 20000);
|
||||
break;
|
||||
case EVENT_EMERGE_WARNING:
|
||||
me->TextEmote(TEXT_RESURFACE, nullptr, true);
|
||||
Talk(EMOTE_RESURFACE);
|
||||
break;
|
||||
case EVENT_COMBAT_EMERGE:
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
Reference in New Issue
Block a user