Merge branch 'master' into Playerbot
# Conflicts: # src/server/game/Guilds/Guild.cpp
This commit is contained in:
@@ -72,6 +72,7 @@ public:
|
||||
{ "customize", HandleCharacterCustomizeCommand, SEC_GAMEMASTER, Console::Yes },
|
||||
{ "changefaction", HandleCharacterChangeFactionCommand, SEC_GAMEMASTER, Console::Yes },
|
||||
{ "changerace", HandleCharacterChangeRaceCommand, SEC_GAMEMASTER, Console::Yes },
|
||||
{ "changeaccount", HandleCharacterChangeAccountCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||
{ "check", characterCheckCommandTable },
|
||||
{ "erase", HandleCharacterEraseCommand, SEC_CONSOLE, Console::Yes },
|
||||
{ "deleted", characterDeletedCommandTable },
|
||||
@@ -381,6 +382,8 @@ public:
|
||||
{
|
||||
target->SetName(newName);
|
||||
|
||||
ObjectAccessor::UpdatePlayerNameMapReference(player->GetName(), target);
|
||||
|
||||
if (WorldSession* session = target->GetSession())
|
||||
session->KickPlayer("HandleCharacterRenameCommand GM Command renaming character");
|
||||
}
|
||||
@@ -1059,6 +1062,55 @@ public:
|
||||
handler->PSendSysMessage("--------------------------------------");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleCharacterChangeAccountCommand(ChatHandler* handler, std::string accountName, Optional<PlayerIdentifier> player)
|
||||
{
|
||||
if (!player)
|
||||
{
|
||||
player = PlayerIdentifier::FromTargetOrSelf(handler);
|
||||
}
|
||||
|
||||
if (!player)
|
||||
{
|
||||
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uint32 accountId = AccountMgr::GetId(accountName))
|
||||
{
|
||||
if (AccountMgr::GetCharactersCount(accountId) >= 10)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, accountName, accountId);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CharacterCacheEntry const* cache = sCharacterCache->GetCharacterCacheByName(player->GetName()))
|
||||
{
|
||||
std::string accName;
|
||||
AccountMgr::GetName(cache->AccountId, accName);
|
||||
handler->PSendSysMessage(LANG_CMD_CHAR_CHANGE_ACC_SUCCESS, player->GetName(), player->GetGUID().GetCounter(), accName, cache->AccountId, accountName, accountId);
|
||||
}
|
||||
|
||||
if (player->IsConnected())
|
||||
{
|
||||
player->GetConnectedPlayer()->GetSession()->KickPlayer("CMD char changeaccount");
|
||||
}
|
||||
|
||||
CharacterDatabase.Query("UPDATE characters SET account = {} WHERE guid = {}", accountId, player->GetGUID().GetCounter());
|
||||
sCharacterCache->UpdateCharacterAccountId(player->GetGUID(), accountId);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_character_commandscript()
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
{
|
||||
static ChatCommandTable groupCommandTable =
|
||||
{
|
||||
{ "list", HandleGroupListCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "list", HandleGroupListCommand, SEC_GAMEMASTER, Console::Yes },
|
||||
{ "join", HandleGroupJoinCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "remove", HandleGroupRemoveCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "disband", HandleGroupDisbandCommand, SEC_GAMEMASTER, Console::No },
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party"));
|
||||
handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "Raid" : "Party"), groupTarget->GetMembersCount());
|
||||
|
||||
for (auto const& slot : groupTarget->GetMemberSlots())
|
||||
{
|
||||
|
||||
@@ -195,9 +195,12 @@ public:
|
||||
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo))
|
||||
continue;
|
||||
|
||||
player->LearnTalent(talentInfo->TalentID, rankId);
|
||||
player->LearnTalent(talentInfo->TalentID, rankId, true);
|
||||
}
|
||||
|
||||
player->SetFreeTalentPoints(0);
|
||||
player->SendTalentsInfoData(false);
|
||||
|
||||
handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1399,7 +1399,7 @@ public:
|
||||
|
||||
if (location->empty() || *location == "inn")
|
||||
{
|
||||
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
|
||||
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->m_homebindO);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
return commandTable;
|
||||
}
|
||||
|
||||
static bool HandleMmapPathCommand(ChatHandler* handler, Optional<std::string> para)
|
||||
static bool HandleMmapPathCommand(ChatHandler* handler, Optional<std::string> param)
|
||||
{
|
||||
if (!MMAP::MMapFactory::createOrGetMMapMgr()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()))
|
||||
{
|
||||
@@ -81,13 +81,19 @@ public:
|
||||
}
|
||||
|
||||
bool useStraightPath = false;
|
||||
if (StringStartsWith("true", *para))
|
||||
useStraightPath = true;
|
||||
|
||||
bool useRaycast = false;
|
||||
if (StringStartsWith("line", *para) || StringStartsWith("ray", *para) || StringStartsWith("raycast", *para))
|
||||
if (param)
|
||||
{
|
||||
useRaycast = true;
|
||||
auto paramValue = param.value();
|
||||
if (paramValue.starts_with("true"))
|
||||
{
|
||||
useStraightPath = true;
|
||||
}
|
||||
|
||||
if (paramValue.starts_with("line") || paramValue.starts_with("ray") || paramValue.starts_with("raycast"))
|
||||
{
|
||||
useRaycast = true;
|
||||
}
|
||||
}
|
||||
|
||||
// unit locations
|
||||
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
else if (targetGuid)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
|
||||
stmt->SetData(0, uint16(AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS));
|
||||
stmt->SetData(0, uint16(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS));
|
||||
stmt->SetData(1, targetGuid.GetCounter());
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
if (where.index() == 1) // References target's homebind
|
||||
{
|
||||
if (Player* target = player->GetConnectedPlayer())
|
||||
target->TeleportTo(target->m_homebindMapId, target->m_homebindX, target->m_homebindY, target->m_homebindZ, target->GetOrientation());
|
||||
target->TeleportTo(target->m_homebindMapId, target->m_homebindX, target->m_homebindY, target->m_homebindZ, target->m_homebindO);
|
||||
else
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_HOMEBIND);
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ public:
|
||||
case EVENT_KNOCKBACK:
|
||||
DoCastVictim(SPELL_KNOCKBACK);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -50);
|
||||
DoModifyThreatByPercent(me->GetVictim(), -50);
|
||||
events.ScheduleEvent(EVENT_KNOCKBACK, 15000, 30000);
|
||||
break;
|
||||
case EVENT_CHECK:
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -75);
|
||||
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
|
||||
break;
|
||||
case EVENT_FLAMEBUFFET:
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public:
|
||||
case EVENT_WINGBUFFET:
|
||||
DoCastVictim(SPELL_WINGBUFFET);
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
DoModifyThreatPercent(me->GetVictim(), -75);
|
||||
DoModifyThreatByPercent(me->GetVictim(), -75);
|
||||
events.ScheduleEvent(EVENT_WINGBUFFET, 30000);
|
||||
break;
|
||||
case EVENT_FRENZY:
|
||||
|
||||
@@ -411,7 +411,7 @@ public:
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->AttackStop();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
|
||||
DoCastSelf(SPELL_RAGNA_SUBMERGE_VISUAL, true);
|
||||
|
||||
+5
-1
@@ -250,7 +250,11 @@ public:
|
||||
|
||||
if (bossId == DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
DoRespawnGameObject(_cacheOfTheFirelordGUID, 7 * DAY);
|
||||
if (GameObject* cache = instance->GetGameObject(_cacheOfTheFirelordGUID))
|
||||
{
|
||||
cache->SetRespawnTime(7 * DAY);
|
||||
cache->SetLootRecipient(instance);
|
||||
}
|
||||
}
|
||||
else if (bossId == DATA_GOLEMAGG)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
@@ -34,6 +35,13 @@ enum Spells
|
||||
SPELL_FULL_HEALTH = 17683,
|
||||
SPELL_FIRE_NOVA_VISUAL = 19823,
|
||||
SPELL_PLAY_DEAD_PACIFY = 19951, // Server side spell
|
||||
|
||||
// Lava Spawn
|
||||
SPELL_FIREBALL = 19391,
|
||||
SPELL_SPLIT_1 = 19569,
|
||||
SPELL_SPLIT_2 = 19570,
|
||||
|
||||
TALK_0 = 0
|
||||
};
|
||||
|
||||
// Serrated Bites timer may be wrong
|
||||
@@ -207,10 +215,60 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_lava_spawn : public ScriptedAI
|
||||
{
|
||||
npc_lava_spawn(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
std::list<Creature*> lavaSpawns;
|
||||
me->GetCreatureListWithEntryInGrid(lavaSpawns, me->GetEntry(), 100.f);
|
||||
if (lavaSpawns.size() < 16)
|
||||
{
|
||||
Talk(TALK_0);
|
||||
|
||||
DoCastSelf(SPELL_SPLIT_1, true);
|
||||
DoCastSelf(SPELL_SPLIT_2, true);
|
||||
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat(15s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoSpellAttackIfReady(SPELL_FIREBALL);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
void AddSC_molten_core()
|
||||
{
|
||||
// Creatures
|
||||
new npc_mc_core_hound();
|
||||
RegisterCreatureAI(npc_lava_spawn);
|
||||
|
||||
// Spells
|
||||
new spell_mc_play_dead();
|
||||
|
||||
@@ -496,7 +496,7 @@ public:
|
||||
{
|
||||
if (me->GetVictim())
|
||||
{
|
||||
DoModifyThreatPercent(me->GetVictim(), -100);
|
||||
DoModifyThreatByPercent(me->GetVictim(), -100);
|
||||
}
|
||||
|
||||
me->AddThreat(target, 1000000.0f);
|
||||
|
||||
@@ -915,7 +915,7 @@ public:
|
||||
DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true);
|
||||
TempThreat = DoGetThreat(target);
|
||||
if (TempThreat)
|
||||
DoModifyThreatPercent(target, -100);
|
||||
DoModifyThreatByPercent(target, -100);
|
||||
HoodGUID = target->GetGUID();
|
||||
me->AddThreat(target, 1000000.0f);
|
||||
ChaseTimer = 20000;
|
||||
@@ -930,7 +930,7 @@ public:
|
||||
{
|
||||
HoodGUID.Clear();
|
||||
if (DoGetThreat(target))
|
||||
DoModifyThreatPercent(target, -100);
|
||||
DoModifyThreatByPercent(target, -100);
|
||||
me->AddThreat(target, TempThreat);
|
||||
TempThreat = 0;
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ public:
|
||||
{
|
||||
case EVENT_SPELL_VANISH:
|
||||
me->CastSpell(me, SPELL_VANISH, false);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Unit* unit = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->AddThreat(unit, 1000.0f);
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ public:
|
||||
case 3:
|
||||
case 4:
|
||||
me->NearTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, me->GetOrientation());
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
|
||||
me->RemoveAurasDueToSpell(Transform[Phase].unaura);
|
||||
DoCast(me, Transform[Phase].spell);
|
||||
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP));
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP));
|
||||
me->AttackStop();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoCastSelf(SPELL_VANISH_VISUAL);
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
}
|
||||
DoCast(me, SPELL_AVATAR);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
events.ScheduleEvent(EVENT_START_PURSUIT, 2s);
|
||||
events.ScheduleEvent(EVENT_STOP_PURSUIT, 15s);
|
||||
events.ScheduleEvent(EVENT_AVATAR, 45s, 50s);
|
||||
|
||||
@@ -164,7 +164,7 @@ struct boss_jeklik : public BossAI
|
||||
if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(50))
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_BAT_FORM);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
events.SetPhase(PHASE_TWO);
|
||||
events.CancelEventGroup(PHASE_ONE);
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ public:
|
||||
{
|
||||
if (!target->IsWithinMeleeRange(me))
|
||||
{
|
||||
_thousandBladesTargets.push_back(target);
|
||||
_thousandBladesTargets.push_back(target->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ public:
|
||||
{
|
||||
if (target->IsWithinMeleeRange(me))
|
||||
{
|
||||
_thousandBladesTargets.push_back(target);
|
||||
_thousandBladesTargets.push_back(target->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,12 +204,12 @@ public:
|
||||
|
||||
if (!_thousandBladesTargets.empty())
|
||||
{
|
||||
std::vector<Unit*>::iterator itr = _thousandBladesTargets.begin();
|
||||
GuidVector::iterator itr = _thousandBladesTargets.begin();
|
||||
std::advance(itr, urand(0, _thousandBladesTargets.size() - 1));
|
||||
|
||||
if (Unit* target = *itr)
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, *itr))
|
||||
{
|
||||
DoCast(target, SPELL_THOUSAND_BLADES, false);
|
||||
DoCast(target, SPELL_THOUSAND_BLADES);
|
||||
}
|
||||
|
||||
if (_thousandBladesTargets.erase(itr) != _thousandBladesTargets.end())
|
||||
@@ -242,7 +242,7 @@ public:
|
||||
bool _enraged;
|
||||
uint32 _dynamicFlags;
|
||||
uint8 _thousandBladesCount;
|
||||
std::vector<Unit*> _thousandBladesTargets;
|
||||
GuidVector _thousandBladesTargets;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetStandState(UNIT_STAND_STATE_SLEEP);
|
||||
me->AttackStop();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
WasDead = true;
|
||||
CheckPhaseTransition();
|
||||
Talk(EMOTE_THEKAL_DIES);
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
DoCast(target, SPELL_CHARGE);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
AttackStart(target);
|
||||
}
|
||||
context.Repeat(15s, 22s);
|
||||
@@ -407,7 +407,7 @@ public:
|
||||
|
||||
if (DoGetThreat(me->GetVictim()))
|
||||
{
|
||||
DoModifyThreatPercent(me->GetVictim(), -100);
|
||||
DoModifyThreatByPercent(me->GetVictim(), -100);
|
||||
}
|
||||
|
||||
context.Repeat(17s, 27s);
|
||||
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
// shapeshift at 50% health
|
||||
DoCast(me, SPELL_VENOXIS_TRANSFORM);
|
||||
Talk(SAY_VENOXIS_TRANSFORM);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
|
||||
// phase two events (snakeform)
|
||||
events.ScheduleEvent(EVENT_VENOM_SPIT, 5000, 0, PHASE_TWO);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GridNotifiers.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_AXE_FLURRY_STUN = 24020
|
||||
};
|
||||
|
||||
class spell_axe_flurry : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_axe_flurry);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if(Acore::UnitAuraCheck(true, SPELL_AXE_FLURRY_STUN));
|
||||
Acore::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
|
||||
void HandleEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
caster->CastSpell(target, SPELL_AXE_FLURRY_STUN, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_axe_flurry::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_axe_flurry::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_zulgurub()
|
||||
{
|
||||
RegisterSpellScript(spell_axe_flurry);
|
||||
}
|
||||
@@ -141,6 +141,7 @@ void AddSC_boss_hazzarah();
|
||||
void AddSC_boss_renataki();
|
||||
void AddSC_boss_wushoolay();
|
||||
void AddSC_instance_zulgurub();
|
||||
void AddSC_zulgurub();
|
||||
// void AddSC_alterac_mountains();
|
||||
void AddSC_arathi_highlands();
|
||||
void AddSC_blasted_lands();
|
||||
@@ -292,6 +293,7 @@ void AddEasternKingdomsScripts()
|
||||
AddSC_boss_renataki();
|
||||
AddSC_boss_wushoolay();
|
||||
AddSC_instance_zulgurub();
|
||||
AddSC_zulgurub();
|
||||
//AddSC_alterac_mountains();
|
||||
AddSC_arathi_highlands();
|
||||
AddSC_blasted_lands();
|
||||
|
||||
@@ -233,8 +233,6 @@ enum costumedOrphan
|
||||
|
||||
// Actions
|
||||
ACTION_START_EVENT = 1,
|
||||
DATA_EVENT = 1,
|
||||
DATA_ALLOW_START = 2,
|
||||
|
||||
// Talks
|
||||
TALK_SHADE_CONFLAGRATION = 0,
|
||||
@@ -323,7 +321,7 @@ class spell_hallows_end_base_fire : public AuraScript
|
||||
|
||||
struct npc_costumed_orphan_matron : public ScriptedAI
|
||||
{
|
||||
npc_costumed_orphan_matron(Creature* c) : ScriptedAI(c) { }
|
||||
npc_costumed_orphan_matron(Creature* c) : ScriptedAI(c) {}
|
||||
|
||||
uint32 eventStarted;
|
||||
bool allowQuest;
|
||||
@@ -340,48 +338,48 @@ struct npc_costumed_orphan_matron : public ScriptedAI
|
||||
{
|
||||
switch (me->GetAreaId())
|
||||
{
|
||||
case 87: // Goldshire
|
||||
x = -9494.4f;
|
||||
y = 48.53f;
|
||||
z = 70.5f;
|
||||
o = 0.5f;
|
||||
path = 235431;
|
||||
break;
|
||||
case 131: // Kharanos
|
||||
x = -5558.34f;
|
||||
y = -499.46f;
|
||||
z = 414.12f;
|
||||
o = 2.08f;
|
||||
path = 235432;
|
||||
break;
|
||||
case 3576: // Azure Watch
|
||||
x = -4163.58f;
|
||||
y = -12460.30f;
|
||||
z = 63.02f;
|
||||
o = 4.31f;
|
||||
path = 235433;
|
||||
break;
|
||||
case 362: // Razor Hill
|
||||
x = 373.2f;
|
||||
y = -4723.4f;
|
||||
z = 31.2f;
|
||||
o = 3.2f;
|
||||
path = 235434;
|
||||
break;
|
||||
case 159: // Brill
|
||||
x = 2195.2f;
|
||||
y = 264.0f;
|
||||
z = 55.62f;
|
||||
o = 0.15f;
|
||||
path = 235435;
|
||||
break;
|
||||
case 3665: // Falcon Wing Square
|
||||
x = 9547.91f;
|
||||
y = -6809.9f;
|
||||
z = 27.96f;
|
||||
o = 3.4f;
|
||||
path = 235436;
|
||||
break;
|
||||
case 87: // Goldshire
|
||||
x = -9494.4f;
|
||||
y = 48.53f;
|
||||
z = 70.5f;
|
||||
o = 0.5f;
|
||||
path = 235431;
|
||||
break;
|
||||
case 131: // Kharanos
|
||||
x = -5558.34f;
|
||||
y = -499.46f;
|
||||
z = 414.12f;
|
||||
o = 2.08f;
|
||||
path = 235432;
|
||||
break;
|
||||
case 3576: // Azure Watch
|
||||
x = -4163.58f;
|
||||
y = -12460.30f;
|
||||
z = 63.02f;
|
||||
o = 4.31f;
|
||||
path = 235433;
|
||||
break;
|
||||
case 362: // Razor Hill
|
||||
x = 373.2f;
|
||||
y = -4723.4f;
|
||||
z = 31.2f;
|
||||
o = 3.2f;
|
||||
path = 235434;
|
||||
break;
|
||||
case 159: // Brill
|
||||
x = 2195.2f;
|
||||
y = 264.0f;
|
||||
z = 55.62f;
|
||||
o = 0.15f;
|
||||
path = 235435;
|
||||
break;
|
||||
case 3665: // Falcon Wing Square
|
||||
x = 9547.91f;
|
||||
y = -6809.9f;
|
||||
z = 27.96f;
|
||||
o = 3.4f;
|
||||
path = 235436;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,14 +401,6 @@ struct npc_costumed_orphan_matron : public ScriptedAI
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 param) const override
|
||||
{
|
||||
if (param == DATA_ALLOW_START)
|
||||
return allowQuest;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (eventStarted)
|
||||
@@ -423,67 +413,78 @@ struct npc_costumed_orphan_matron : public ScriptedAI
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature)
|
||||
{
|
||||
QuestRelationBounds pObjectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry());
|
||||
QuestRelationBounds pObjectQIR = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(creature->GetEntry());
|
||||
|
||||
QuestMenu& qm = player->PlayerTalkClass->GetQuestMenu();
|
||||
qm.ClearMenu();
|
||||
|
||||
for (QuestRelations::const_iterator i = pObjectQIR.first; i != pObjectQIR.second; ++i)
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
uint32 quest_id = i->second;
|
||||
QuestStatus status = player->GetQuestStatus(quest_id);
|
||||
if (status == QUEST_STATUS_COMPLETE)
|
||||
qm.AddMenuItem(quest_id, 4);
|
||||
else if (status == QUEST_STATUS_INCOMPLETE)
|
||||
qm.AddMenuItem(quest_id, 4);
|
||||
}
|
||||
QuestRelationBounds pObjectQR = sObjectMgr->GetCreatureQuestRelationBounds(me->GetEntry());
|
||||
QuestRelationBounds pObjectQIR = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(me->GetEntry());
|
||||
|
||||
for (QuestRelations::const_iterator i = pObjectQR.first; i != pObjectQR.second; ++i)
|
||||
{
|
||||
uint32 quest_id = i->second;
|
||||
Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id);
|
||||
if (!pQuest)
|
||||
continue;
|
||||
QuestMenu& qm = player->PlayerTalkClass->GetQuestMenu();
|
||||
qm.ClearMenu();
|
||||
|
||||
if (!player->CanTakeQuest(pQuest, false))
|
||||
continue;
|
||||
else if (player->GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
|
||||
for (QuestRelations::const_iterator i = pObjectQIR.first; i != pObjectQIR.second; ++i)
|
||||
{
|
||||
switch (quest_id)
|
||||
uint32 quest_id = i->second;
|
||||
QuestStatus status = player->GetQuestStatus(quest_id);
|
||||
if (status == QUEST_STATUS_COMPLETE)
|
||||
{
|
||||
case QUEST_LET_THE_FIRES_COME_A:
|
||||
case QUEST_LET_THE_FIRES_COME_H:
|
||||
if (!creature->AI()->GetData(DATA_ALLOW_START))
|
||||
qm.AddMenuItem(quest_id, 2);
|
||||
break;
|
||||
case QUEST_STOP_THE_FIRES_A:
|
||||
case QUEST_STOP_THE_FIRES_H:
|
||||
if (creature->AI()->GetData(DATA_ALLOW_START))
|
||||
qm.AddMenuItem(quest_id, 2);
|
||||
break;
|
||||
default:
|
||||
qm.AddMenuItem(quest_id, 2);
|
||||
break;
|
||||
qm.AddMenuItem(quest_id, 4);
|
||||
}
|
||||
else if (status == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
qm.AddMenuItem(quest_id, 4);
|
||||
}
|
||||
}
|
||||
|
||||
for (QuestRelations::const_iterator i = pObjectQR.first; i != pObjectQR.second; ++i)
|
||||
{
|
||||
uint32 quest_id = i->second;
|
||||
Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id);
|
||||
if (!pQuest)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!player->CanTakeQuest(pQuest, false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (player->GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
|
||||
{
|
||||
switch (quest_id)
|
||||
{
|
||||
case QUEST_LET_THE_FIRES_COME_A:
|
||||
case QUEST_LET_THE_FIRES_COME_H:
|
||||
if (!allowQuest)
|
||||
{
|
||||
qm.AddMenuItem(quest_id, 2);
|
||||
}
|
||||
break;
|
||||
case QUEST_STOP_THE_FIRES_A:
|
||||
case QUEST_STOP_THE_FIRES_H:
|
||||
if (allowQuest)
|
||||
{
|
||||
qm.AddMenuItem(quest_id, 2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qm.AddMenuItem(quest_id, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player->SendPreparedQuest(me->GetGUID());
|
||||
}
|
||||
|
||||
player->SendPreparedQuest(creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnQuestAccept(Player* /*player*/, Creature* creature, Quest const* quest)
|
||||
{
|
||||
if ((quest->GetQuestId() == QUEST_LET_THE_FIRES_COME_A || quest->GetQuestId() == QUEST_LET_THE_FIRES_COME_H) && !creature->AI()->GetData(DATA_ALLOW_START))
|
||||
creature->AI()->DoAction(ACTION_START_EVENT);
|
||||
|
||||
return true;
|
||||
}
|
||||
void sQuestAccept(Player* /*player*/, Quest const* quest) override
|
||||
{
|
||||
if ((quest->GetQuestId() == QUEST_LET_THE_FIRES_COME_A || quest->GetQuestId() == QUEST_LET_THE_FIRES_COME_H) && !allowQuest)
|
||||
{
|
||||
DoAction(ACTION_START_EVENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_soh_fire_trigger : public NullCreatureAI
|
||||
{
|
||||
|
||||
@@ -354,7 +354,7 @@ public:
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->StopMoving();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->GetMotionMaster()->MovePoint(10, OnyxiaMoveData[0].x, OnyxiaMoveData[0].y, OnyxiaMoveData[0].z);
|
||||
break;
|
||||
}
|
||||
@@ -404,7 +404,7 @@ public:
|
||||
Talk(SAY_PHASE_3_TRANS);
|
||||
me->SendMeleeAttackStop(me->GetVictim());
|
||||
me->GetMotionMaster()->MoveLand(13, OnyxiaMoveData[0].x + 1.0f, OnyxiaMoveData[0].y, OnyxiaMoveData[0].z, 12.0f);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
break;
|
||||
}
|
||||
case EVENT_SPELL_FIREBALL_FIRST:
|
||||
|
||||
@@ -221,7 +221,7 @@ struct boss_ayamiss : public BossAI
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
_scheduler.CancelGroup(PHASE_AIR);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ struct boss_buru : public BossAI
|
||||
events.ScheduleEvent(EVENT_GATHERING_SPEED, 2s);
|
||||
if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.f, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
AttackStart(victim);
|
||||
me->AddThreat(victim, 1000000.f);
|
||||
Talk(EMOTE_TARGET, victim);
|
||||
@@ -143,7 +143,7 @@ struct boss_buru : public BossAI
|
||||
events.Reset();
|
||||
_phase = PHASE_TRANSFORM;
|
||||
instance->SetData(DATA_BURU_PHASE, _phase);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2s);
|
||||
DoCastSelf(SPELL_BURU_TRANSFORM);
|
||||
}
|
||||
|
||||
@@ -79,15 +79,29 @@ public:
|
||||
|
||||
void EnterCombatWithTrio(Unit* who)
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
|
||||
if (Creature* vem = instance->GetCreature(DATA_VEM))
|
||||
{
|
||||
if (vem->GetGUID() != me->GetGUID())
|
||||
{
|
||||
vem->GetAI()->AttackStart(who);
|
||||
}
|
||||
}
|
||||
if (Creature* kri = instance->GetCreature(DATA_KRI))
|
||||
{
|
||||
if (kri->GetGUID() != me->GetGUID())
|
||||
{
|
||||
kri->GetAI()->AttackStart(who);
|
||||
}
|
||||
}
|
||||
if (Creature* yauj = instance->GetCreature(DATA_YAUJ))
|
||||
{
|
||||
if (yauj->GetGUID() != me->GetGUID())
|
||||
{
|
||||
yauj->GetAI()->AttackStart(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EvadeAllBosses(EvadeReason why)
|
||||
@@ -152,7 +166,7 @@ public:
|
||||
me->SetSpeed(MOVE_RUN, 15.f/7.f); // From sniffs
|
||||
DoCastSelf(SPELL_FULL_HEAL, true);
|
||||
if (me->GetThreatMgr().GetThreatListSize())
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Creature* dying = instance->GetCreature(_creatureDying))
|
||||
{
|
||||
dying->AI()->DoAction(ACTION_EXPLODE);
|
||||
@@ -405,7 +419,7 @@ struct boss_yauj : public boss_bug_trio
|
||||
.Schedule(12s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_FEAR);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
context.Repeat(20600ms);
|
||||
})
|
||||
.Schedule(11s, 14500ms, [this](TaskContext context)
|
||||
|
||||
@@ -25,6 +25,7 @@ EndScriptData */
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
|
||||
@@ -101,6 +102,7 @@ enum Misc
|
||||
{
|
||||
MAX_TENTACLE_GROUPS = 5,
|
||||
NPC_TRIGGER = 15384,
|
||||
NPC_EXIT_TRIGGER = 15800
|
||||
};
|
||||
|
||||
enum Yells
|
||||
@@ -149,6 +151,7 @@ struct boss_eye_of_cthun : public BossAI
|
||||
boss_eye_of_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->m_SightDistance = 90.f;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
@@ -187,7 +190,7 @@ struct boss_eye_of_cthun : public BossAI
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
ScheduleTasks();
|
||||
ScheduleTasks(true);
|
||||
BossAI::EnterCombat(who);
|
||||
_beamTarget = who->GetGUID();
|
||||
}
|
||||
@@ -197,7 +200,7 @@ struct boss_eye_of_cthun : public BossAI
|
||||
if (who->GetTypeId() == TYPEID_PLAYER && !me->IsInCombat())
|
||||
{
|
||||
// Z checks are necessary here because AQ maps do funky stuff.
|
||||
if (me->IsWithinLOSInMap(who) && me->IsWithinDist2d(who, 50.0f) && who->GetPositionZ() > 100.0f)
|
||||
if (me->IsWithinLOSInMap(who) && me->IsWithinDist2d(who, 90.0f) && who->GetPositionZ() > 100.0f)
|
||||
{
|
||||
AttackStart(who);
|
||||
}
|
||||
@@ -218,12 +221,22 @@ struct boss_eye_of_cthun : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleTasks()
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
cthun->AI()->JustSummoned(summon);
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleTasks(bool onEngage = false)
|
||||
{
|
||||
_scheduler.
|
||||
Schedule(3s, [this](TaskContext task)
|
||||
Schedule(3s, [this, onEngage](TaskContext task)
|
||||
{
|
||||
if (task.GetRepeatCounter() < 3)
|
||||
if (task.GetRepeatCounter() < 3 && onEngage)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, _beamTarget))
|
||||
{
|
||||
@@ -249,7 +262,7 @@ struct boss_eye_of_cthun : public BossAI
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
{
|
||||
if (Creature* tentacle = me->SummonCreature(NPC_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 1000))
|
||||
if (Creature* tentacle = me->SummonCreature(NPC_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000))
|
||||
{
|
||||
tentacle->AI()->AttackStart(target);
|
||||
}
|
||||
@@ -273,6 +286,9 @@ struct boss_eye_of_cthun : public BossAI
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetTarget(ObjectGuid::Empty);
|
||||
|
||||
//Freeze animation
|
||||
DoCast(me, SPELL_FREEZE_ANIM, true);
|
||||
|
||||
_scheduler.Schedule(1s, [this](TaskContext /*task*/)
|
||||
{
|
||||
//Select random target for dark beam to start on
|
||||
@@ -283,14 +299,9 @@ struct boss_eye_of_cthun : public BossAI
|
||||
DarkGlareTick = 0;
|
||||
ClockWise = RAND(true, false);
|
||||
|
||||
me->SetTarget(target->GetGUID());
|
||||
|
||||
//Add red coloration to C'thun
|
||||
DoCast(me, SPELL_RED_COLORATION, true);
|
||||
|
||||
//Freeze animation
|
||||
DoCast(me, SPELL_FREEZE_ANIM, true);
|
||||
|
||||
me->StopMoving();
|
||||
me->SetFacingToObject(target);
|
||||
me->SetOrientation(DarkGlareAngle);
|
||||
@@ -301,19 +312,12 @@ struct boss_eye_of_cthun : public BossAI
|
||||
me->SetTarget(ObjectGuid::Empty);
|
||||
me->StopMoving();
|
||||
|
||||
if (ClockWise)
|
||||
{
|
||||
me->SetFacingTo(DarkGlareAngle + DarkGlareTick * float(M_PI) / 35);
|
||||
me->SetOrientation(DarkGlareAngle + DarkGlareTick * float(M_PI) / 35);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetFacingTo(DarkGlareAngle - DarkGlareTick * float(M_PI) / 35);
|
||||
me->SetOrientation(DarkGlareAngle - DarkGlareTick * float(M_PI) / 35);
|
||||
}
|
||||
float angle = ClockWise ? DarkGlareAngle + DarkGlareTick * float(M_PI) / 35 : DarkGlareAngle - DarkGlareTick * float(M_PI) / 35;
|
||||
me->SetFacingTo(angle);
|
||||
me->SetOrientation(angle);
|
||||
|
||||
DoCastSelf(SPELL_DARK_GLARE);
|
||||
|
||||
++DarkGlareTick;
|
||||
|
||||
if (tasker.GetRepeatCounter() >= 35)
|
||||
@@ -344,7 +348,7 @@ struct boss_eye_of_cthun : public BossAI
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
//Only if it will kill
|
||||
if (damage < me->GetHealth())
|
||||
if (damage < me->GetHealth() || !me->GetHealth())
|
||||
return;
|
||||
|
||||
//Fake death in phase 0 or 1 (green beam or dark glare phase)
|
||||
@@ -366,10 +370,13 @@ struct boss_eye_of_cthun : public BossAI
|
||||
me->RemoveAllAuras();
|
||||
_scheduler.CancelAll();
|
||||
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
cthun->AI()->DoAction(ACTION_START_PHASE_TWO);
|
||||
}
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
cthun->AI()->DoAction(ACTION_START_PHASE_TWO);
|
||||
}
|
||||
}, 3s);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -445,10 +452,9 @@ struct boss_cthun : public BossAI
|
||||
|
||||
target->m_Events.AddEventAtOffset([target, this]()
|
||||
{
|
||||
DoCast(target, SPELL_DIGESTIVE_ACID, true);
|
||||
DoTeleportPlayer(target, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O);
|
||||
target->RemoveAurasDueToSpell(SPELL_MIND_FLAY);
|
||||
//Cast digestive acid on them
|
||||
DoCast(target, SPELL_DIGESTIVE_ACID, true);
|
||||
}, 3800ms);
|
||||
}
|
||||
|
||||
@@ -466,7 +472,7 @@ struct boss_cthun : public BossAI
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, -SPELL_DIGESTIVE_ACID))
|
||||
{
|
||||
//Spawn claw tentacle on the random target
|
||||
if (Creature* spawned = me->SummonCreature(NPC_GIANT_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500))
|
||||
if (Creature* spawned = me->SummonCreature(NPC_GIANT_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000))
|
||||
{
|
||||
spawned->AI()->AttackStart(target);
|
||||
}
|
||||
@@ -478,7 +484,7 @@ struct boss_cthun : public BossAI
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, -SPELL_DIGESTIVE_ACID))
|
||||
{
|
||||
//Spawn claw tentacle on the random target
|
||||
if (Creature* spawned = me->SummonCreature(NPC_GIANT_EYE_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500))
|
||||
if (Creature* spawned = me->SummonCreature(NPC_GIANT_EYE_TENTACLE, *target, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000))
|
||||
{
|
||||
spawned->AI()->AttackStart(target);
|
||||
}
|
||||
@@ -534,6 +540,13 @@ struct boss_cthun : public BossAI
|
||||
{
|
||||
pPortal->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
if (Creature* eye = instance->GetCreature(DATA_EYE_OF_CTHUN))
|
||||
{
|
||||
eye->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* creature, Unit* /*killer*/) override
|
||||
@@ -560,11 +573,11 @@ struct boss_cthun : public BossAI
|
||||
ScheduleTasks();
|
||||
//Remove purple coloration
|
||||
me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION);
|
||||
|
||||
DoCastSelf(SPELL_CARAPACE_CTHUN, true);
|
||||
//Spawn flesh tentacle
|
||||
for (uint8 i = 0; i < 2; i++)
|
||||
{
|
||||
me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -589,11 +602,14 @@ struct npc_eye_tentacle : public ScriptedAI
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
if (me->ToTempSummon())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -660,11 +676,14 @@ struct npc_claw_tentacle : public ScriptedAI
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
if (me->ToTempSummon())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -727,14 +746,19 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
if (me->ToTempSummon())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_canAttack = false;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -756,21 +780,10 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
|
||||
_scheduler.Schedule(2s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_HAMSTRING);
|
||||
context.Repeat(10s);
|
||||
}).Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
context.Repeat(10s);
|
||||
});
|
||||
|
||||
ScheduleMeleeCheck();
|
||||
ScheduleTasks();
|
||||
}
|
||||
|
||||
void ScheduleMeleeCheck()
|
||||
void ScheduleTasks()
|
||||
{
|
||||
// Check if a target is in melee range
|
||||
_scheduler.Schedule(10s, [this](TaskContext task)
|
||||
@@ -792,6 +805,17 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
}
|
||||
|
||||
task.Repeat();
|
||||
}).Schedule(2s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_HAMSTRING);
|
||||
context.Repeat(10s);
|
||||
}).Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
context.Repeat(10s);
|
||||
}).Schedule(3s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_canAttack = true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -813,6 +837,7 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
_scheduler.CancelAll();
|
||||
_canAttack = false;
|
||||
|
||||
_scheduler.Schedule(5s, [this](TaskContext /*task*/)
|
||||
{
|
||||
@@ -837,7 +862,7 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
DoCastAOE(SPELL_MASSIVE_GROUND_RUPTURE, true);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
ScheduleMeleeCheck();
|
||||
ScheduleTasks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,12 +874,16 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
if (_canAttack)
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
ObjectGuid _portalGUID;
|
||||
bool _canAttack;
|
||||
};
|
||||
|
||||
struct npc_giant_eye_tentacle : public ScriptedAI
|
||||
@@ -868,11 +897,14 @@ struct npc_giant_eye_tentacle : public ScriptedAI
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
if (me->ToTempSummon())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -921,6 +953,43 @@ private:
|
||||
ObjectGuid _portalGUID;
|
||||
};
|
||||
|
||||
class spell_cthun_dark_glare : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_cthun_dark_glare);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
targets.remove_if([caster](WorldObject const* target) { return !caster->HasInLine(target, 5.0f); });
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_cthun_dark_glare::FilterTargets, EFFECT_ALL, TARGET_UNIT_CONE_ENEMY_24);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_cthun_digestive_acid : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_cthun_digestive_acid);
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (InstanceScript* instance = GetUnitOwner()->GetInstanceScript())
|
||||
{
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
cthun->CastSpell(GetUnitOwner(), SPELL_DIGESTIVE_ACID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_cthun_digestive_acid::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// 4033 - At C'thun's stomach
|
||||
class at_cthun_stomach_exit : public AreaTriggerScript
|
||||
{
|
||||
@@ -933,30 +1002,37 @@ public:
|
||||
{
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
player->CastSpell(player, SPELL_RUBBLE_ROCKY, true);
|
||||
|
||||
player->m_Events.AddEventAtOffset([player]()
|
||||
if (Creature* trigger = player->FindNearestCreature(NPC_TRIGGER, 15.0f))
|
||||
{
|
||||
if (Creature* trigger = player->FindNearestCreature(NPC_TRIGGER, 15.0f))
|
||||
trigger->CastSpell(player, SPELL_EXIT_STOMACH, true);
|
||||
|
||||
if (Creature* exittrigger = player->FindNearestCreature(NPC_EXIT_TRIGGER, 15.0f))
|
||||
{
|
||||
trigger->CastSpell(player, SPELL_EXIT_STOMACH, true);
|
||||
exittrigger->CastSpell(player, SPELL_RUBBLE_ROCKY, true);
|
||||
}
|
||||
}, 3s);
|
||||
|
||||
player->m_Events.AddEventAtOffset([player]()
|
||||
{
|
||||
player->JumpTo(0.0f, 80.0f, false);
|
||||
}, 5s);
|
||||
}
|
||||
|
||||
player->m_Events.AddEventAtOffset([player, cthun]()
|
||||
{
|
||||
if (cthun)
|
||||
if (player->FindNearestCreature(NPC_EXIT_TRIGGER, 10.0f))
|
||||
{
|
||||
player->NearTeleportTo(cthun->GetPositionX(), cthun->GetPositionY(), cthun->GetPositionZ() + 10, float(rand32() % 6));
|
||||
}
|
||||
player->JumpTo(0.0f, 80.0f, false);
|
||||
|
||||
player->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID);
|
||||
}, 6s);
|
||||
player->m_Events.AddEventAtOffset([player, cthun]()
|
||||
{
|
||||
if (cthun)
|
||||
{
|
||||
player->NearTeleportTo(cthun->GetPositionX(), cthun->GetPositionY(), cthun->GetPositionZ() + 10, float(rand32() % 6));
|
||||
}
|
||||
|
||||
player->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID);
|
||||
}, 1s);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->m_Events.KillAllEvents(false);
|
||||
}
|
||||
}, 3s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -975,7 +1051,10 @@ public:
|
||||
{
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
cthun->CastSpell(player, SPELL_SPIT_OUT, true);
|
||||
if (cthun->IsAlive())
|
||||
{
|
||||
cthun->CastSpell(player, SPELL_SPIT_OUT, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,6 +1070,8 @@ void AddSC_boss_cthun()
|
||||
RegisterTempleOfAhnQirajCreatureAI(npc_claw_tentacle);
|
||||
RegisterTempleOfAhnQirajCreatureAI(npc_giant_claw_tentacle);
|
||||
RegisterTempleOfAhnQirajCreatureAI(npc_giant_eye_tentacle);
|
||||
RegisterSpellScript(spell_cthun_dark_glare);
|
||||
RegisterSpellScript(spell_cthun_digestive_acid);
|
||||
new at_cthun_stomach_exit();
|
||||
new at_cthun_center();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,10 @@ enum Events
|
||||
|
||||
struct boss_huhuran : public BossAI
|
||||
{
|
||||
boss_huhuran(Creature* creature) : BossAI(creature, DATA_HUHURAN) { }
|
||||
boss_huhuran(Creature* creature) : BossAI(creature, DATA_HUHURAN)
|
||||
{
|
||||
me->m_CombatDistance = 90.f;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
@@ -58,8 +61,9 @@ struct boss_huhuran : public BossAI
|
||||
_hardEnrage = false;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 12s, 21s);
|
||||
events.ScheduleEvent(EVENT_WYVERN_STING, 25s, 43s);
|
||||
events.ScheduleEvent(EVENT_ACID_SPIT, 1s, 20s);
|
||||
@@ -153,6 +157,7 @@ class spell_huhuran_wyvern_sting : public AuraScript
|
||||
};
|
||||
|
||||
// 26052 - Poison Bolt
|
||||
// 26180 - Wyvern Sting
|
||||
class spell_huhuran_poison_bolt : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_huhuran_poison_bolt);
|
||||
|
||||
@@ -78,8 +78,15 @@ struct npc_ouro_spawner : public ScriptedAI
|
||||
// Spawn Ouro on LoS check
|
||||
if (!hasSummoned && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 40.0f) && !who->ToPlayer()->IsGameMaster())
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_OURO);
|
||||
hasSummoned = true;
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
{
|
||||
Creature* ouro = instance->GetCreature(DATA_OURO);
|
||||
if (instance->GetBossState(DATA_OURO) != IN_PROGRESS && !ouro)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_OURO);
|
||||
hasSummoned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
@@ -105,6 +112,11 @@ struct boss_ouro : public BossAI
|
||||
_scheduler.SetValidator([this] { return !me->HasUnitState(UNIT_STATE_CASTING); });
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* victim) const override
|
||||
{
|
||||
return me->IsWithinMeleeRange(victim);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(20, damage) && !_enraged)
|
||||
@@ -129,6 +141,9 @@ struct boss_ouro : public BossAI
|
||||
|
||||
void Submerge()
|
||||
{
|
||||
if (_enraged || _submerged)
|
||||
return;
|
||||
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
@@ -180,7 +195,9 @@ struct boss_ouro : public BossAI
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spellInfo->Id == SPELL_SAND_BLAST && target)
|
||||
me->GetThreatMgr().ModifyThreatByPercent(target, 100);
|
||||
{
|
||||
me->GetThreatMgr().ModifyThreatByPercent(target, -100);
|
||||
}
|
||||
}
|
||||
|
||||
void Emerge()
|
||||
@@ -192,7 +209,21 @@ struct boss_ouro : public BossAI
|
||||
_scheduler
|
||||
.Schedule(20s, GROUP_EMERGED, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SAND_BLAST);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, 0.0f, true))
|
||||
{
|
||||
me->SetTarget(target->GetGUID());
|
||||
}
|
||||
|
||||
DoCastAOE(SPELL_SAND_BLAST);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
if (Unit* victim = me->GetVictim())
|
||||
{
|
||||
me->SetTarget(victim->GetGUID());
|
||||
}
|
||||
}, 3s);
|
||||
|
||||
context.Repeat();
|
||||
})
|
||||
.Schedule(22s, GROUP_EMERGED, [this](TaskContext context)
|
||||
@@ -206,6 +237,9 @@ struct boss_ouro : public BossAI
|
||||
})
|
||||
.Schedule(3s, GROUP_PHASE_TRANSITION, [this](TaskContext context)
|
||||
{
|
||||
if (_enraged)
|
||||
return;
|
||||
|
||||
if (!IsPlayerWithinMeleeRange() && !_submerged)
|
||||
{
|
||||
if (_submergeMelee < 10)
|
||||
@@ -214,8 +248,7 @@ struct boss_ouro : public BossAI
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_enraged)
|
||||
Submerge();
|
||||
Submerge();
|
||||
_submergeMelee = 0;
|
||||
}
|
||||
}
|
||||
@@ -240,11 +273,14 @@ struct boss_ouro : public BossAI
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL);
|
||||
me->DespawnOrUnsummon(1000);
|
||||
instance->SetBossState(DATA_OURO, FAIL);
|
||||
if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f))
|
||||
base->DespawnOrUnsummon();
|
||||
if (me->GetThreatMgr().GetThreatList().empty())
|
||||
{
|
||||
DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL);
|
||||
me->DespawnOrUnsummon(1000);
|
||||
instance->SetBossState(DATA_OURO, FAIL);
|
||||
if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f))
|
||||
base->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
@@ -256,9 +292,7 @@ struct boss_ouro : public BossAI
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
UpdateVictim();
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
@@ -318,7 +352,7 @@ struct npc_dirt_mound : ScriptedAI
|
||||
|
||||
void ChaseNewTarget()
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.f, true))
|
||||
{
|
||||
me->AddThreat(target, 1000000.f);
|
||||
|
||||
@@ -34,7 +34,6 @@ enum Spells
|
||||
SPELL_ENRAGE = 8269,
|
||||
SPELL_BERSERK = 27680,
|
||||
SPELL_SUNDERING_CLEAVE = 25174,
|
||||
|
||||
// Sartura's Royal Guard
|
||||
SPELL_GUARD_WHIRLWIND = 26038,
|
||||
SPELL_GUARD_KNOCKBACK = 26027
|
||||
@@ -44,20 +43,15 @@ enum events
|
||||
{
|
||||
// Battleguard Sartura
|
||||
EVENT_SARTURA_WHIRLWIND = 1,
|
||||
EVENT_SARTURA_WHIRLWIND_RANDOM = 2,
|
||||
EVENT_SARTURA_WHIRLWIND_END = 3,
|
||||
EVENT_SPELL_BERSERK = 4,
|
||||
EVENT_SARTURA_AGGRO_RESET = 5,
|
||||
EVENT_SARTURA_AGGRO_RESET_END = 6,
|
||||
EVENT_SARTURA_SUNDERING_CLEAVE = 7,
|
||||
|
||||
EVENT_SARTURA_WHIRLWIND_RANDOM,
|
||||
EVENT_SARTURA_WHIRLWIND_END,
|
||||
EVENT_SPELL_BERSERK,
|
||||
EVENT_SARTURA_SUNDERING_CLEAVE,
|
||||
// Sartura's Royal Guard
|
||||
EVENT_GUARD_WHIRLWIND = 8,
|
||||
EVENT_GUARD_WHIRLWIND_RANDOM = 9,
|
||||
EVENT_GUARD_WHIRLWIND_END = 10,
|
||||
EVENT_GUARD_KNOCKBACK = 11,
|
||||
EVENT_GUARD_AGGRO_RESET = 12,
|
||||
EVENT_GUARD_AGGRO_RESET_END = 13
|
||||
EVENT_GUARD_WHIRLWIND,
|
||||
EVENT_GUARD_WHIRLWIND_RANDOM,
|
||||
EVENT_GUARD_WHIRLWIND_END,
|
||||
EVENT_GUARD_KNOCKBACK,
|
||||
};
|
||||
|
||||
struct boss_sartura : public BossAI
|
||||
@@ -74,23 +68,10 @@ struct boss_sartura : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
whirlwind = false;
|
||||
enraged = false;
|
||||
berserked = false;
|
||||
aggroReset = false;
|
||||
MinionReset();
|
||||
_savedTargetGUID.Clear();
|
||||
_savedTargetThreat = 0.f;
|
||||
}
|
||||
|
||||
void MinionReset()
|
||||
{
|
||||
std::list<Creature*> royalGuards;
|
||||
me->GetCreaturesWithEntryInRange(royalGuards, 200.0f, NPC_SARTURA_ROYAL_GUARD);
|
||||
for (Creature* minion : royalGuards)
|
||||
{
|
||||
minion->Respawn();
|
||||
}
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
@@ -98,8 +79,7 @@ struct boss_sartura : public BossAI
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 12s, 22s);
|
||||
events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(45000, 55000));
|
||||
events.ScheduleEvent(EVENT_SPELL_BERSERK, 10 * 60000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BERSERK, 10min);
|
||||
events.ScheduleEvent(EVENT_SARTURA_SUNDERING_CLEAVE, 2400ms, 3s);
|
||||
}
|
||||
|
||||
@@ -135,70 +115,38 @@ struct boss_sartura : public BossAI
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SARTURA_WHIRLWIND:
|
||||
DoCastSelf(SPELL_WHIRLWIND, true);
|
||||
whirlwind = true;
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_RANDOM, urand(3000, 7000));
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_END, 15000);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
|
||||
{
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->AddThreat(target, 1000.0f);
|
||||
}
|
||||
DoCastSelf(SPELL_WHIRLWIND);
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_RANDOM, 2s, 7s);
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND_END, 15s);
|
||||
break;
|
||||
case EVENT_SARTURA_WHIRLWIND_RANDOM:
|
||||
if (whirlwind == true)
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AttackStart(target);
|
||||
}
|
||||
events.RepeatEvent(urand(3000, 7000));
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->AddThreat(target, 1000.0f);
|
||||
}
|
||||
events.Repeat(2s, 7s);
|
||||
break;
|
||||
case EVENT_SARTURA_WHIRLWIND_END:
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
events.CancelEvent(EVENT_SARTURA_WHIRLWIND_RANDOM);
|
||||
whirlwind = false;
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 5s, 11s);
|
||||
break;
|
||||
case EVENT_SARTURA_AGGRO_RESET:
|
||||
if (aggroReset == false)
|
||||
{
|
||||
if (Unit* originalTarget = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
_savedTargetGUID = originalTarget->GetGUID();
|
||||
_savedTargetThreat = me->GetThreatMgr().GetThreat(originalTarget);
|
||||
me->GetThreatMgr().ModifyThreatByPercent(originalTarget, -100);
|
||||
}
|
||||
aggroReset = true;
|
||||
events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET_END, 5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AttackStart(target);
|
||||
}
|
||||
}
|
||||
events.RepeatEvent(urand(1000, 2000));
|
||||
break;
|
||||
case EVENT_SARTURA_AGGRO_RESET_END:
|
||||
events.CancelEvent(EVENT_SARTURA_AGGRO_RESET);
|
||||
if (Unit* originalTarget = ObjectAccessor::GetUnit(*me, _savedTargetGUID))
|
||||
{
|
||||
me->GetThreatMgr().AddThreat(originalTarget, _savedTargetThreat);
|
||||
_savedTargetGUID.Clear();
|
||||
}
|
||||
aggroReset = false;
|
||||
events.RescheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(30000, 40000));
|
||||
break;
|
||||
case EVENT_SPELL_BERSERK:
|
||||
if (!berserked)
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK);
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
berserked = true;
|
||||
}
|
||||
break;
|
||||
case EVENT_SARTURA_SUNDERING_CLEAVE:
|
||||
if (whirlwind)
|
||||
if (me->HasReactState(REACT_PASSIVE))
|
||||
{
|
||||
Milliseconds whirlwindTimer = events.GetTimeUntilEvent(EVENT_SARTURA_WHIRLWIND_END);
|
||||
events.RescheduleEvent(EVENT_SARTURA_SUNDERING_CLEAVE, whirlwindTimer + 500ms);
|
||||
@@ -213,15 +161,13 @@ struct boss_sartura : public BossAI
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
};
|
||||
|
||||
private:
|
||||
bool whirlwind;
|
||||
bool enraged;
|
||||
bool berserked;
|
||||
bool aggroReset;
|
||||
ObjectGuid _savedTargetGUID;
|
||||
float _savedTargetThreat;
|
||||
};
|
||||
|
||||
struct npc_sartura_royal_guard : public ScriptedAI
|
||||
@@ -231,16 +177,13 @@ struct npc_sartura_royal_guard : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
whirlwind = false;
|
||||
aggroReset = false;
|
||||
_savedTargetGUID.Clear();
|
||||
_savedTargetThreat = 0.f;
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 6s, 10s);
|
||||
events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(45000, 55000));
|
||||
events.ScheduleEvent(EVENT_GUARD_KNOCKBACK, 12s, 16s);
|
||||
}
|
||||
|
||||
@@ -256,74 +199,38 @@ struct npc_sartura_royal_guard : public ScriptedAI
|
||||
switch (eventid)
|
||||
{
|
||||
case EVENT_GUARD_WHIRLWIND:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
|
||||
{
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->AddThreat(target, 1000.0f);
|
||||
}
|
||||
DoCastSelf(SPELL_GUARD_WHIRLWIND);
|
||||
whirlwind = true;
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_RANDOM, urand(3000, 7000));
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_RANDOM, 2s, 7s);
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_END, 8s);
|
||||
break;
|
||||
case EVENT_GUARD_WHIRLWIND_RANDOM:
|
||||
if (whirlwind == true)
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AttackStart(target);
|
||||
}
|
||||
events.RepeatEvent(urand(3000, 7000));
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->AddThreat(target, 1000.0f);
|
||||
}
|
||||
events.Repeat(2s, 7s);
|
||||
break;
|
||||
case EVENT_GUARD_WHIRLWIND_END:
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
events.CancelEvent(EVENT_GUARD_WHIRLWIND_RANDOM);
|
||||
whirlwind = false;
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 500ms, 9s);
|
||||
break;
|
||||
case EVENT_GUARD_AGGRO_RESET:
|
||||
if (aggroReset == true)
|
||||
{
|
||||
if (Unit* originalTarget = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
_savedTargetGUID = originalTarget->GetGUID();
|
||||
_savedTargetThreat = me->GetThreatMgr().GetThreat(originalTarget);
|
||||
me->GetThreatMgr().ModifyThreatByPercent(originalTarget, -100);
|
||||
}
|
||||
aggroReset = true;
|
||||
events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET_END, 5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(target, 1.0f);
|
||||
me->TauntApply(target);
|
||||
AttackStart(target);
|
||||
}
|
||||
}
|
||||
events.RepeatEvent(urand(1000, 2000));
|
||||
break;
|
||||
case EVENT_GUARD_AGGRO_RESET_END:
|
||||
events.CancelEvent(EVENT_GUARD_AGGRO_RESET);
|
||||
if (Unit* originalTarget = ObjectAccessor::GetUnit(*me, _savedTargetGUID))
|
||||
{
|
||||
me->GetThreatMgr().AddThreat(originalTarget, _savedTargetThreat);
|
||||
_savedTargetGUID.Clear();
|
||||
}
|
||||
aggroReset = false;
|
||||
events.RescheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(30000, 40000));
|
||||
break;
|
||||
case EVENT_GUARD_KNOCKBACK:
|
||||
DoCastVictim(SPELL_GUARD_KNOCKBACK);
|
||||
events.Repeat(21s, 37s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool whirlwind;
|
||||
bool aggroReset;
|
||||
ObjectGuid _savedTargetGUID;
|
||||
float _savedTargetThreat;
|
||||
};
|
||||
|
||||
void AddSC_boss_sartura()
|
||||
|
||||
@@ -134,6 +134,8 @@ struct boss_skeram : public BossAI
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
if (me->GetMap() && me->GetMap()->ToInstanceMap())
|
||||
me->GetMap()->ToInstanceMap()->PermBindAllPlayers();
|
||||
}
|
||||
else
|
||||
me->RemoveCorpse();
|
||||
@@ -176,7 +178,7 @@ struct boss_skeram : public BossAI
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
DoCast(me, BlinkSpells[urand(0, 2)]);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
events.ScheduleEvent(EVENT_BLINK, 10s, 30s);
|
||||
break;
|
||||
case EVENT_EARTH_SHOCK:
|
||||
@@ -194,7 +196,7 @@ struct boss_skeram : public BossAI
|
||||
DoTeleport(image);
|
||||
}
|
||||
}
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
events.RescheduleEvent(EVENT_BLINK, 10s, 30s);
|
||||
break;
|
||||
case EVENT_INIT_IMAGE:
|
||||
|
||||
@@ -158,7 +158,7 @@ struct boss_twinemperorsAI : public BossAI
|
||||
|
||||
if (action == ACTION_AFTER_TELEPORT)
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
DoCastSelf(SPELL_TWIN_TELEPORT_VISUAL, true);
|
||||
_scheduler.DelayAll(2300ms);
|
||||
@@ -168,7 +168,7 @@ struct boss_twinemperorsAI : public BossAI
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
if (Unit* victim = me->SelectNearestTarget())
|
||||
{
|
||||
me->AddThreat(victim, 200000.f);
|
||||
me->AddThreat(victim, 2000.f);
|
||||
AttackStart(victim);
|
||||
}
|
||||
});
|
||||
@@ -327,10 +327,7 @@ struct boss_veknilash : public boss_twinemperorsAI
|
||||
|
||||
struct boss_veklor : public boss_twinemperorsAI
|
||||
{
|
||||
boss_veklor(Creature* creature) : boss_twinemperorsAI(creature)
|
||||
{
|
||||
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 45.f);
|
||||
}
|
||||
boss_veklor(Creature* creature) : boss_twinemperorsAI(creature) { }
|
||||
|
||||
bool IAmVeklor() override { return true; }
|
||||
|
||||
@@ -343,13 +340,26 @@ struct boss_veklor : public boss_twinemperorsAI
|
||||
_scheduler
|
||||
.Schedule(4s, [this](TaskContext context)
|
||||
{
|
||||
if (me->GetVictim())
|
||||
{
|
||||
if (!me->IsWithinDist(me->GetVictim(), 45.0f))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), 45.0f, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->StopMoving();
|
||||
me->GetMotionMaster()->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
DoCastVictim(SPELL_SHADOW_BOLT);
|
||||
context.Repeat(2500ms);
|
||||
})
|
||||
.Schedule(10s, 15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_BLIZZARD, 0, 45.f);
|
||||
context.Repeat(5s, 12s);
|
||||
context.Repeat(10s, 24s);
|
||||
})
|
||||
.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
@@ -357,10 +367,10 @@ struct boss_veklor : public boss_twinemperorsAI
|
||||
DoCastAOE(SPELL_ARCANE_BURST);
|
||||
context.Repeat(7s, 12s);
|
||||
})
|
||||
.Schedule(30s, 40s, [this](TaskContext context)
|
||||
.Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_TWIN_TELEPORT_0);
|
||||
context.Repeat();
|
||||
context.Repeat(30s, 40s);
|
||||
})
|
||||
.Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
@@ -391,6 +401,19 @@ struct boss_veklor : public boss_twinemperorsAI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (who && who->isTargetableForAttack() && me->GetReactState() != REACT_PASSIVE)
|
||||
{
|
||||
// VL doesn't melee
|
||||
if (me->Attack(who, false))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(who, 45.0f, 0);
|
||||
me->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class at_twin_emperors : public OnlyOnceAreaTriggerScript
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
@@ -100,6 +101,7 @@ struct boss_viscidus : public BossAI
|
||||
boss_viscidus(Creature* creature) : BossAI(creature, DATA_VISCIDUS)
|
||||
{
|
||||
me->LowerPlayerDamageReq(me->GetMaxHealth());
|
||||
me->m_CombatDistance = 60.f;
|
||||
}
|
||||
|
||||
bool CheckInRoom() override
|
||||
@@ -131,13 +133,36 @@ struct boss_viscidus : public BossAI
|
||||
me->RemoveAurasDueToSpell(SPELL_INVIS_SELF);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType effType, SpellSchoolMask) override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll(10 * IN_MILLISECONDS);
|
||||
if (instance)
|
||||
{
|
||||
instance->SetBossState(DATA_VISCIDUS, DONE);
|
||||
instance->SaveToDB();
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType effType, SpellSchoolMask spellSchoolMask) override
|
||||
{
|
||||
if (me->HealthBelowPct(5))
|
||||
damage = 0;
|
||||
|
||||
if (!attacker || _phase != PHASE_MELEE)
|
||||
if (!attacker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_phase != PHASE_MELEE)
|
||||
{
|
||||
if (_phase == PHASE_FROST && effType == DIRECT_DAMAGE && (spellSchoolMask & SPELL_SCHOOL_MASK_FROST) != 0)
|
||||
{
|
||||
++_hitcounter;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (effType == DIRECT_DAMAGE)
|
||||
++_hitcounter;
|
||||
@@ -170,7 +195,7 @@ struct boss_viscidus : public BossAI
|
||||
me->SetAuraStack(SPELL_VISCIDUS_SHRINKS, me, 20);
|
||||
me->LowerPlayerDamageReq(me->GetMaxHealth());
|
||||
me->SetHealth(me->GetMaxHealth() * 0.01f); // set 1% health
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->NearTeleportTo(roomCenter.GetPositionX(),
|
||||
roomCenter.GetPositionY(),
|
||||
roomCenter.GetPositionZ(),
|
||||
@@ -183,14 +208,23 @@ struct boss_viscidus : public BossAI
|
||||
Talk(EMOTE_CRACK);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (spell->Id == SPELL_REJOIN_VISCIDUS)
|
||||
if (spellInfo->Id == SPELL_REJOIN_VISCIDUS)
|
||||
{
|
||||
me->RemoveAuraFromStack(SPELL_VISCIDUS_SHRINKS);
|
||||
}
|
||||
|
||||
if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST)
|
||||
SpellSchoolMask spellSchoolMask = spellInfo->GetSchoolMask();
|
||||
if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && spellInfo->EquippedItemSubClassMask & (1 << ITEM_SUBCLASS_WEAPON_WAND))
|
||||
{
|
||||
if (Item* pItem = caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK))
|
||||
{
|
||||
spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->Damage[0].DamageType);
|
||||
}
|
||||
}
|
||||
|
||||
if ((spellSchoolMask & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST)
|
||||
{
|
||||
++_hitcounter;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ ObjectData const creatureData[] =
|
||||
{ NPC_SARTURA, DATA_SARTURA },
|
||||
{ NPC_CTHUN, DATA_CTHUN },
|
||||
{ NPC_EYE_OF_CTHUN, DATA_EYE_OF_CTHUN },
|
||||
{ NPC_OURO, DATA_OURO },
|
||||
{ NPC_OURO_SPAWNER, DATA_OURO_SPAWNER },
|
||||
{ NPC_MASTERS_EYE, DATA_MASTERS_EYE },
|
||||
{ NPC_VEKLOR, DATA_VEKLOR },
|
||||
|
||||
@@ -15,22 +15,11 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: npc_anubisath_sentinel
|
||||
SD%Complete: 95
|
||||
SDComment: Shadow storm is not properly implemented in core it should only target ppl outside of melee range.
|
||||
SDCategory: Temple of Ahn'Qiraj
|
||||
EndScriptData */
|
||||
|
||||
#include "Cell.h"
|
||||
#include "CellImpl.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "SpellScript.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
@@ -179,7 +168,7 @@ public:
|
||||
void AddSentinelsNear(Unit* /*nears*/)
|
||||
{
|
||||
std::list<Creature*> assistList;
|
||||
me->GetCreatureListWithEntryInGrid(assistList, 15264, 70.0f);
|
||||
me->GetCreatureListWithEntryInGrid(assistList, 15264, 100.0f);
|
||||
|
||||
if (assistList.empty())
|
||||
return;
|
||||
@@ -316,7 +305,46 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
// 9347: Mortal Strike
|
||||
class spell_anubisath_mortal_strike : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_anubisath_mortal_strike);
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
if (Unit* target = GetUnitOwner()->GetVictim())
|
||||
if (target->IsWithinDist(GetUnitOwner(), 5.f))
|
||||
GetUnitOwner()->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_anubisath_mortal_strike::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
// 26626 (Server-side): Mana Burn Area
|
||||
class spell_mana_burn_area : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_mana_burn_area);
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
GetCaster()->CastSpell(target, SPELL_MANAB, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_mana_burn_area::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_npc_anubisath_sentinel()
|
||||
{
|
||||
new npc_anubisath_sentinel();
|
||||
RegisterSpellScript(spell_anubisath_mortal_strike);
|
||||
RegisterSpellScript(spell_mana_burn_area);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ enum Spells
|
||||
SPELL_SHADOW_STORM = 26555,
|
||||
SPELL_THUNDERCLAP = 26554,
|
||||
SPELL_ENRAGE = 14204,
|
||||
SPELL_EXPLODE = 25699,
|
||||
SPELL_EXPLODE = 25698,
|
||||
SPELL_SUMMON_WARRIOR = 17431,
|
||||
SPELL_SUMMON_SWARMGUARD = 17430,
|
||||
SPELL_SUMMON_LARGE_OBSIDIAN_CHUNK = 27630, // Server-side
|
||||
@@ -47,7 +47,7 @@ enum Spells
|
||||
|
||||
// Obsidian Eradicator
|
||||
SPELL_SHOCK_BLAST = 26458,
|
||||
SPELL_DRAIN_MANA = 25671,
|
||||
SPELL_DRAIN_MANA_ERADICATOR = 25755,
|
||||
SPELL_DRAIN_MANA_VISUAL = 26639,
|
||||
|
||||
// Anubisath Warder
|
||||
@@ -59,6 +59,7 @@ enum Spells
|
||||
|
||||
// Obsidian Nullifier
|
||||
SPELL_NULLIFY = 26552,
|
||||
SPELL_DRAIN_MANA_NULLIFIER = 25671,
|
||||
SPELL_CLEAVE = 40504,
|
||||
|
||||
// Qiraji Scorpion
|
||||
@@ -242,14 +243,14 @@ struct npc_obsidian_eradicator : public ScriptedAI
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
me->SetPower(POWER_MANA, 0);
|
||||
_targets.clear();
|
||||
_targetGUIDs.clear();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(3500ms, [this](TaskContext context)
|
||||
{
|
||||
if (_targets.empty())
|
||||
if (_targetGUIDs.empty())
|
||||
{
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
@@ -258,22 +259,25 @@ struct npc_obsidian_eradicator : public ScriptedAI
|
||||
{
|
||||
if (player->IsAlive() && !player->IsGameMaster() && !player->IsSpectator() && player->GetPower(POWER_MANA) > 0)
|
||||
{
|
||||
_targets.push_back(player);
|
||||
_targetGUIDs.push_back(player->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Acore::Containers::RandomResize(_targets, 10);
|
||||
Acore::Containers::RandomResize(_targetGUIDs, 10);
|
||||
}
|
||||
|
||||
for (Unit* target : _targets)
|
||||
for (ObjectGuid guid : _targetGUIDs)
|
||||
{
|
||||
DoCast(target, SPELL_DRAIN_MANA, true);
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, guid))
|
||||
{
|
||||
DoCast(target, SPELL_DRAIN_MANA_ERADICATOR, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (me->GetPowerPct(POWER_MANA) >= 100.f)
|
||||
{
|
||||
DoCastAOE(SPELL_SHOCK_BLAST, true);
|
||||
DoCastAOE(SPELL_SHOCK_BLAST);
|
||||
}
|
||||
|
||||
context.Repeat(3500ms);
|
||||
@@ -293,7 +297,7 @@ struct npc_obsidian_eradicator : public ScriptedAI
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::list<Player*> _targets;
|
||||
GuidList _targetGUIDs;
|
||||
};
|
||||
|
||||
struct npc_anubisath_warder : public ScriptedAI
|
||||
@@ -375,14 +379,14 @@ struct npc_obsidian_nullifier : public ScriptedAI
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
me->SetPower(POWER_MANA, 0);
|
||||
_targets.clear();
|
||||
_targetGUIDs.clear();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
if (_targets.empty())
|
||||
if (_targetGUIDs.empty())
|
||||
{
|
||||
Map::PlayerList const& players = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
@@ -391,22 +395,25 @@ struct npc_obsidian_nullifier : public ScriptedAI
|
||||
{
|
||||
if (player->IsAlive() && !player->IsGameMaster() && !player->IsSpectator() && player->GetPower(POWER_MANA) > 0)
|
||||
{
|
||||
_targets.push_back(player);
|
||||
_targetGUIDs.push_back(player->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Acore::Containers::RandomResize(_targets, 11);
|
||||
Acore::Containers::RandomResize(_targetGUIDs, 11);
|
||||
}
|
||||
|
||||
for (Unit* target : _targets)
|
||||
for (ObjectGuid guid : _targetGUIDs)
|
||||
{
|
||||
DoCast(target, SPELL_DRAIN_MANA, true);
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, guid))
|
||||
{
|
||||
DoCast(target, SPELL_DRAIN_MANA_NULLIFIER, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (me->GetPowerPct(POWER_MANA) >= 100.f)
|
||||
{
|
||||
DoCastAOE(SPELL_NULLIFY, true);
|
||||
DoCastAOE(SPELL_NULLIFY);
|
||||
}
|
||||
|
||||
context.Repeat(6s);
|
||||
@@ -431,7 +438,7 @@ struct npc_obsidian_nullifier : public ScriptedAI
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::list<Player*> _targets;
|
||||
GuidList _targetGUIDs;
|
||||
};
|
||||
|
||||
struct npc_ahnqiraji_critter : public ScriptedAI
|
||||
@@ -445,6 +452,19 @@ struct npc_ahnqiraji_critter : public ScriptedAI
|
||||
me->RestoreFaction();
|
||||
|
||||
_scheduler.CancelAll();
|
||||
|
||||
// Don't attack nearby players randomly if they are the Twin's pet bugs.
|
||||
if (CreatureData const* crData = me->GetCreatureData())
|
||||
{
|
||||
ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Unit>(crData->id1, me->GetSpawnId());
|
||||
ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
|
||||
|
||||
if (targetGuid.GetEntry() == NPC_VEKLOR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_scheduler.Schedule(100ms, [this](TaskContext context)
|
||||
{
|
||||
if (Player* player = me->SelectNearestPlayer(10.f))
|
||||
|
||||
+1
-1
@@ -429,7 +429,7 @@ public:
|
||||
{
|
||||
case SPELL_CLAW_N:
|
||||
case SPELL_CLAW_H:
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
|
||||
{
|
||||
me->AddThreat(target, 100.0f);
|
||||
|
||||
+1
-1
@@ -927,7 +927,7 @@ public:
|
||||
Player* player = itr->GetSource();
|
||||
if( player && me->IsInRange(player, 8.0f, 25.0f, false) )
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(player, 5.0f);
|
||||
me->CastSpell(player, SPELL_INTERCEPT, false);
|
||||
break;
|
||||
|
||||
+21
-9
@@ -256,26 +256,36 @@ public:
|
||||
|
||||
// EVENT STUFF BELOW:
|
||||
|
||||
void OnPlayerEnter(Player*) override
|
||||
void OnPlayerEnter(Player* plr) override
|
||||
{
|
||||
if( DoNeedCleanup(true) )
|
||||
if (DoNeedCleanup(plr))
|
||||
{
|
||||
InstanceCleanup();
|
||||
}
|
||||
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, CLEANUP_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
bool DoNeedCleanup(bool /*enter*/)
|
||||
bool DoNeedCleanup(Player* ignoredPlayer = nullptr)
|
||||
{
|
||||
uint8 aliveCount = 0;
|
||||
Map::PlayerList const& pl = instance->GetPlayers();
|
||||
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
|
||||
if( Player* plr = itr->GetSource() )
|
||||
if( plr->IsAlive() && !plr->IsGameMaster() )
|
||||
for (const auto &itr: instance->GetPlayers())
|
||||
{
|
||||
if (Player* plr = itr.GetSource())
|
||||
{
|
||||
if (plr != ignoredPlayer && plr->IsAlive() && !plr->IsGameMaster())
|
||||
{
|
||||
++aliveCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool need = aliveCount == 0;
|
||||
if( !need && CLEANED )
|
||||
if (!need && CLEANED)
|
||||
{
|
||||
CLEANED = false;
|
||||
}
|
||||
|
||||
return need;
|
||||
}
|
||||
|
||||
@@ -769,8 +779,10 @@ public:
|
||||
break;
|
||||
case EVENT_CHECK_PLAYERS:
|
||||
{
|
||||
if( DoNeedCleanup(false) )
|
||||
if (DoNeedCleanup())
|
||||
{
|
||||
InstanceCleanup();
|
||||
}
|
||||
events.RepeatEvent(CLEANUP_CHECK_INTERVAL);
|
||||
}
|
||||
break;
|
||||
|
||||
+1
-1
@@ -767,7 +767,7 @@ public:
|
||||
me->RemoveAllAuras();
|
||||
}
|
||||
DoZoneInCombat();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if( Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 250.0f, true) )
|
||||
{
|
||||
if (!next)
|
||||
|
||||
+1
-1
@@ -336,7 +336,7 @@ public:
|
||||
case EVENT_SPELL_FEL_STEAK:
|
||||
if( Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 44.0f, true) )
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(target, 50000.0f);
|
||||
me->CastSpell(target, SPELL_FEL_STEAK_MORPH, true);
|
||||
me->CastSpell(target, SPELL_FEL_STEAK, true);
|
||||
|
||||
+1
-1
@@ -593,7 +593,7 @@ struct boss_jormungarAI : public ScriptedAI
|
||||
}
|
||||
me->UpdatePosition(Locs[LOC_CENTER].GetPositionX() + cos(angle)*dist, Locs[LOC_CENTER].GetPositionY() + std::sin(angle)*dist, me->GetPositionZ(), me->GetOrientation(), true);
|
||||
me->StopMovingOnCurrentPos();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
|
||||
events.RescheduleEvent(EVENT_EMERGE, 6000);
|
||||
}
|
||||
|
||||
+20
-8
@@ -567,8 +567,10 @@ public:
|
||||
DoCheckDedicatedInsanity();
|
||||
bSwitcher = !bSwitcher;
|
||||
|
||||
if( DoNeedCleanup(false) )
|
||||
if (DoNeedCleanup())
|
||||
{
|
||||
InstanceCleanup();
|
||||
}
|
||||
events.RepeatEvent(CLEANUP_CHECK_INTERVAL);
|
||||
}
|
||||
break;
|
||||
@@ -1401,8 +1403,10 @@ public:
|
||||
else
|
||||
plr->SendUpdateWorldState(UPDATE_STATE_UI_SHOW, 0);
|
||||
|
||||
if( DoNeedCleanup(true) )
|
||||
if (DoNeedCleanup(plr))
|
||||
{
|
||||
InstanceCleanup();
|
||||
}
|
||||
|
||||
// if missing spawn anub'arak
|
||||
SpawnAnubArak();
|
||||
@@ -1410,18 +1414,26 @@ public:
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, CLEANUP_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
bool DoNeedCleanup(bool /*enter*/)
|
||||
bool DoNeedCleanup(Player* ignoredPlayer = nullptr)
|
||||
{
|
||||
uint8 aliveCount = 0;
|
||||
Map::PlayerList const& pl = instance->GetPlayers();
|
||||
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
|
||||
if( Player* plr = itr->GetSource() )
|
||||
if( plr->IsAlive() && !plr->IsGameMaster() )
|
||||
for (auto const& itr: instance->GetPlayers())
|
||||
{
|
||||
if (Player* plr = itr.GetSource())
|
||||
{
|
||||
if (plr != ignoredPlayer && plr->IsAlive() && !plr->IsGameMaster())
|
||||
{
|
||||
++aliveCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool need = aliveCount == 0;
|
||||
if( !need && CLEANED )
|
||||
if (!need && CLEANED)
|
||||
{
|
||||
CLEANED = false;
|
||||
}
|
||||
|
||||
return need;
|
||||
}
|
||||
|
||||
|
||||
@@ -971,7 +971,7 @@ public:
|
||||
case EVENT_SHADOW_STEP:
|
||||
if (Unit* target = SelectTargetFromPlayerList(100.0f, 0, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(target, 5000.0f);
|
||||
AttackStart(target);
|
||||
me->CastSpell(target, SPELL_SHADOW_STEP, false);
|
||||
|
||||
@@ -750,8 +750,8 @@ public:
|
||||
InstanceScript* instance = creature->GetInstanceScript();
|
||||
if (instance && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != IN_PROGRESS)
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "We are ready to go, High Overlord. The Lich King must fall!", 631, -ACTION_START_EVENT);
|
||||
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
|
||||
AddGossipItemFor(player, 10953, 0, GOSSIP_SENDER_INFO, -ACTION_START_EVENT);
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(10953, creature), creature->GetGUID());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -964,8 +964,8 @@ public:
|
||||
InstanceScript* instance = creature->GetInstanceScript();
|
||||
if (instance && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != IN_PROGRESS)
|
||||
{
|
||||
AddGossipItemFor(player, 0, "Let it begin...", 631, -ACTION_START_EVENT + 1);
|
||||
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
|
||||
AddGossipItemFor(player, 10933, 0, GOSSIP_SENDER_INFO, -ACTION_START_EVENT + 1);
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(10933, creature), creature->GetGUID());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -305,7 +305,7 @@ public:
|
||||
Unit* unit = ObjectAccessor::GetUnit((*me), (*itr)->getUnitGuid());
|
||||
|
||||
if (unit && DoGetThreat(unit))
|
||||
DoModifyThreatPercent(unit, -100);
|
||||
DoModifyThreatByPercent(unit, -100);
|
||||
}
|
||||
|
||||
Talk(SAY_PHASE_2);
|
||||
|
||||
@@ -383,7 +383,7 @@ public:
|
||||
me->CastSpell(me, SPELL_WEAK_RADIATING_OOZE, true);
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_STICKY_OOZE, 5000);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetInCombatWithZone();
|
||||
if (TempSummon* ts = me->ToTempSummon())
|
||||
if (Unit* summoner = ts->GetSummonerUnit())
|
||||
@@ -468,7 +468,7 @@ public:
|
||||
me->CastSpell(me, SPELL_GREEN_ABOMINATION_HITTIN__YA_PROC, true);
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_STICKY_OOZE, 5000);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetInCombatWithZone();
|
||||
if (Player* p = me->SelectNearestPlayer(100.0f))
|
||||
AttackStart(p);
|
||||
|
||||
@@ -1777,7 +1777,7 @@ public:
|
||||
c->NearTeleportTo(myPos.GetPositionX(), myPos.GetPositionY(), myPos.GetPositionZ(), myPos.GetOrientation());
|
||||
const ThreatContainer::StorageType me_tl = me->GetThreatMgr().GetThreatList();
|
||||
const ThreatContainer::StorageType target_tl = c->GetThreatMgr().GetThreatList();
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator iter = target_tl.begin(); iter != target_tl.end(); ++iter)
|
||||
me->GetThreatMgr().AddThreat((*iter)->getTarget(), (*iter)->GetThreat());
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ public:
|
||||
StartBalconyPhase();
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->CastSpell(me, RAID_MODE(SPELL_CRIPPLE_10, SPELL_CRIPPLE_25), false);
|
||||
me->CastSpell(me, SPELL_BLINK, true);
|
||||
Talk(EMOTE_BLINK);
|
||||
|
||||
@@ -835,7 +835,7 @@ public:
|
||||
_flyTargetGUID.Clear();
|
||||
me->RemoveAura(SPELL_LIGHTNING_TENDRILS);
|
||||
me->RemoveAura(61883);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
break;
|
||||
case EVENT_ENRAGE:
|
||||
Talk(SAY_BRUNDIR_BERSERK);
|
||||
|
||||
@@ -412,7 +412,7 @@ public:
|
||||
|
||||
if (_feralRushTimer >= 6000)
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
|
||||
@@ -1184,7 +1184,7 @@ public:
|
||||
break;
|
||||
case EVENT_DETONATING_LASHER_FLAME_LASH:
|
||||
me->CastSpell(me->GetVictim(), SPELL_FLAME_LASH, false);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Unit* target = SelectTargetFromPlayerList(80))
|
||||
AttackStart(target);
|
||||
else
|
||||
|
||||
@@ -1033,7 +1033,7 @@ public:
|
||||
break;
|
||||
case 4:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
Phase = 4;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (Unit* target = SelectTargetFromPlayerList(75.0f))
|
||||
@@ -1613,7 +1613,7 @@ public:
|
||||
break;
|
||||
case 4:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
Phase = 4;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (Unit* target = SelectTargetFromPlayerList(75.0f))
|
||||
|
||||
@@ -518,7 +518,7 @@ public:
|
||||
Talk(EMOTE_PERMA_GROUND);
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
me->DisableRotate(false);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 0.0, true);
|
||||
if (!target)
|
||||
target = me->SelectNearestPlayer(200.0f);
|
||||
|
||||
@@ -552,7 +552,7 @@ public:
|
||||
summons.DoAction(ACTION_SIF_JOIN_FIGHT, pred);
|
||||
}
|
||||
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Player* player = GetArenaPlayer())
|
||||
me->AddThreat(player, 1000.0f);
|
||||
}
|
||||
|
||||
@@ -1511,7 +1511,7 @@ public:
|
||||
{
|
||||
if (who && damagetype == DIRECT_DAMAGE)
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(who, 100000);
|
||||
AttackStart(who);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
@@ -1539,7 +1539,7 @@ public:
|
||||
return;
|
||||
|
||||
me->CastSpell(me, SPELL_DIMINISH_POWER, false);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
case EVENT_SHARVALD_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, (IsHeroic() ? 100.0f : 30.0f), true))
|
||||
{
|
||||
ScriptedAI::DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(target, 10000.0f);
|
||||
me->CastSpell(target, SPELL_CHARGE, false);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
if (!PlayerList.IsEmpty())
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
if (Player* player = i->GetSource())
|
||||
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
|
||||
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->m_homebindO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
break;
|
||||
case EVENT_SPELL_ARCANE_VACUUM:
|
||||
me->CastSpell((Unit*)nullptr, SPELL_ARCANE_VACUUM, false);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
me->setAttackTimer(BASE_ATTACK, 3000);
|
||||
events.RepeatEvent(30000);
|
||||
|
||||
@@ -350,7 +350,7 @@ public:
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!sWorld->getBoolConfig(CONFIG_WINTERGRASP_ENABLE))
|
||||
if (sWorld->getIntConfig(CONFIG_WINTERGRASP_ENABLE) != 1)
|
||||
return;
|
||||
|
||||
ScriptedAI::UpdateAI(diff);
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public:
|
||||
me->CastSpell(target, SPELL_INCITE_CHAOS_B, true);
|
||||
}
|
||||
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
InciteChaos = true;
|
||||
events.DelayEvents(15000);
|
||||
events.RepeatEvent(40000);
|
||||
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->GetVictim()->InterruptNonMeleeSpells(false);
|
||||
me->AddThreat(me->GetVictim(), 1000000.0f);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
{
|
||||
events.CancelEventGroup(EVENT_GROUP_ABILITIES);
|
||||
events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
|
||||
if (!run)
|
||||
{
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
case EVENT_SWITCH_TARGET:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(target, 5000000.0f);
|
||||
Talk(EMOTE_NEW_TARGET);
|
||||
}
|
||||
|
||||
@@ -553,7 +553,7 @@ public:
|
||||
me->CastSpell(me, SPELL_VANISH_OUT, false);
|
||||
break;
|
||||
case EVENT_SPELL_ENRAGE:
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
if (Creature* council = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_ILLIDARI_COUNCIL)))
|
||||
council->GetAI()->DoAction(ACTION_ENRAGE);
|
||||
break;
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ public:
|
||||
void SetForm(bool corrupt, bool initial)
|
||||
{
|
||||
events.CancelEventGroup(GROUP_ABILITIES);
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
|
||||
if (corrupt)
|
||||
{
|
||||
|
||||
+3
-3
@@ -203,7 +203,7 @@ public:
|
||||
{
|
||||
if (me->GetDisplayId() != me->GetNativeDisplayId())
|
||||
{
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->LoadEquipment();
|
||||
me->RemoveAurasDueToSpell(SPELL_METAMORPHOSIS);
|
||||
events.ScheduleEvent(EVENT_SPELL_WHIRLWIND, 10000);
|
||||
@@ -223,7 +223,7 @@ public:
|
||||
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
|
||||
break;
|
||||
case EVENT_SWITCH_TO_DEMON:
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
Talk(SAY_SWITCH_TO_DEMON);
|
||||
me->LoadEquipment(0, true);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), 25.0f);
|
||||
@@ -234,7 +234,7 @@ public:
|
||||
events.ScheduleEvent(EVENT_SWITCH_TO_ELF, 60000);
|
||||
break;
|
||||
case EVENT_SWITCH_TO_ELF:
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->LoadEquipment();
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), 0.0f);
|
||||
me->RemoveAurasDueToSpell(SPELL_METAMORPHOSIS);
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ public:
|
||||
head->AI()->Talk(threatYell - 1);
|
||||
events.ScheduleEvent(threatYell, 3000);
|
||||
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->AddThreat(target, 10.0f);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RESET_THREAT, 30000);
|
||||
|
||||
@@ -480,7 +480,7 @@ public:
|
||||
events2.CancelEvent(EVENT_PREFIGHT_PHASE71);
|
||||
Talk(SAY_PHASE4_INTRO2);
|
||||
phase = PHASE_FINAL;
|
||||
DoResetThreat();
|
||||
DoResetThreatList();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
AttackStart(target);
|
||||
|
||||
@@ -648,10 +648,13 @@ class spell_dk_dancing_rune_weapon : public AuraScript
|
||||
{
|
||||
target = player->GetMeleeHitRedirectTarget(target);
|
||||
CalcDamageInfo damageInfo;
|
||||
player->CalculateMeleeDamage(target, 0, &damageInfo, eventInfo.GetDamageInfo()->GetAttackType());
|
||||
Unit::DealDamageMods(target, damageInfo.damage, &damageInfo.absorb);
|
||||
player->CalculateMeleeDamage(target, &damageInfo, eventInfo.GetDamageInfo()->GetAttackType());
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
Unit::DealDamageMods(target, damageInfo.damages[i].damage, &damageInfo.damages[i].absorb);
|
||||
damageInfo.damages[i].damage /= 2.0f;
|
||||
}
|
||||
damageInfo.attacker = dancingRuneWeapon;
|
||||
damageInfo.damage /= 2.0f;
|
||||
dancingRuneWeapon->SendAttackStateUpdate(&damageInfo);
|
||||
dancingRuneWeapon->DealMeleeDamage(&damageInfo, true);
|
||||
}
|
||||
|
||||
@@ -3738,6 +3738,25 @@ class spell_item_freeze_rookery_egg : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 9160 - Sleep
|
||||
class spell_item_green_whelp_armor : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_item_green_whelp_armor);
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (eventInfo.GetActor() && eventInfo.GetActor()->getLevel() <= 50)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_item_green_whelp_armor::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_item_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_item_massive_seaforium_charge);
|
||||
@@ -3853,4 +3872,5 @@ void AddSC_item_spell_scripts()
|
||||
RegisterSpellScript(spell_item_mirrens_drinking_hat);
|
||||
RegisterSpellScript(spell_item_snowman);
|
||||
RegisterSpellScript(spell_item_freeze_rookery_egg);
|
||||
RegisterSpellScript(spell_item_green_whelp_armor);
|
||||
}
|
||||
|
||||
@@ -789,12 +789,13 @@ class spell_mage_master_of_elements : public AuraScript
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
_spellInfo = eventInfo.GetSpellInfo();
|
||||
if (!_spellInfo || !eventInfo.GetActor() || !eventInfo.GetActionTarget())
|
||||
if (!eventInfo.GetActor() || !eventInfo.GetActionTarget())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_spellInfo = eventInfo.GetSpellInfo();
|
||||
|
||||
bool selectCaster = false;
|
||||
// Triggered spells cost no mana so we need triggering spellInfo
|
||||
if (SpellInfo const* triggeredByAuraSpellInfo = eventInfo.GetTriggerAuraSpell())
|
||||
@@ -803,6 +804,13 @@ class spell_mage_master_of_elements : public AuraScript
|
||||
selectCaster = true;
|
||||
}
|
||||
|
||||
if (!_spellInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_ticksModifier = 1;
|
||||
|
||||
// If spell is periodic, mana amount is divided by tick number
|
||||
if (eventInfo.GetTriggerAuraEffectIndex() >= EFFECT_0)
|
||||
{
|
||||
@@ -812,24 +820,29 @@ class spell_mage_master_of_elements : public AuraScript
|
||||
{
|
||||
if (AuraEffect const* aurEff = target->GetAuraEffect(_spellInfo->Id, eventInfo.GetTriggerAuraEffectIndex(), caster->GetGUID()))
|
||||
{
|
||||
ticksModifier = aurEff->GetTotalTicks();
|
||||
_ticksModifier = std::max(1, aurEff->GetTotalTicks());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _spellInfo; // eventInfo.GetSpellInfo()
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
int32 mana = int32(_spellInfo->CalcPowerCost(GetTarget(), eventInfo.GetSchoolMask()) / ticksModifier);
|
||||
mana = CalculatePct(mana, aurEff->GetAmount());
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
int32 mana = int32(_spellInfo->CalcPowerCost(target, eventInfo.GetSchoolMask()) / _ticksModifier);
|
||||
mana = CalculatePct(mana, aurEff->GetAmount());
|
||||
|
||||
if (mana > 0)
|
||||
GetTarget()->CastCustomSpell(SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, nullptr, aurEff);
|
||||
if (mana > 0)
|
||||
{
|
||||
target->CastCustomSpell(SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, target, true, nullptr, aurEff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
@@ -840,7 +853,7 @@ class spell_mage_master_of_elements : public AuraScript
|
||||
|
||||
private:
|
||||
SpellInfo const* _spellInfo = nullptr;
|
||||
uint8 ticksModifier = 1;
|
||||
uint8 _ticksModifier = 0;
|
||||
};
|
||||
|
||||
enum SilvermoonPolymorph
|
||||
|
||||
@@ -62,7 +62,8 @@ enum WarlockSpells
|
||||
SPELL_WARLOCK_SIPHON_LIFE_HEAL = 63106,
|
||||
SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117,
|
||||
SPELL_WARLOCK_IMPROVED_DRAIN_SOUL_R1 = 18213,
|
||||
SPELL_WARLOCK_IMPROVED_DRAIN_SOUL_PROC = 18371
|
||||
SPELL_WARLOCK_IMPROVED_DRAIN_SOUL_PROC = 18371,
|
||||
SPELL_WARLOCK_EYE_OF_KILROGG_FLY = 58083
|
||||
};
|
||||
|
||||
enum WarlockSpellIcons
|
||||
@@ -84,16 +85,15 @@ class spell_warl_eye_of_kilrogg : public AuraScript
|
||||
|
||||
// Glyph of Kilrogg
|
||||
if (player->HasAura(58081))
|
||||
{
|
||||
if (Unit* charm = player->GetCharm())
|
||||
{
|
||||
charm->SetSpeed(MOVE_RUN, 2.14f, true);
|
||||
if (charm->GetMapId() == 530 || charm->GetMapId() == 571)
|
||||
{
|
||||
charm->SetCanFly(true);
|
||||
charm->SetSpeed(MOVE_FLIGHT, 2.14f, true);
|
||||
charm->SendMovementFlagUpdate();
|
||||
charm->CastSpell(charm, SPELL_WARLOCK_EYE_OF_KILROGG_FLY, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -567,8 +567,14 @@ class spell_warr_rend : public AuraScript
|
||||
// $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick
|
||||
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
int32 mws = caster->GetAttackTime(BASE_ATTACK);
|
||||
float mwbMin = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
|
||||
float mwbMax = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
|
||||
float mwbMin = 0.f;
|
||||
float mwbMax = 0.f;
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
mwbMin += caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE, i);
|
||||
mwbMax += caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE, i);
|
||||
}
|
||||
|
||||
float mwb = ((mwbMin + mwbMax) / 2 + ap * mws / 14000) * 0.2f;
|
||||
amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb));
|
||||
|
||||
|
||||
@@ -207,19 +207,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum riggleBassbait
|
||||
/*
|
||||
* Stranglethorn Vale Fishing Extravaganza World States
|
||||
*/
|
||||
enum FishingExtravaganzaWorldStates
|
||||
{
|
||||
EVENT_RIGGLE_ANNOUNCE = 1,
|
||||
STV_FISHING_PREV_WIN_TIME = 197,
|
||||
STV_FISHING_HAS_WINNER = 198,
|
||||
STV_FISHING_ANNOUNCE_EVENT_BEGIN = 199,
|
||||
STV_FISHING_ANNOUNCE_POOLS_DESPAN = 200
|
||||
};
|
||||
|
||||
RIGGLE_SAY_START = 0,
|
||||
RIGGLE_SAY_WINNER = 1,
|
||||
RIGGLE_SAY_END = 2,
|
||||
enum RiggleBassbait
|
||||
{
|
||||
RIGGLE_SAY_START = 0,
|
||||
RIGGLE_SAY_POOLS_END = 1,
|
||||
RIGGLE_SAY_WINNER = 2,
|
||||
|
||||
QUEST_MASTER_ANGLER = 8193,
|
||||
QUEST_MASTER_ANGLER = 8193,
|
||||
|
||||
DATA_ANGLER_FINISHED = 1,
|
||||
EVENT_FISHING_TURN_INS = 90,
|
||||
EVENT_FISHING_POOLS = 15,
|
||||
|
||||
GAME_EVENT_FISHING = 62
|
||||
GOSSIP_EVENT_ACTIVE = 7614,
|
||||
GOSSIP_EVENT_OVER = 7714
|
||||
};
|
||||
|
||||
class npc_riggle_bassbait : public CreatureScript
|
||||
@@ -231,84 +242,95 @@ public:
|
||||
{
|
||||
npc_riggle_bassbaitAI(Creature* c) : ScriptedAI(c)
|
||||
{
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_RIGGLE_ANNOUNCE, 1000, 1, 0);
|
||||
finished = sWorld->getWorldState(GAME_EVENT_FISHING) == 1;
|
||||
startWarning = false;
|
||||
finishWarning = false;
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
bool finished;
|
||||
bool startWarning;
|
||||
bool finishWarning;
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_ANGLER_FINISHED)
|
||||
return (uint32)finished;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == DATA_ANGLER_FINISHED)
|
||||
m_uiTimer = 0;
|
||||
auto prevWinTime = sWorld->getWorldState(STV_FISHING_PREV_WIN_TIME);
|
||||
if (GameTime::GetGameTime().count() - prevWinTime > DAY)
|
||||
{
|
||||
finished = true;
|
||||
sWorld->setWorldState(GAME_EVENT_FISHING, 1);
|
||||
// reset all after 1 day
|
||||
sWorld->setWorldState(STV_FISHING_ANNOUNCE_EVENT_BEGIN, 1);
|
||||
sWorld->setWorldState(STV_FISHING_ANNOUNCE_POOLS_DESPAN, 0);
|
||||
sWorld->setWorldState(STV_FISHING_HAS_WINNER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 m_uiTimer;
|
||||
|
||||
void CheckTournamentState() const
|
||||
{
|
||||
if (sGameEventMgr->IsActiveEvent(EVENT_FISHING_TURN_INS) && !sWorld->getWorldState(STV_FISHING_HAS_WINNER))
|
||||
{
|
||||
if (!me->IsQuestGiver())
|
||||
{
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
}
|
||||
if (sWorld->getWorldState(STV_FISHING_ANNOUNCE_EVENT_BEGIN))
|
||||
{
|
||||
me->AI()->Talk(RIGGLE_SAY_START);
|
||||
sWorld->setWorldState(STV_FISHING_ANNOUNCE_EVENT_BEGIN, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (me->IsQuestGiver())
|
||||
{
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
}
|
||||
}
|
||||
if (sGameEventMgr->IsActiveEvent(EVENT_FISHING_POOLS))
|
||||
{
|
||||
// enable announcement: when pools despawn
|
||||
sWorld->setWorldState(STV_FISHING_ANNOUNCE_POOLS_DESPAN, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sWorld->getWorldState(STV_FISHING_ANNOUNCE_POOLS_DESPAN))
|
||||
{
|
||||
me->AI()->Talk(RIGGLE_SAY_POOLS_END);
|
||||
sWorld->setWorldState(STV_FISHING_ANNOUNCE_POOLS_DESPAN, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
if (m_uiTimer < diff)
|
||||
{
|
||||
case EVENT_RIGGLE_ANNOUNCE:
|
||||
{
|
||||
tm strdate = Acore::Time::TimeBreakdown();
|
||||
|
||||
if (!startWarning && strdate.tm_hour == 14 && strdate.tm_min == 0)
|
||||
{
|
||||
sCreatureTextMgr->SendChat(me, RIGGLE_SAY_START, 0, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, TEXT_RANGE_ZONE);
|
||||
startWarning = true;
|
||||
}
|
||||
|
||||
if (!finishWarning && strdate.tm_hour == 16 && strdate.tm_min == 0)
|
||||
{
|
||||
sCreatureTextMgr->SendChat(me, RIGGLE_SAY_END, 0, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, TEXT_RANGE_ZONE);
|
||||
finishWarning = true;
|
||||
// no one won - despawn
|
||||
if (!finished)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
events.RepeatEvent(1000);
|
||||
break;
|
||||
}
|
||||
CheckTournamentState();
|
||||
m_uiTimer = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uiTimer -= diff;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (!creature->AI()->GetData(DATA_ANGLER_FINISHED))
|
||||
if (creature->IsQuestGiver())
|
||||
{
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
}
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
if (sWorld->getWorldState(STV_FISHING_HAS_WINNER))
|
||||
{
|
||||
SendGossipMenuFor(player, GOSSIP_EVENT_OVER, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, GOSSIP_EVENT_ACTIVE, creature->GetGUID());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 /*opt*/) override
|
||||
{
|
||||
if (!creature->AI()->GetData(DATA_ANGLER_FINISHED) && quest->GetQuestId() == QUEST_MASTER_ANGLER)
|
||||
if (quest->GetQuestId() == QUEST_MASTER_ANGLER)
|
||||
{
|
||||
creature->AI()->DoAction(DATA_ANGLER_FINISHED);
|
||||
sCreatureTextMgr->SendChat(creature, RIGGLE_SAY_WINNER, player, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, TEXT_RANGE_ZONE);
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
creature->AI()->Talk(RIGGLE_SAY_WINNER, player);
|
||||
sWorld->setWorldState(STV_FISHING_PREV_WIN_TIME, GameTime::GetGameTime().count());
|
||||
sWorld->setWorldState(STV_FISHING_HAS_WINNER, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2542,6 +2564,64 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
enum ArcaniteDragonling
|
||||
{
|
||||
SPELL_FLAME_BUFFET = 9658,
|
||||
SPELL_FLAME_BREATH = 8873,
|
||||
|
||||
EVENT_FLAME_BUFFET = 1,
|
||||
EVENT_FLAME_BREATH = 2
|
||||
};
|
||||
|
||||
struct npc_arcanite_dragonling : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_arcanite_dragonling(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
creature->SetCanModifyStats(true);
|
||||
creature->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetPvP(true);
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FLAME_BUFFET, 4s);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREATH, 12s);
|
||||
}
|
||||
|
||||
void IsSummonedBy(Unit* summoner) override
|
||||
{
|
||||
me->GetMotionMaster()->MoveFollow(summoner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_FLAME_BUFFET:
|
||||
DoCastVictim(SPELL_FLAME_BUFFET);
|
||||
events.Repeat(12s);
|
||||
break;
|
||||
case EVENT_FLAME_BREATH:
|
||||
DoCastVictim(SPELL_FLAME_BREATH);
|
||||
events.Repeat(24s);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_npcs_special()
|
||||
{
|
||||
// Ours
|
||||
@@ -2568,4 +2648,5 @@ void AddSC_npcs_special()
|
||||
new npc_firework();
|
||||
new npc_spring_rabbit();
|
||||
new npc_stable_master();
|
||||
RegisterCreatureAI(npc_arcanite_dragonling);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user