mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-26 07:06:23 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -49,13 +49,15 @@ public:
|
||||
{
|
||||
static ChatCommandTable deserterInstanceCommandTable =
|
||||
{
|
||||
{ "add", HandleDeserterInstanceAdd, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "remove", HandleDeserterInstanceRemove, SEC_ADMINISTRATOR, Console::No }
|
||||
{ "add", HandleDeserterInstanceAdd, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "remove all", HandleDeserterInstanceRemoveAll, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "remove", HandleDeserterInstanceRemove, SEC_ADMINISTRATOR, Console::Yes }
|
||||
};
|
||||
static ChatCommandTable deserterBGCommandTable =
|
||||
{
|
||||
{ "add", HandleDeserterBGAdd, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "remove", HandleDeserterBGRemove, SEC_ADMINISTRATOR, Console::No }
|
||||
{ "add", HandleDeserterBGAdd, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "remove all", HandleDeserterBGRemoveAll, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "remove", HandleDeserterBGRemove, SEC_ADMINISTRATOR, Console::Yes }
|
||||
};
|
||||
|
||||
static ChatCommandTable deserterCommandTable =
|
||||
@@ -90,9 +92,13 @@ public:
|
||||
* .deserter bg add 3600 (one hour)
|
||||
* @endcode
|
||||
*/
|
||||
static bool HandleDeserterAdd(ChatHandler* handler, uint32 time, bool isInstance)
|
||||
static bool HandleDeserterAdd(ChatHandler* handler, Optional<PlayerIdentifier> player, uint32 time, bool isInstance)
|
||||
{
|
||||
Player* player = handler->getSelectedPlayer();
|
||||
if (!player)
|
||||
{
|
||||
player = PlayerIdentifier::FromTargetOrSelf(handler);
|
||||
}
|
||||
|
||||
if (!player)
|
||||
{
|
||||
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
|
||||
@@ -107,15 +113,42 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
Aura* aura = player->AddAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER, player);
|
||||
Player* target = player->GetConnectedPlayer();
|
||||
|
||||
if (!aura)
|
||||
if (target)
|
||||
{
|
||||
handler->SendSysMessage(LANG_BAD_VALUE);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
Aura* aura = target->AddAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER, target);
|
||||
|
||||
if (!aura)
|
||||
{
|
||||
handler->SendSysMessage(LANG_BAD_VALUE);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
aura->SetDuration(time * IN_MILLISECONDS);
|
||||
|
||||
return true;
|
||||
}
|
||||
aura->SetDuration(time * IN_MILLISECONDS);
|
||||
|
||||
uint8 index = 0;
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AURA);
|
||||
stmt->SetData(index++, player->GetGUID().GetCounter());
|
||||
stmt->SetData(index++, player->GetGUID().GetCounter());
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
stmt->SetData(index++, 1);
|
||||
stmt->SetData(index++, 1);
|
||||
stmt->SetData(index++, 1);
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, 0);
|
||||
stmt->SetData(index++, isInstance ? 1800000 : 900000);
|
||||
stmt->SetData(index++, time * 1000);
|
||||
stmt->SetData(index, 0);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -139,9 +172,13 @@ public:
|
||||
* .deserter bg remove
|
||||
* @endcode
|
||||
*/
|
||||
static bool HandleDeserterRemove(ChatHandler* handler, bool isInstance)
|
||||
static bool HandleDeserterRemove(ChatHandler* handler, Optional<PlayerIdentifier> player, bool isInstance)
|
||||
{
|
||||
Player* player = handler->getSelectedPlayer();
|
||||
if (!player)
|
||||
{
|
||||
player = PlayerIdentifier::FromTargetOrSelf(handler);
|
||||
}
|
||||
|
||||
if (!player)
|
||||
{
|
||||
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
|
||||
@@ -149,33 +186,71 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
player->RemoveAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
Player* target = player->GetConnectedPlayer();
|
||||
|
||||
if (target)
|
||||
{
|
||||
target->RemoveAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
return true;
|
||||
}
|
||||
|
||||
CharacterDatabase.Query("DELETE FROM character_aura WHERE guid = {} AND spell = {}", player->GetGUID().GetCounter(), isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @sa HandleDeserterAdd()
|
||||
static bool HandleDeserterInstanceAdd(ChatHandler* handler, uint32 time)
|
||||
static bool HandleDeserterRemoveAll(ChatHandler* handler, bool isInstance)
|
||||
{
|
||||
return HandleDeserterAdd(handler, time, true);
|
||||
CharacterDatabase.Query("DELETE FROM character_aura WHERE spell = {} AND remainTime <= 1800000", isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
|
||||
HashMapHolder<Player>::MapType const& onlinePlayerList = ObjectAccessor::GetPlayers();
|
||||
for (HashMapHolder<Player>::MapType::const_iterator itr = onlinePlayerList.begin(); itr != onlinePlayerList.end(); ++itr)
|
||||
{
|
||||
Player* player = itr->second;
|
||||
Aura* aura = player->GetAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
if (aura && aura->GetDuration() <= 1800000)
|
||||
{
|
||||
player->RemoveAura(isInstance ? LFG_SPELL_DUNGEON_DESERTER : BG_SPELL_DESERTER);
|
||||
}
|
||||
}
|
||||
|
||||
handler->PSendSysMessage("%s Deserter has been removed from all players", isInstance ? "Instance" : "Battleground");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @sa HandleDeserterAdd()
|
||||
static bool HandleDeserterBGAdd(ChatHandler* handler, uint32 time)
|
||||
static bool HandleDeserterInstanceAdd(ChatHandler* handler, Optional<PlayerIdentifier> player, uint32 time)
|
||||
{
|
||||
return HandleDeserterAdd(handler, time, false);
|
||||
return HandleDeserterAdd(handler, player, time, true);
|
||||
}
|
||||
|
||||
/// @sa HandleDeserterAdd()
|
||||
static bool HandleDeserterBGAdd(ChatHandler* handler, Optional<PlayerIdentifier> player, uint32 time)
|
||||
{
|
||||
return HandleDeserterAdd(handler, player, time, false);
|
||||
}
|
||||
|
||||
/// @sa HandleDeserterRemove()
|
||||
static bool HandleDeserterInstanceRemove(ChatHandler* handler)
|
||||
static bool HandleDeserterInstanceRemove(ChatHandler* handler, Optional<PlayerIdentifier> player)
|
||||
{
|
||||
return HandleDeserterRemove(handler, true);
|
||||
return HandleDeserterRemove(handler, player, true);
|
||||
}
|
||||
|
||||
/// @sa HandleDeserterRemove()
|
||||
static bool HandleDeserterBGRemove(ChatHandler* handler)
|
||||
static bool HandleDeserterBGRemove(ChatHandler* handler, Optional<PlayerIdentifier> player)
|
||||
{
|
||||
return HandleDeserterRemove(handler, false);
|
||||
return HandleDeserterRemove(handler, player, false);
|
||||
}
|
||||
|
||||
static bool HandleDeserterInstanceRemoveAll(ChatHandler* handler)
|
||||
{
|
||||
return HandleDeserterRemoveAll(handler, true);
|
||||
}
|
||||
|
||||
static bool HandleDeserterBGRemoveAll(ChatHandler* handler)
|
||||
{
|
||||
return HandleDeserterRemoveAll(handler, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GameObjectAI.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "zulgurub.h"
|
||||
|
||||
enum Says
|
||||
@@ -49,7 +52,8 @@ enum Spells
|
||||
SPELL_GREATER_HEAL = 23954,
|
||||
|
||||
// Batriders Spell
|
||||
SPELL_BOMB = 40332 // Wrong ID but Magmadars bomb is not working...
|
||||
SPELL_THROW_LIQUID_FIRE = 23970,
|
||||
SPELL_SUMMON_LIQUID_FIRE = 23971
|
||||
};
|
||||
|
||||
enum BatIds
|
||||
@@ -93,214 +97,227 @@ Position const SpawnBat[6] =
|
||||
{ -12293.6220f, -1380.2640f, 144.8304f, 5.483f }
|
||||
};
|
||||
|
||||
class boss_jeklik : public CreatureScript
|
||||
struct boss_jeklik : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_jeklik() : CreatureScript("boss_jeklik") { }
|
||||
boss_jeklik(Creature* creature) : BossAI(creature, DATA_JEKLIK) { }
|
||||
|
||||
struct boss_jeklikAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_jeklikAI(Creature* creature) : BossAI(creature, DATA_JEKLIK) { }
|
||||
DoCastSelf(SPELL_GREEN_CHANNELING);
|
||||
me->SetHover(false);
|
||||
me->SetDisableGravity(false);
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
const Position homePos = me->GetHomePosition();
|
||||
me->NearTeleportTo(homePos.GetPositionX(), homePos.GetPositionY(), homePos.GetPositionZ(), homePos.GetOrientation());
|
||||
BossAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(SAY_AGGRO);
|
||||
me->RemoveAurasDueToSpell(SPELL_GREEN_CHANNELING);
|
||||
me->SetHover(true);
|
||||
me->SetDisableGravity(true);
|
||||
me->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
|
||||
DoCastSelf(SPELL_BAT_FORM);
|
||||
events.SetPhase(PHASE_ONE);
|
||||
|
||||
events.ScheduleEvent(EVENT_CHARGE_JEKLIK, urand(10000, 20000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, urand(5000, 15000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_BLOOD_LEECH, urand(5000, 15000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_SONIC_BURST, urand(5000, 15000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_SWOOP, 20000, PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_SPAWN_BATS, 30000, PHASE_ONE);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*who*/, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(50))
|
||||
{
|
||||
DoCastSelf(SPELL_GREEN_CHANNELING);
|
||||
_Reset();
|
||||
me->RemoveAurasDueToSpell(SPELL_BAT_FORM);
|
||||
me->SetHover(false);
|
||||
me->SetDisableGravity(false);
|
||||
DoResetThreat();
|
||||
events.SetPhase(PHASE_TWO);
|
||||
events.CancelEventGroup(PHASE_ONE);
|
||||
|
||||
events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(5000, 15000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(10000, 15000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, urand(25000, 35000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_MIND_FLAY, urand(10000, 30000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_GREATER_HEAL, 25000, PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_SPAWN_FLYING_BATS, 10000, PHASE_TWO);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(SAY_AGGRO);
|
||||
me->RemoveAurasDueToSpell(SPELL_GREEN_CHANNELING);
|
||||
me->SetDisableGravity(true);
|
||||
DoCastSelf(SPELL_BAT_FORM);
|
||||
events.SetPhase(PHASE_ONE);
|
||||
|
||||
events.ScheduleEvent(EVENT_CHARGE_JEKLIK, urand(10000, 20000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, urand(5000, 15000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_BLOOD_LEECH, urand(5000, 15000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_SONIC_BURST, urand(5000, 15000), PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_SWOOP, 20000, PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_SPAWN_BATS, 30000, PHASE_ONE);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(50))
|
||||
switch (eventId)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_BAT_FORM);
|
||||
me->SetDisableGravity(false);
|
||||
DoResetThreat();
|
||||
events.SetPhase(PHASE_TWO);
|
||||
|
||||
events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(5000, 15000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(10000, 15000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, urand(25000, 35000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_MIND_FLAY, urand(10000, 30000), PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_GREATER_HEAL, 25000, PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_SPAWN_FLYING_BATS, 10000, PHASE_TWO);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
// Phase one
|
||||
case EVENT_CHARGE_JEKLIK:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
AttackStart(target);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHARGE_JEKLIK, urand(15000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_PIERCE_ARMOR:
|
||||
DoCastVictim(SPELL_PIERCE_ARMOR);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, urand(20000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_BLOOD_LEECH:
|
||||
DoCastVictim(SPELL_BLOOD_LEECH);
|
||||
events.ScheduleEvent(EVENT_BLOOD_LEECH, urand(10000, 20000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_SONIC_BURST:
|
||||
DoCastVictim(SPELL_SONIC_BURST);
|
||||
events.ScheduleEvent(EVENT_SONIC_BURST, urand(20000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_SWOOP:
|
||||
DoCastVictim(SPELL_SWOOP);
|
||||
events.ScheduleEvent(EVENT_SWOOP, urand(20000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_SPAWN_BATS:
|
||||
Talk(EMOTE_SUMMON_BATS);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
for (uint8 i = 0; i < 6; ++i)
|
||||
if (Creature* bat = me->SummonCreature(NPC_BLOODSEEKER_BAT, SpawnBat[i], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000))
|
||||
bat->AI()->AttackStart(target);
|
||||
events.ScheduleEvent(EVENT_SPAWN_BATS, 30000, PHASE_ONE);
|
||||
break;
|
||||
// Phase one
|
||||
case EVENT_CHARGE_JEKLIK:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
AttackStart(target);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHARGE_JEKLIK, urand(15000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_PIERCE_ARMOR:
|
||||
DoCastVictim(SPELL_PIERCE_ARMOR);
|
||||
events.ScheduleEvent(EVENT_PIERCE_ARMOR, urand(20000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_BLOOD_LEECH:
|
||||
DoCastVictim(SPELL_BLOOD_LEECH);
|
||||
events.ScheduleEvent(EVENT_BLOOD_LEECH, urand(10000, 20000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_SONIC_BURST:
|
||||
DoCastVictim(SPELL_SONIC_BURST);
|
||||
events.ScheduleEvent(EVENT_SONIC_BURST, urand(20000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_SWOOP:
|
||||
DoCastVictim(SPELL_SWOOP);
|
||||
events.ScheduleEvent(EVENT_SWOOP, urand(20000, 30000), PHASE_ONE);
|
||||
break;
|
||||
case EVENT_SPAWN_BATS:
|
||||
Talk(EMOTE_SUMMON_BATS);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
for (uint8 i = 0; i < 6; ++i)
|
||||
if (Creature* bat = me->SummonCreature(NPC_BLOODSEEKER_BAT, SpawnBat[i], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000))
|
||||
bat->AI()->AttackStart(target);
|
||||
events.ScheduleEvent(EVENT_SPAWN_BATS, 30000, PHASE_ONE);
|
||||
break;
|
||||
//Phase two
|
||||
case EVENT_CURSE_OF_BLOOD:
|
||||
DoCastSelf(SPELL_CURSE_OF_BLOOD);
|
||||
events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(25000, 30000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_PSYCHIC_SCREAM:
|
||||
DoCastVictim(SPELL_PSYCHIC_SCREAM);
|
||||
events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, urand(35000, 45000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_SHADOW_WORD_PAIN:
|
||||
DoCastRandomTarget(SPELL_SHADOW_WORD_PAIN, 0, true);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(12000, 18000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_MIND_FLAY:
|
||||
DoCastVictim(SPELL_MIND_FLAY);
|
||||
events.ScheduleEvent(EVENT_MIND_FLAY, urand(20000, 40000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_GREATER_HEAL:
|
||||
Talk(EMOTE_GREAT_HEAL);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCastSelf(SPELL_GREATER_HEAL);
|
||||
events.ScheduleEvent(EVENT_GREATER_HEAL, 25000, PHASE_TWO);
|
||||
break;
|
||||
case EVENT_SPAWN_FLYING_BATS:
|
||||
Talk(SAY_CALL_RIDERS);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
if (Creature* flyingBat = me->SummonCreature(NPC_FRENZIED_BAT, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000))
|
||||
flyingBat->AI()->AttackStart(target);
|
||||
events.ScheduleEvent(EVENT_SPAWN_FLYING_BATS, urand(10000, 15000), PHASE_TWO);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case EVENT_CURSE_OF_BLOOD:
|
||||
DoCastSelf(SPELL_CURSE_OF_BLOOD);
|
||||
events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(25000, 30000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_PSYCHIC_SCREAM:
|
||||
DoCastVictim(SPELL_PSYCHIC_SCREAM);
|
||||
events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, urand(35000, 45000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_SHADOW_WORD_PAIN:
|
||||
DoCastRandomTarget(SPELL_SHADOW_WORD_PAIN, 0, true);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(12000, 18000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_MIND_FLAY:
|
||||
DoCastVictim(SPELL_MIND_FLAY);
|
||||
events.ScheduleEvent(EVENT_MIND_FLAY, urand(20000, 40000), PHASE_TWO);
|
||||
break;
|
||||
case EVENT_GREATER_HEAL:
|
||||
Talk(EMOTE_GREAT_HEAL);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
DoCastSelf(SPELL_GREATER_HEAL);
|
||||
events.ScheduleEvent(EVENT_GREATER_HEAL, 25000, PHASE_TWO);
|
||||
break;
|
||||
case EVENT_SPAWN_FLYING_BATS:
|
||||
Talk(SAY_CALL_RIDERS);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
if (Creature* flyingBat = me->SummonCreature(NPC_FRENZIED_BAT, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000))
|
||||
flyingBat->AI()->DoZoneInCombat();
|
||||
events.ScheduleEvent(EVENT_SPAWN_FLYING_BATS, urand(10000, 15000), PHASE_TWO);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetZulGurubAI<boss_jeklikAI>(creature);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
// Flying Bat
|
||||
class npc_batrider : public CreatureScript
|
||||
struct npc_batrider : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_batrider() : CreatureScript("npc_batrider") { }
|
||||
|
||||
struct npc_batriderAI : public ScriptedAI
|
||||
npc_batrider(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
npc_batriderAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
uint32 Bomb_Timer;
|
||||
|
||||
void Reset() override
|
||||
_scheduler.SetValidator([this]
|
||||
{
|
||||
Bomb_Timer = 2000;
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->AddUnitState(UNIT_STATE_ROOT);
|
||||
}
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Bomb_Timer <= diff)
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, 1, SelectTargetMethod::Random, 500.0f, true);
|
||||
if (!targets.empty())
|
||||
{
|
||||
if (targets.size() > 1)
|
||||
{
|
||||
targets.resize(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
|
||||
{
|
||||
me->CastSpell((*itr), SPELL_BOMB);
|
||||
}
|
||||
|
||||
Bomb_Timer = 7000;
|
||||
}
|
||||
else
|
||||
Bomb_Timer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return GetZulGurubAI<npc_batriderAI>(creature);
|
||||
_scheduler.CancelAll();
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetHover(true);
|
||||
me->SetDisableGravity(true);
|
||||
me->AddUnitState(UNIT_STATE_ROOT);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(2s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_THROW_LIQUID_FIRE);
|
||||
context.Repeat(7s);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
class spell_batrider_bomb : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_batrider_bomb);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SUMMON_LIQUID_FIRE });
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
target->CastSpell(target, SPELL_SUMMON_LIQUID_FIRE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_batrider_bomb::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_jeklik()
|
||||
{
|
||||
new boss_jeklik();
|
||||
new npc_batrider();
|
||||
RegisterCreatureAI(boss_jeklik);
|
||||
RegisterCreatureAI(npc_batrider);
|
||||
RegisterSpellScript(spell_batrider_bomb);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user