Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2023-03-21 08:46:26 -06:00
committed by GitHub
55 changed files with 3356 additions and 948 deletions
@@ -674,8 +674,13 @@ void WheatyExceptionReport::GenerateExceptionReport(
// Initialize DbgHelp
if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
{
Log(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
ErrorMessage(GetLastError()));
Log(_T("\r\n"));
Log(_T("----\r\n"));
Log(_T("SYMBOL HANDLER ERROR (THIS IS NOT THE CRASH ERROR)\r\n\r\n"));
Log(_T("Couldn't initialize symbol handler for process when generating crash report\r\n"));
Log(_T("Error: %s\r\n"), ErrorMessage(GetLastError()));
Log(_T("THE BELOW CALL STACKS MIGHT HAVE MISSING OR INACCURATE FILE/FUNCTION NAMES\r\n\r\n"));
Log(_T("----\r\n"));
}
CONTEXT trashableContext = *pCtx;
+5
View File
@@ -211,6 +211,11 @@ inline bool isNumeric(char c)
return (c >= '0' && c <= '9');
}
inline bool IsEvenNumber(int32 n)
{
return n % 2 == 0;
}
inline bool isNumeric(char const* str)
{
for (char const* c = str; *c; ++c)
@@ -2481,6 +2481,12 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
if (!criteria)
continue;
if (!GetAchievement(criteria->referredAchievement))
{
LOG_DEBUG("server.loading", "Achievement {} referenced by criteria {} doesn't exist, criteria not loaded.", criteria->referredAchievement, criteria->ID);
continue;
}
_achievementCriteriasByType[criteria->requiredType].push_back(criteria);
_achievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria);
+5 -2
View File
@@ -917,10 +917,13 @@ void BfCapturePoint::SendChangePhase()
}
}
bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint)
bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint, TeamId team)
{
ASSERT(capturePoint);
//At first call using TEAM_NEUTRAL as a checker but never using it, after first call we reset the capturepoints to the new winner of the last WG war
if (team == TEAM_NEUTRAL)
team = m_team;
LOG_DEBUG("bg.battlefield", "Creating capture point {}", capturePoint->GetEntry());
m_capturePoint = capturePoint->GetGUID();
@@ -939,7 +942,7 @@ bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint)
m_neutralValuePct = goinfo->capturePoint.neutralPercent;
m_minValue = m_maxValue * goinfo->capturePoint.neutralPercent / 100;
m_capturePointEntry = capturePoint->GetEntry();
if (m_team == TEAM_ALLIANCE)
if (team == TEAM_ALLIANCE)
{
m_value = m_maxValue;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE;
+2 -1
View File
@@ -104,7 +104,8 @@ public:
virtual void ChangeTeam(TeamId /*oldTeam*/) {}
virtual void SendChangePhase();
bool SetCapturePointData(GameObject* capturePoint);
//Added team to reset capturepoints on sliders after warTime
bool SetCapturePointData(GameObject* capturePoint, TeamId team);
GameObject* GetCapturePointGo();
GameObject* GetCapturePointGo(WorldObject* obj);
@@ -102,7 +102,7 @@ bool BattlefieldWG::SetupBattlefield()
// When between games, the graveyard is controlled by the defending team
if (WGGraveYard[i].startcontrol == TEAM_NEUTRAL)
graveyard->Initialize(m_DefenderTeam, WGGraveYard[i].gyid);
graveyard->Initialize(WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SE || WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : m_DefenderTeam, WGGraveYard[i].gyid);
else
graveyard->Initialize(WGGraveYard[i].startcontrol, WGGraveYard[i].gyid);
@@ -114,7 +114,7 @@ bool BattlefieldWG::SetupBattlefield()
for (uint8 i = 0; i < WG_MAX_WORKSHOP; i++)
{
WGWorkshop* workshop = new WGWorkshop(this, i);
if (i < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
if (i == BATTLEFIELD_WG_WORKSHOP_SE || i == BATTLEFIELD_WG_WORKSHOP_SW)
workshop->GiveControlTo(GetAttackerTeam(), true);
else
workshop->GiveControlTo(GetDefenderTeam(), true);
@@ -262,6 +262,11 @@ void BattlefieldWG::OnBattleStart()
if (*itr)
(*itr)->UpdateGraveyardAndWorkshop();
// Set Sliders capture points data to his owners when battle start
for (BfCapturePointVector::const_iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
(*itr)->SetCapturePointData((*itr)->GetCapturePointGo(),
(*itr)->GetCapturePointGo()->GetEntry() == GO_WINTERGRASP_FACTORY_BANNER_SE || (*itr)->GetCapturePointGo()->GetEntry() == GO_WINTERGRASP_FACTORY_BANNER_SW ? GetAttackerTeam() : GetDefenderTeam());
for (uint8 team = 0; team < 2; ++team)
for (GuidUnorderedSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
{
@@ -375,7 +380,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
// Update all graveyard, control is to defender when no wartime
for (uint8 i = 0; i < BATTLEFIELD_WG_GY_HORDE; i++)
if (BfGraveyard* graveyard = GetGraveyardById(i))
graveyard->GiveControlTo(GetDefenderTeam());
graveyard->GiveControlTo(i == BATTLEFIELD_WG_GY_WORKSHOP_SE || i == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : GetDefenderTeam());
for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr)
(*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
@@ -396,7 +401,10 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
}
for (Workshop::const_iterator itr = WorkshopsList.begin(); itr != WorkshopsList.end(); ++itr)
{
(*itr)->GiveControlTo((*itr)->workshopId == BATTLEFIELD_WG_WORKSHOP_SE || (*itr)->workshopId == BATTLEFIELD_WG_WORKSHOP_SW ? GetAttackerTeam() : GetDefenderTeam(), true);
(*itr)->Save();
}
for (uint8 team = 0; team < 2; ++team)
{
@@ -689,9 +697,9 @@ void BattlefieldWG::OnGameObjectCreate(GameObject* go)
{
if (workshop->workshopId == workshopId)
{
WintergraspCapturePoint* capturePoint = new WintergraspCapturePoint(this, GetAttackerTeam());
capturePoint->SetCapturePointData(go);
WintergraspCapturePoint* capturePoint = new WintergraspCapturePoint(this, workshop->teamControl);
//Sending neutral team at start to set normal capture points by workshop->teamControl, TEAM_NEUTRAL is ignored at first call
capturePoint->SetCapturePointData(go, TEAM_NEUTRAL);
capturePoint->LinkToWorkshop(workshop);
AddCapturePoint(capturePoint);
break;
@@ -846,7 +854,7 @@ void BattlefieldWG::OnPlayerJoinWar(Player* player)
if (player->GetTeamId() == TEAM_HORDE)
player->TeleportTo(571, 5025.857422f, 3674.628906f, 362.737122f, 4.135169f);
else
player->TeleportTo(571, 5101.284f, 2186.564f, 373.549f, 3.812f);
player->TeleportTo(571, 5101.284f, 2186.564f, 365.549f, 3.812f);
}
if (player->GetTeamId() == GetAttackerTeam())
@@ -1474,6 +1474,17 @@ struct WGWorkshop
// Send warning message to all player to inform a faction attack to a workshop
// alliance / horde attacking a workshop
bf->SendWarning(teamControl ? WorkshopsData[workshopId].attackText : (WorkshopsData[workshopId].attackText + 2));
// Updating worldstate, update icon to neutral
state = BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT;
bf->SendUpdateWorldState(WorkshopsData[workshopId].worldstate, state);
// Found associate graveyard and update it
if (workshopId < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
if (bf->GetGraveyardById(workshopId))
bf->GetGraveyardById(workshopId)->GiveControlTo(team);
teamControl = team;
break;
}
case TEAM_ALLIANCE:
+12 -2
View File
@@ -927,7 +927,7 @@ void ArenaTeam::UpdateArenaPointsHelper(std::map<ObjectGuid, uint32>& playerPoin
}
}
void ArenaTeam::SaveToDB()
void ArenaTeam::SaveToDB(bool forceMemberSave)
{
if (!sScriptMgr->CanSaveToDB(this))
return;
@@ -949,6 +949,10 @@ void ArenaTeam::SaveToDB()
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
// Save the effort and go
if (itr->WeekGames == 0 && !forceMemberSave)
continue;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_MEMBER);
stmt->SetData(0, itr->PersonalRating);
stmt->SetData(1, itr->WeekGames);
@@ -970,8 +974,12 @@ void ArenaTeam::SaveToDB()
CharacterDatabase.CommitTransaction(trans);
}
void ArenaTeam::FinishWeek()
bool ArenaTeam::FinishWeek()
{
// No need to go further than this
if (Stats.WeekGames == 0)
return false;
// Reset team stats
Stats.WeekGames = 0;
Stats.WeekWins = 0;
@@ -982,6 +990,8 @@ void ArenaTeam::FinishWeek()
itr->WeekGames = 0;
itr->WeekWins = 0;
}
return true;
}
bool ArenaTeam::IsFighting() const
+2 -2
View File
@@ -182,7 +182,7 @@ public:
bool LoadArenaTeamFromDB(QueryResult arenaTeamDataResult);
bool LoadMembersFromDB(QueryResult arenaTeamMembersResult);
void LoadStatsFromDB(uint32 ArenaTeamId);
void SaveToDB();
void SaveToDB(bool forceMemberSave = false);
void BroadcastPacket(WorldPacket* packet);
void BroadcastEvent(ArenaTeamEvents event, ObjectGuid guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3);
@@ -206,7 +206,7 @@ public:
void UpdateArenaPointsHelper(std::map<ObjectGuid, uint32>& PlayerPoints);
void FinishWeek();
bool FinishWeek(); // returns true if arena team played this week
void FinishGame(int32 mod, const Map* bgMap);
void SetPreviousOpponents(uint32 arenaTeamId) { PreviousOpponents = arenaTeamId; }
@@ -239,8 +239,9 @@ void ArenaTeamMgr::DistributeArenaPoints()
{
if (ArenaTeam* at = titr->second)
{
at->FinishWeek();
at->SaveToDB();
if (at->FinishWeek())
at->SaveToDB(true);
at->NotifyStatsChanged();
}
}
+30 -5
View File
@@ -1863,7 +1863,9 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
return false;
if (!CanDetect(obj, ignoreStealth, !distanceCheck, checkAlert))
{
return false;
}
return true;
}
@@ -1890,7 +1892,9 @@ bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth, bool che
if (!ignoreStealth)
{
if (!seer->CanDetectInvisibilityOf(obj)) // xinef: added ignoreStealth, allow AoE spells to hit invisible targets!
{
return false;
}
if (!seer->CanDetectStealthOf(obj, checkAlert))
{
@@ -1923,11 +1927,32 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const
// It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
if (obj->ToUnit())
{
uint32 objMask = m_invisibility.GetFlags() & obj->m_invisibilityDetect.GetFlags();
// xinef: include invisible flags of caster in the mask, 2 invisible objects should be able to detect eachother
objMask |= m_invisibility.GetFlags() & obj->m_invisibility.GetFlags();
if (objMask != m_invisibility.GetFlags())
return false;
// Permanently invisible creatures should be able to engage non-invisible targets.
// ex. Skulking Witch (20882) / Greater Invisibility (16380)
bool isPermInvisibleCreature = false;
if (Creature const* baseObj = ToCreature())
{
auto auraEffects = baseObj->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY);
for (auto const effect : auraEffects)
{
if (SpellInfo const* spell = effect->GetSpellInfo())
{
if (spell->GetMaxDuration() == -1)
{
isPermInvisibleCreature = true;
}
}
}
}
if (!isPermInvisibleCreature)
{
uint32 objMask = m_invisibility.GetFlags() & obj->m_invisibilityDetect.GetFlags();
// xinef: include invisible flags of caster in the mask, 2 invisible objects should be able to detect eachother
objMask |= m_invisibility.GetFlags() & obj->m_invisibility.GetFlags();
if (objMask != m_invisibility.GetFlags())
return false;
}
}
for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
+1 -1
View File
@@ -15144,7 +15144,7 @@ void Player::ActivateSpec(uint8 spec)
for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
{
Aura* aura = *iter;
if (!HasActiveSpell(aura->GetId()) && !HasTalent(aura->GetId(), GetActiveSpec()))
if (!HasActiveSpell(aura->GetId()) && !HasTalent(aura->GetId(), GetActiveSpec()) && !aura->GetCastItemGUID())
{
aura->Remove();
iter = scAuras.begin();
+1 -1
View File
@@ -13490,7 +13490,7 @@ void Unit::Dismount()
if (Player* player = ToPlayer())
{
sScriptMgr->AnticheatSetUnderACKmount(player);
ToPlayer()->SetCanTeleport(true);
if (Pet* pPet = player->GetPet())
{
if (pPet->HasUnitFlag(UNIT_FLAG_STUNNED) && !pPet->HasUnitState(UNIT_STATE_STUNNED))
+18 -3
View File
@@ -18,6 +18,7 @@
#include "ObjectGridLoader.h"
#include "CellImpl.h"
#include "Corpse.h"
#include "GridNotifiers.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "DynamicObject.h"
@@ -97,13 +98,17 @@ void AddObjectHelper(CellCoord& cell, GameObjectMapType& m, uint32& count, Map*
}
template <class T>
void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<T>& m, uint32& count, Map* map)
void LoadHelper(CellGuidSet const& /*guid_set*/, CellCoord& /*cell*/, GridRefMgr<T>& /*m*/, uint32& /*count*/, Map* /*map*/)
{
}
template <>
void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<Creature>& m, uint32& count, Map* map)
{
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
T* obj = new T;
Creature* obj = new Creature();
ObjectGuid::LowType guid = *i_guid;
if (!obj->LoadFromDB(guid, map))
{
delete obj;
@@ -111,6 +116,16 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<T>& m,
}
AddObjectHelper(cell, m, count, map, obj);
if (!obj->IsMoveInLineOfSightDisabled() && obj->GetDefaultMovementType() == IDLE_MOTION_TYPE && !obj->isNeedNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION))
{
if (obj->IsAlive() && !obj->HasUnitState(UNIT_STATE_SIGHTLESS) && obj->HasReactState(REACT_AGGRESSIVE) && !obj->IsImmuneToNPC())
{
// call MoveInLineOfSight for nearby grid creatures
Acore::AIRelocationNotifier notifier(*obj);
Cell::VisitGridObjects(obj, notifier, 60.f);
}
}
}
}
+7 -6
View File
@@ -237,6 +237,13 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
// handle empty bag before CanBeTraded, since that func already has that check
if (item->IsNotEmptyBag())
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS);
return;
}
if (!item->CanBeTraded(true))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
@@ -261,12 +268,6 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
if (item->IsNotEmptyBag())
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS);
return;
}
if (!sScriptMgr->CanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR);
+5 -1
View File
@@ -355,8 +355,12 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
sessionGuard.lock();
LogOpcodeText(opcode, sessionGuard);
if (_worldSession)
{
_worldSession->ResetTimeOutTime(true);
return ReadDataHandlerResult::Ok;
return ReadDataHandlerResult::Ok;
}
LOG_ERROR("network", "WorldSocket::ReadDataHandler: client {} sent CMSG_KEEP_ALIVE without being authenticated", GetRemoteIpAddress().to_string());
return ReadDataHandlerResult::Error;
case CMSG_TIME_SYNC_RESP:
packetToQueue = new WorldPacket(std::move(packet), GameTime::Now());
break;
+2 -1
View File
@@ -6328,7 +6328,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// chance for fail at lockpicking attempt
// second check prevent fail at rechecks
if (skillId != SKILL_NONE && (!m_selfContainer || ((*m_selfContainer) != this)))
// herbalism and mining cannot fail as of patch 3.1.0
if (skillId != SKILL_NONE && skillId != SKILL_HERBALISM && skillId != SKILL_MINING && (!m_selfContainer || ((*m_selfContainer) != this)))
{
// chance for failure in orange lockpick
if (skillId == SKILL_LOCKPICKING && reqSkillValue > irand(skillValue - 25, skillValue + 37))
@@ -4483,6 +4483,18 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL;
});
// Buffeting Winds of Susurrus
ApplySpellFix({ 32474 }, [](SpellInfo* spellInfo)
{
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(556); // 28 seconds
});
// Quest - Healing Salve
ApplySpellFix({ 29314 }, [](SpellInfo* spellInfo)
{
spellInfo->CastTimeEntry = sSpellCastTimesStore.LookupEntry(1); // 0s
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
+2
View File
@@ -1193,6 +1193,8 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
return spellId == 56618;
else if (team == TEAM_ALLIANCE)
return spellId == 56617;
else
return false;
break;
}
// Hellscream's Warsong
@@ -155,6 +155,9 @@ public:
if (data == SPECIAL)
encounter = SPECIAL;
break;
case DATA_HORSEMAN_EVENT:
encounter = data;
break;
}
}
@@ -177,6 +180,8 @@ public:
{
if (type == TYPE_MOGRAINE_AND_WHITE_EVENT)
return encounter;
else if (type == DATA_HORSEMAN_EVENT)
return encounter;
return 0;
}
private:
+73 -32
View File
@@ -24,6 +24,7 @@
#include "PassiveAI.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
@@ -981,14 +982,29 @@ enum headlessHorseman
EVENT_HORSEMAN_CONFLAGRATION = 5,
EVENT_SUMMON_PUMPKIN = 6,
EVENT_HORSEMAN_FOLLOW = 7,
// Headless Horseman
TALK_ENTRANCE = 0,
TALK_REJOINED = 1,
TALK_CONFLAGRATION = 2,
TALK_SPROUTING_PUMPKINS = 3,
TALK_DEATH = 4,
TALK_PLAYER_DEATH = 5,
// Head of the Horseman
TALK_LAUGH = 0,
TALK_LOST_HEAD = 1,
// Player
TALK_PLAYER_RISE = 22695,
TALK_PLAYER_TIME_IS_NIGH = 22696,
TALK_PLAYER_FELT_DEATH = 22720,
TALK_PLAYER_KNOW_DEMISE = 22721,
};
enum hhSounds
enum hhMisc
{
SOUND_AGGRO = 11961,
SOUND_SLAY = 11962,
SOUND_SPROUT = 11963,
SOUND_DEATH = 11964,
DATA_HORSEMAN_EVENT = 5,
};
struct boss_headless_horseman : public ScriptedAI
@@ -1006,8 +1022,7 @@ struct boss_headless_horseman : public ScriptedAI
void JustDied(Unit* /*killer*/) override
{
summons.DespawnAll();
me->Say("This end have I reached before. What new adventure lies in store?", LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_DEATH);
Talk(TALK_DEATH);
std::list<Creature*> unitList;
me->GetCreaturesWithEntryInRange(unitList, 100.0f, NPC_PUMPKIN_FIEND);
for (std::list<Creature*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
@@ -1016,12 +1031,14 @@ struct boss_headless_horseman : public ScriptedAI
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (!players.IsEmpty() && players.begin()->GetSource() && players.begin()->GetSource()->GetGroup())
sLFGMgr->FinishDungeon(players.begin()->GetSource()->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_HEADLESS_HORSEMAN, me->FindMap());
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(DATA_HORSEMAN_EVENT, DONE);
}
void KilledUnit(Unit* /*who*/) override
{
me->Yell("Your body lies beaten, battered and broken. Let my curse be your own, fate has spoken.", LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_SLAY);
Talk(TALK_PLAYER_DEATH);
}
void DoAction(int32 param) override
@@ -1052,7 +1069,7 @@ struct boss_headless_horseman : public ScriptedAI
events.CancelEvent(EVENT_HORSEMAN_WHIRLWIND);
events.CancelEvent(EVENT_HORSEMAN_CONFLAGRATION);
events.CancelEvent(EVENT_SUMMON_PUMPKIN);
me->Yell("Here's my body, fit and pure! Now, your blackened souls I'll cure!", LANG_UNIVERSAL);
Talk(TALK_REJOINED);
if (phase == 1)
events.ScheduleEvent(EVENT_HORSEMAN_CONFLAGRATION, 6s);
@@ -1131,6 +1148,14 @@ struct boss_headless_horseman : public ScriptedAI
me->SetSpeed(MOVE_WALK, 5.0f, true);
}
void JustReachedHome() override
{
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(DATA_HORSEMAN_EVENT, FAIL);
me->DespawnOrUnsummon();
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
@@ -1152,23 +1177,22 @@ struct boss_headless_horseman : public ScriptedAI
switch (talkCount)
{
case 1:
player->Say("Horseman rise...", LANG_UNIVERSAL);
player->Say(TALK_PLAYER_RISE);
break;
case 2:
player->Say("Your time is nigh...", LANG_UNIVERSAL);
player->Say(TALK_PLAYER_TIME_IS_NIGH);
if (Creature* trigger = me->SummonTrigger(1765.28f, 1347.46f, 17.5514f, 0.0f, 15 * IN_MILLISECONDS))
trigger->CastSpell(trigger, SPELL_EARTH_EXPLOSION, true);
break;
case 3:
me->GetMotionMaster()->MovePath(236820, false);
me->CastSpell(me, SPELL_SHAKE_CAMERA_SMALL, true);
player->Say("You felt death once...", LANG_UNIVERSAL);
me->Say("It is over, your search is done. Let fate choose now, the righteous one.", LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_AGGRO);
player->Say(TALK_PLAYER_FELT_DEATH);
Talk(TALK_ENTRANCE);
break;
case 4:
me->CastSpell(me, SPELL_SHAKE_CAMERA_MEDIUM, true);
player->Say("Now, know demise!", LANG_UNIVERSAL);
player->Say(TALK_PLAYER_KNOW_DEMISE);
talkCount = 0;
return; // pop and return, skip repeat
}
@@ -1220,7 +1244,7 @@ struct boss_headless_horseman : public ScriptedAI
{
me->CastSpell(target, SPELL_HORSEMAN_CONFLAGRATION, false);
target->CastSpell(target, SPELL_HORSEMAN_CONFLAGRATION_SOUND, true);
me->Say("Harken, cur! Tis you I spurn! Now feel... the burn!", LANG_UNIVERSAL, target);
Talk(TALK_CONFLAGRATION);
}
events.RepeatEvent(12500);
@@ -1236,8 +1260,7 @@ struct boss_headless_horseman : public ScriptedAI
}
else
{
me->Say("Soldiers arise, stand and fight! Bring victory at last to this fallen knight!", LANG_UNIVERSAL);
me->PlayDirectSound(SOUND_SPROUT);
Talk(TALK_SPROUTING_PUMPKINS);
events.RepeatEvent(15000);
talkCount = 0;
}
@@ -1334,6 +1357,8 @@ struct boss_headless_horseman_head : public ScriptedAI
me->CastSpell(me, SPELL_THROW_HEAD_BACK, true);
if (Unit* owner = GetOwner())
owner->RemoveAura(SPELL_HORSEMAN_IMMUNITY);
Talk(TALK_LOST_HEAD);
}
}
@@ -1351,20 +1376,8 @@ struct boss_headless_horseman_head : public ScriptedAI
if (timer >= 30000)
{
timer = urand(0, 15000);
uint32 sound = 11965;
switch (urand(0, 2))
{
case 1:
sound = 11975;
break;
case 2:
sound = 11976;
break;
}
me->CastSpell(me, SPELL_HORSEMAN_SPEAKS, true);
me->TextEmote("Headless Horseman laughs");
me->PlayDirectSound(sound);
Talk(TALK_LAUGH);
}
}
};
@@ -1450,6 +1463,33 @@ public:
}
};
class go_pumpkin_shrine : public GameObjectScript
{
public:
go_pumpkin_shrine() : GameObjectScript("go_pumpkin_shrine") {}
bool OnGossipSelect(Player* player, GameObject* go, uint32 /*sender*/, uint32 /*action*/) override
{
CloseGossipMenuFor(player);
if (InstanceScript* instance = go->GetInstanceScript())
{
if (instance->GetData(DATA_HORSEMAN_EVENT) == IN_PROGRESS || instance->GetData(DATA_HORSEMAN_EVENT) == DONE)
return true;
if (player->FindNearestCreature(NPC_HEADLESS_HORSEMAN_MOUNTED, 100.0f))
return true;
if (Creature* horseman = go->SummonCreature(NPC_HEADLESS_HORSEMAN_MOUNTED, 1754.00f, 1346.00f, 17.50f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0))
horseman->CastSpell(player, SPELL_SUMMONING_RHYME_TARGET, true);
instance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS);
}
return true;
}
};
void AddSC_event_hallows_end_scripts()
{
// Spells
@@ -1475,6 +1515,7 @@ void AddSC_event_hallows_end_scripts()
// Headless Horseman
new go_loosely_turned_soil();
new go_pumpkin_shrine();
RegisterCreatureAI(boss_headless_horseman);
RegisterCreatureAI(boss_headless_horseman_head);
RegisterCreatureAI(boss_headless_horseman_pumpkin);
@@ -203,7 +203,7 @@ public:
events.ScheduleEvent(EVENT_SPELL_HAMMER, 30000);
break;
case EVENT_SPELL_HOLY_SHIELD:
me->CastSpell(me, SPELL_CLEANSE, false);
me->CastSpell(me, SPELL_HOLY_SHIELD, false);
events.ScheduleEvent(SPELL_HOLY_SHIELD, 30000);
break;
case EVENT_SPELL_CONSECRATION:
@@ -130,7 +130,7 @@ public:
case NPC_INFINITE_EXECUTIONER_2:
case NPC_INFINITE_VANQUISHER:
case NPC_INFINITE_VANQUISHER_2:
creature->DespawnOrUnsummon();
creature->DespawnOrUnsummon(1);
break;
default:
break;
@@ -3051,95 +3051,110 @@ public:
}
};
class npc_icc_spire_frostwyrm : public CreatureScript
enum SpireFrostwyrm
{
public:
npc_icc_spire_frostwyrm() : CreatureScript("npc_icc_spire_frostwyrm") { }
SPELL_BLIZZARD = 70362,
SPELL_CLEAVE = 70361,
SPELL_FROSTBREATH = 70116,
struct npc_icc_spire_frostwyrmAI : public ScriptedAI
HORDE_AREATRIGGER = 5630
};
struct npc_icc_spire_frostwyrm : public ScriptedAI
{
npc_icc_spire_frostwyrm(Creature* creature) : ScriptedAI(creature)
{
npc_icc_spire_frostwyrmAI(Creature* creature) : ScriptedAI(creature)
_scheduler.SetValidator([this]
{
me->SetCanFly(true);
me->SetDisableGravity(true);
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
EventMap events;
void Reset() override
{
events.Reset();
events.ScheduleEvent(1, 15s, 25s); // blizzard
events.ScheduleEvent(2, 5s); // cleave
events.ScheduleEvent(3, 10s, 15s); // frost breath
}
void DoAction(int32 a) override
{
if (a != -1)
return;
if (me->GetHomePosition().GetPositionZ() < 225.0f)
return;
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), 191.26f, me->GetOrientation());
me->GetMotionMaster()->MoveLand(1, me->GetPositionX(), me->GetPositionY(), 191.26f, 2.5f * 7.0f);
Talk(0);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == EFFECT_MOTION_TYPE && id == 1)
{
me->SetCanFly(false);
me->SetDisableGravity(false);
if (Player* p = SelectTargetFromPlayerList(100.0f))
{
Talk(p->GetTeamId() == TEAM_HORDE ? 1 : 2);
AttackStart(p);
}
}
}
bool CanAIAttack(Unit const* target) const override
{
return me->GetPositionZ() < 225.0f && me->GetHomePosition().GetExactDist(target) < 200.0f;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case 1:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
me->CastSpell(target, 70362, false);
events.Repeat(25s, 35s);
break;
case 2:
me->CastSpell(me->GetVictim(), 70361, false);
events.Repeat(5s);
break;
case 3:
me->CastSpell(me->GetVictim(), 70116, false);
events.Repeat(10s, 15s);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetIcecrownCitadelAI<npc_icc_spire_frostwyrmAI>(creature);
_canResetFlyingEffects = true;
}
void Reset() override
{
if (!_canResetFlyingEffects)
{
me->SetCanFly(false);
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
}
}
void JustEngagedWith(Unit* /*victim*/) override
{
_scheduler.Schedule(15s, 25s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_BLIZZARD);
context.Repeat(25s, 35s);
}).Schedule(5s, [this](TaskContext context)
{
DoCastVictim(SPELL_CLEAVE);
context.Repeat();
}).Schedule(10s, 15s, [this](TaskContext context)
{
DoCastVictim(SPELL_FROSTBREATH);
context.Repeat();
});
_canResetFlyingEffects = false;
}
void DoAction(int32 action) override
{
const Position posHordeMove = { -433.667084f, 2080.347412f, 191.253860f, 3.825093f };
const Position posAllianceMove = { -433.589508f, 2344.564697f, 191.253616f, 2.543328f };
bool hordeSide = action == HORDE_AREATRIGGER || action == HORDE_AREATRIGGER + 1;
Position landingPosition = hordeSide ? posHordeMove : posAllianceMove;
me->GetMotionMaster()->MovePoint(1, landingPosition);
me->SetHomePosition(landingPosition);
Talk(0);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == EFFECT_MOTION_TYPE && id == 1)
{
me->SetCanFly(false);
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
_canResetFlyingEffects = false;
}
}
void JustReachedHome() override
{
ScriptedAI::JustReachedHome();
if (!_canResetFlyingEffects)
{
me->SetCanFly(false);
me->SetDisableGravity(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
}
}
bool CanAIAttack(Unit const* target) const override
{
return me->GetPositionZ() < 225.0f && me->GetHomePosition().GetExactDist(target) < 200.0f;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff,
std::bind(&ScriptedAI::DoMeleeAttackIfReady, this));
}
private:
TaskScheduler _scheduler;
bool _canResetFlyingEffects;
};
#define VENGEFUL_WP_COUNT 6
@@ -3746,16 +3761,27 @@ public:
}
};
class at_icc_spire_frostwyrm : public AreaTriggerScript
class at_icc_spire_frostwyrm : public OnlyOnceAreaTriggerScript
{
public:
at_icc_spire_frostwyrm() : AreaTriggerScript("at_icc_spire_frostwyrm") { }
at_icc_spire_frostwyrm() : OnlyOnceAreaTriggerScript("at_icc_spire_frostwyrm") { }
bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override
bool _OnTrigger(Player* player, AreaTrigger const* areaTrigger) override
{
if (Creature* frostwyrm = player->FindNearestCreature(NPC_SPIRE_FROSTWYRM, 150.0f, true))
if (frostwyrm->GetPositionZ() > 250.0f && frostwyrm->AI())
frostwyrm->AI()->DoAction(-1);
if (player->GetInstanceScript()->GetPersistentData(DATA_SPIRE_FROSTWYRM) != DONE)
{
player->GetInstanceScript()->StorePersistentData(DATA_SPIRE_FROSTWYRM, DONE);
const Position posHordeWyrm = { -375.538879f, 2120.774658f, 242.256775f, 3.714352f };
const Position posAllianceWyrm = { -361.154358f, 2305.821289f, 244.771713f, 2.704335f };
bool hordeSide = areaTrigger->entry == HORDE_AREATRIGGER || areaTrigger->entry == HORDE_AREATRIGGER + 1;
if (Creature* frostwyrm = player->SummonCreature(NPC_SPIRE_FROSTWYRM, hordeSide ? posHordeWyrm : posAllianceWyrm))
{
frostwyrm->AI()->DoAction(areaTrigger->entry);
}
}
return true;
}
};
@@ -3803,7 +3829,7 @@ void AddSC_icecrown_citadel()
new npc_icc_skybreaker_luminary();
new npc_icc_valkyr_herald();
new npc_icc_severed_essence();
new npc_icc_spire_frostwyrm();
RegisterIcecrownCitadelCreatureAI(npc_icc_spire_frostwyrm);
new npc_icc_vengeful_fleshreaper();
new npc_icc_buff_switcher();
new npc_icc_nerubar_broodkeeper();
@@ -148,6 +148,12 @@ enum DataTypes
DATA_BPC_TRASH_DIED = 300,
};
enum PersistentData
{
DATA_SPIRE_FROSTWYRM = 0,
MAX_DATA_INDEXES
};
enum CreaturesIds
{
// At Light's Hammer
@@ -199,6 +199,7 @@ public:
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTERS);
SetPersistentDataCount(MAX_DATA_INDEXES);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
TeamIdInInstance = TEAM_NEUTRAL;
@@ -34,81 +34,54 @@ enum Spells
SPELL_SHADOW_POWER = 35322
};
enum Events
struct boss_gatewatcher_gyrokill : public BossAI
{
EVENT_STREAM_OF_MACHINE_FLUID = 1,
EVENT_SAW_BLADE = 2,
EVENT_SHADOW_POWER = 3
};
class boss_gatewatcher_gyrokill : public CreatureScript
{
public:
boss_gatewatcher_gyrokill() : CreatureScript("boss_gatewatcher_gyrokill") { }
struct boss_gatewatcher_gyrokillAI : public BossAI
boss_gatewatcher_gyrokill(Creature* creature) : BossAI(creature, DATA_GATEWATCHER_GYROKILL)
{
boss_gatewatcher_gyrokillAI(Creature* creature) : BossAI(creature, DATA_GATEWATCHER_GYROKILL) { }
void JustDied(Unit* /*killer*/) override
scheduler.SetValidator([this]
{
_JustDied();
Talk(SAY_DEATH);
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
events.ScheduleEvent(EVENT_STREAM_OF_MACHINE_FLUID, 10000);
events.ScheduleEvent(EVENT_SAW_BLADE, 20000);
events.ScheduleEvent(EVENT_SHADOW_POWER, 30000);
Talk(SAY_AGGRO);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_STREAM_OF_MACHINE_FLUID:
me->CastSpell(me->GetVictim(), SPELL_STREAM_OF_MACHINE_FLUID, false);
events.ScheduleEvent(EVENT_STREAM_OF_MACHINE_FLUID, urand(12000, 14000));
break;
case EVENT_SAW_BLADE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f))
me->CastSpell(target, SPELL_SAW_BLADE, false);
Talk(SAY_SAW_BLADE);
events.ScheduleEvent(EVENT_SAW_BLADE, 25000);
break;
case EVENT_SHADOW_POWER:
me->CastSpell(me, SPELL_SHADOW_POWER, false);
events.ScheduleEvent(EVENT_SAW_BLADE, 25000);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustDied(Unit* /*killer*/) override
{
return GetMechanarAI<boss_gatewatcher_gyrokillAI>(creature);
_JustDied();
Talk(SAY_DEATH);
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
scheduler.Schedule(10s, [this](TaskContext context)
{
DoCastVictim(SPELL_STREAM_OF_MACHINE_FLUID);
context.Repeat(12s, 14s);
}).Schedule(20s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_SAW_BLADE, 0, 50.0f);
Talk(SAY_SAW_BLADE);
context.Repeat(25s);
}).Schedule(30s, [this](TaskContext context)
{
me->CastSpell(me, SPELL_SHADOW_POWER, false);
context.Repeat(25s);
});
Talk(SAY_AGGRO);
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
};
void AddSC_boss_gatewatcher_gyrokill()
{
new boss_gatewatcher_gyrokill();
RegisterMechanarCreatureAI(boss_gatewatcher_gyrokill);
}
@@ -35,83 +35,55 @@ enum Spells
SPELL_STREAM_OF_MACHINE_FLUID = 35311
};
enum Events
struct boss_gatewatcher_iron_hand : public BossAI
{
EVENT_STREAM_OF_MACHINE_FLUID = 1,
EVENT_JACKHAMMER = 2,
EVENT_SHADOW_POWER = 3
};
class boss_gatewatcher_iron_hand : public CreatureScript
{
public:
boss_gatewatcher_iron_hand(): CreatureScript("boss_gatewatcher_iron_hand") { }
struct boss_gatewatcher_iron_handAI : public BossAI
boss_gatewatcher_iron_hand(Creature* creature) : BossAI(creature, DATA_GATEWATCHER_IRON_HAND)
{
boss_gatewatcher_iron_handAI(Creature* creature) : BossAI(creature, DATA_GATEWATCHER_IRON_HAND) { }
void JustEngagedWith(Unit* /*who*/) override
scheduler.SetValidator([this]
{
_JustEngagedWith();
events.ScheduleEvent(EVENT_STREAM_OF_MACHINE_FLUID, 15000);
events.ScheduleEvent(EVENT_JACKHAMMER, 35000);
events.ScheduleEvent(EVENT_SHADOW_POWER, 25000);
Talk(SAY_AGGRO);
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_STREAM_OF_MACHINE_FLUID:
me->CastSpell(me->GetVictim(), SPELL_STREAM_OF_MACHINE_FLUID, false);
events.ScheduleEvent(EVENT_STREAM_OF_MACHINE_FLUID, 20000);
break;
case EVENT_JACKHAMMER:
Talk(EMOTE_HAMMER);
Talk(SAY_HAMMER);
me->CastSpell(me, SPELL_JACKHAMMER, false);
events.ScheduleEvent(EVENT_JACKHAMMER, 40000);
break;
case EVENT_SHADOW_POWER:
me->CastSpell(me, SPELL_SHADOW_POWER, false);
events.ScheduleEvent(EVENT_SHADOW_POWER, 25000);
break;
default:
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustEngagedWith(Unit* /*who*/) override
{
return GetMechanarAI<boss_gatewatcher_iron_handAI>(creature);
_JustEngagedWith();
scheduler.Schedule(15s, [this](TaskContext context)
{
DoCastVictim(SPELL_STREAM_OF_MACHINE_FLUID);
context.Repeat(20s);
}).Schedule(35s, [this](TaskContext context)
{
Talk(EMOTE_HAMMER);
Talk(SAY_HAMMER);
DoCastSelf(SPELL_JACKHAMMER);
context.Repeat(40s);
}).Schedule(25s, [this](TaskContext context)
{
DoCastSelf(SPELL_SHADOW_POWER);
context.Repeat(25s);
});
Talk(SAY_AGGRO);
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
};
void AddSC_boss_gatewatcher_iron_hand()
{
new boss_gatewatcher_iron_hand();
RegisterMechanarCreatureAI(boss_gatewatcher_iron_hand);
}
@@ -27,16 +27,23 @@ enum Spells
SPELL_REFLECTIVE_MAGIC_SHIELD = 35158,
SPELL_REFLECTIVE_DAMAGE_SHIELD = 35159,
SPELL_POLARITY_SHIFT = 39096,
SPELL_BERSERK = 26662
SPELL_BERSERK = 26662,
SPELL_NETHER_CHARGE_PASSIVE = 35150,
SPELL_SUMMON_NETHER_CHARGE_NE = 35153,
SPELL_SUMMON_NETHER_CHARGE_NW = 35904,
SPELL_SUMMON_NETHER_CHARGE_SE = 35905,
SPELL_SUMMON_NETHER_CHARGE_SW = 35906,
};
enum Yells
{
YELL_AGGRO = 0,
YELL_REFLECTIVE_MAGIC_SHIELD = 1,
YELL_REFLECTIVE_DAMAGE_SHIELD = 2,
YELL_KILL = 3,
YELL_DEATH = 4
SAY_AGGRO = 0,
SAY_REFLECTIVE_MAGIC_SHIELD = 1,
SAY_REFLECTIVE_DAMAGE_SHIELD = 2,
SAY_KILL = 3,
SAY_DEATH = 4
};
enum Creatures
@@ -44,101 +51,84 @@ enum Creatures
NPC_NETHER_CHARGE = 20405
};
enum Events
struct boss_mechano_lord_capacitus : public BossAI
{
EVENT_HEADCRACK = 1,
EVENT_REFLECTIVE_DAMAGE_SHIELD = 2,
EVENT_REFLECTIVE_MAGIE_SHIELD = 3,
EVENT_POSITIVE_SHIFT = 4,
EVENT_SUMMON_NETHER_CHARGE = 5,
EVENT_BERSERK = 6
};
class boss_mechano_lord_capacitus : public CreatureScript
{
public:
boss_mechano_lord_capacitus() : CreatureScript("boss_mechano_lord_capacitus") { }
struct boss_mechano_lord_capacitusAI : public BossAI
boss_mechano_lord_capacitus(Creature* creature) : BossAI(creature, DATA_MECHANOLORD_CAPACITUS)
{
boss_mechano_lord_capacitusAI(Creature* creature) : BossAI(creature, DATA_MECHANOLORD_CAPACITUS) { }
void JustEngagedWith(Unit* /*who*/) override
scheduler.SetValidator([this]
{
_JustEngagedWith();
Talk(YELL_AGGRO);
events.ScheduleEvent(EVENT_HEADCRACK, 6000);
events.ScheduleEvent(EVENT_SUMMON_NETHER_CHARGE, 10000);
events.ScheduleEvent(EVENT_BERSERK, 180000);
events.ScheduleEvent(IsHeroic() ? EVENT_POSITIVE_SHIFT : EVENT_REFLECTIVE_DAMAGE_SHIELD, 15000);
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void KilledUnit(Unit* victim) override
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
Talk(SAY_AGGRO);
scheduler.Schedule(6s, [this](TaskContext context)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(YELL_KILL);
}
void JustDied(Unit* /*killer*/) override
DoCastVictim(SPELL_HEADCRACK);
context.Repeat(20s);
}).Schedule(10s, [this](TaskContext context)
{
_JustDied();
Talk(YELL_DEATH);
}
void JustSummoned(Creature* summon) override
uint32 spellId = RAND(SPELL_SUMMON_NETHER_CHARGE_NE,
SPELL_SUMMON_NETHER_CHARGE_NW,
SPELL_SUMMON_NETHER_CHARGE_SE,
SPELL_SUMMON_NETHER_CHARGE_SW);
DoCastAOE(spellId);
IsHeroic() ? context.Repeat(2s, 5s) : context.Repeat(9s, 11s);
}).Schedule(3min, [this](TaskContext /*context*/)
{
summons.Summon(summon);
summon->GetMotionMaster()->MoveRandom(30.0f);
}
DoCastSelf(SPELL_BERSERK, true);
});
void UpdateAI(uint32 diff) override
if (IsHeroic())
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
scheduler.Schedule(15s, [this](TaskContext context)
{
case EVENT_HEADCRACK:
me->CastSpell(me->GetVictim(), SPELL_HEADCRACK, false);
events.ScheduleEvent(EVENT_HEADCRACK, 20000);
break;
case EVENT_REFLECTIVE_DAMAGE_SHIELD:
Talk(YELL_REFLECTIVE_DAMAGE_SHIELD);
me->CastSpell(me, SPELL_REFLECTIVE_DAMAGE_SHIELD, false);
events.ScheduleEvent(EVENT_REFLECTIVE_MAGIE_SHIELD, 20000);
break;
case EVENT_REFLECTIVE_MAGIE_SHIELD:
Talk(YELL_REFLECTIVE_MAGIC_SHIELD);
me->CastSpell(me, SPELL_REFLECTIVE_MAGIC_SHIELD, false);
events.ScheduleEvent(EVENT_REFLECTIVE_DAMAGE_SHIELD, 20000);
break;
case EVENT_SUMMON_NETHER_CHARGE:
{
Position pos = me->GetRandomNearPosition(8.0f);
me->SummonCreature(NPC_NETHER_CHARGE, pos, TEMPSUMMON_TIMED_DESPAWN, 18000);
events.ScheduleEvent(EVENT_SUMMON_NETHER_CHARGE, 5000);
break;
}
case EVENT_POSITIVE_SHIFT:
me->CastSpell(me, SPELL_POLARITY_SHIFT, true);
events.ScheduleEvent(EVENT_POSITIVE_SHIFT, 30000);
break;
case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true);
break;
}
DoMeleeAttackIfReady();
DoCastSelf(SPELL_POLARITY_SHIFT, true);
context.Repeat(30s);
});
}
};
else
{
scheduler.Schedule(15s, [this](TaskContext context)
{
if (IsEvenNumber(context.GetRepeatCounter()))
{
Talk(SAY_REFLECTIVE_DAMAGE_SHIELD);
DoCastSelf(SPELL_REFLECTIVE_DAMAGE_SHIELD);
}
else
{
Talk(SAY_REFLECTIVE_MAGIC_SHIELD);
DoCastSelf(SPELL_REFLECTIVE_MAGIC_SHIELD);
}
CreatureAI* GetAI(Creature* creature) const override
context.Repeat(20s);
});
}
}
void KilledUnit(Unit* victim) override
{
return GetMechanarAI<boss_mechano_lord_capacitusAI>(creature);
if (victim->IsPlayer())
{
Talk(SAY_KILL);
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
summon->GetMotionMaster()->MoveRandom(30.0f);
}
};
@@ -153,84 +143,62 @@ enum polarityShift
SPELL_NEGATIVE_CHARGE = 39093
};
class spell_capacitus_polarity_charge : public SpellScriptLoader
class spell_capacitus_polarity_charge : public SpellScript
{
public:
spell_capacitus_polarity_charge() : SpellScriptLoader("spell_capacitus_polarity_charge") { }
PrepareSpellScript(spell_capacitus_polarity_charge);
class spell_capacitus_polarity_charge_SpellScript : public SpellScript
void HandleTargets(std::list<WorldObject*>& targetList)
{
PrepareSpellScript(spell_capacitus_polarity_charge_SpellScript);
uint8 count = 0;
for (std::list<WorldObject*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit)
if ((*ihit)->GetGUID() != GetCaster()->GetGUID())
if (Player* target = (*ihit)->ToPlayer())
if (target->HasAura(GetTriggeringSpell()->Id))
++count;
void HandleTargets(std::list<WorldObject*>& targetList)
if (count)
{
uint8 count = 0;
for (std::list<WorldObject*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit)
if ((*ihit)->GetGUID() != GetCaster()->GetGUID())
if (Player* target = (*ihit)->ToPlayer())
if (target->HasAura(GetTriggeringSpell()->Id))
++count;
if (count)
{
uint32 spellId = GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE ? SPELL_POSITIVE_CHARGE_STACK : SPELL_NEGATIVE_CHARGE_STACK;
GetCaster()->SetAuraStack(spellId, GetCaster(), count);
}
uint32 spellId = GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE ? SPELL_POSITIVE_CHARGE_STACK : SPELL_NEGATIVE_CHARGE_STACK;
GetCaster()->SetAuraStack(spellId, GetCaster(), count);
}
}
void HandleDamage(SpellEffIndex /*effIndex*/)
{
if (!GetTriggeringSpell())
return;
Unit* target = GetHitUnit();
if (target->HasAura(GetTriggeringSpell()->Id))
SetHitDamage(0);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_capacitus_polarity_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_capacitus_polarity_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
}
};
SpellScript* GetSpellScript() const override
void HandleDamage(SpellEffIndex /*effIndex*/)
{
return new spell_capacitus_polarity_charge_SpellScript();
if (!GetTriggeringSpell())
return;
Unit* target = GetHitUnit();
if (target->HasAura(GetTriggeringSpell()->Id))
SetHitDamage(0);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_capacitus_polarity_charge::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_capacitus_polarity_charge::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
}
};
class spell_capacitus_polarity_shift : public SpellScriptLoader
class spell_capacitus_polarity_shift : public SpellScript
{
public:
spell_capacitus_polarity_shift() : SpellScriptLoader("spell_capacitus_polarity_shift") { }
PrepareSpellScript(spell_capacitus_polarity_shift);
class spell_capacitus_polarity_shift_SpellScript : public SpellScript
void HandleDummy(SpellEffIndex /*effIndex*/)
{
PrepareSpellScript(spell_capacitus_polarity_shift_SpellScript);
if (Unit* target = GetHitUnit())
target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, nullptr, nullptr, GetCaster()->GetGUID());
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, nullptr, nullptr, GetCaster()->GetGUID());
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_capacitus_polarity_shift_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
void Register() override
{
return new spell_capacitus_polarity_shift_SpellScript();
OnEffectHitTarget += SpellEffectFn(spell_capacitus_polarity_shift::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
void AddSC_boss_mechano_lord_capacitus()
{
new boss_mechano_lord_capacitus();
new spell_capacitus_polarity_charge();
new spell_capacitus_polarity_shift();
RegisterMechanarCreatureAI(boss_mechano_lord_capacitus);
RegisterSpellScript(spell_capacitus_polarity_charge);
RegisterSpellScript(spell_capacitus_polarity_shift);
}
@@ -30,201 +30,174 @@ enum Says
enum Spells
{
SPELL_SUMMON_RAGIN_FLAMES = 35275,
SPELL_FROST_ATTACK = 35263,
SPELL_FROST_ATTACK = 45196, // This is definitely spell added in TBC but did it replaced both 35264 and 39086 or only normal version?
SPELL_SUMMON_RAGING_FLAMES = 35275,
SPELL_QUELL_RAGING_FLAMES = 35277,
SPELL_ARCANE_BLAST = 35314,
SPELL_DRAGONS_BREATH = 35250,
// Raging Flames
SPELL_RAGING_FLAMES_DUMMY = 35274, // NYI, no clue what it can do
SPELL_RAGING_FLAMES_AREA_AURA = 35281,
SPELL_INVIS_STEALTH_DETECTION = 18950,
SPELL_INFERNO = 35268,
SPELL_INFERNO_DAMAGE = 35283
};
enum Events
struct boss_nethermancer_sepethrea : public BossAI
{
EVENT_FROST_ATTACK = 1,
EVENT_ARCANE_BLAST = 2,
EVENT_DRAGONS_BREATH = 3,
};
class boss_nethermancer_sepethrea : public CreatureScript
{
public:
boss_nethermancer_sepethrea(): CreatureScript("boss_nethermancer_sepethrea") { }
struct boss_nethermancer_sepethreaAI : public BossAI
boss_nethermancer_sepethrea(Creature* creature) : BossAI(creature, DATA_NETHERMANCER_SEPRETHREA)
{
boss_nethermancer_sepethreaAI(Creature* creature) : BossAI(creature, DATA_NETHERMANCER_SEPRETHREA) { }
void JustEngagedWith(Unit* /*who*/) override
scheduler.SetValidator([this]
{
_JustEngagedWith();
events.ScheduleEvent(EVENT_FROST_ATTACK, 6000);
events.ScheduleEvent(EVENT_ARCANE_BLAST, 14000);
events.ScheduleEvent(EVENT_DRAGONS_BREATH, 18000);
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
Talk(SAY_AGGRO);
me->CastSpell(me, SPELL_SUMMON_RAGIN_FLAMES, true);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (Unit* victim = me->GetVictim())
{
summon->AI()->AttackStart(victim);
summon->AddThreat(victim, 1000.0f);
summon->SetInCombatWithZone();
}
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
events.Reset();
if (instance)
{
instance->SetBossState(DATA_NETHERMANCER_SEPRETHREA, DONE);
instance->SaveToDB();
}
Talk(SAY_DEATH);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
Unit::Kill(summon, summon);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_FROST_ATTACK:
me->CastSpell(me->GetVictim(), SPELL_FROST_ATTACK, false);
events.ScheduleEvent(EVENT_FROST_ATTACK, 8000);
break;
case EVENT_ARCANE_BLAST:
me->CastSpell(me->GetVictim(), SPELL_ARCANE_BLAST, false);
events.ScheduleEvent(EVENT_ARCANE_BLAST, 12000);
break;
case EVENT_DRAGONS_BREATH:
me->CastSpell(me->GetVictim(), SPELL_DRAGONS_BREATH, true);
events.ScheduleEvent(EVENT_DRAGONS_BREATH, 16000);
if (roll_chance_i(50))
Talk(SAY_DRAGONS_BREATH);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustEngagedWith(Unit* /*who*/) override
{
return GetMechanarAI<boss_nethermancer_sepethreaAI>(creature);
_JustEngagedWith();
scheduler.Schedule(6s, [this](TaskContext context)
{
DoCastVictim(SPELL_FROST_ATTACK);
context.Repeat(8s);
}).Schedule(15s, 25s, [this](TaskContext context)
{
DoCastVictim(SPELL_ARCANE_BLAST);
if (me->GetVictim())
{
DoModifyThreatByPercent(me->GetVictim(), -50);
}
context.Repeat();
}).Schedule(20s, 30s, [this](TaskContext context)
{
DoCastVictim(SPELL_DRAGONS_BREATH);
context.Repeat(25s, 35s);
if (roll_chance_i(50))
{
Talk(SAY_DRAGONS_BREATH);
}
});
Talk(SAY_AGGRO);
DoCastSelf(SPELL_SUMMON_RAGING_FLAMES, true);
}
void EnterEvadeMode(EvadeReason why) override
{
// Fails probably because target is in evade mode (yes, she kills them on evade too). We'll kill them directly in their script for now
DoCastSelf(SPELL_QUELL_RAGING_FLAMES, true);
ScriptedAI::EnterEvadeMode(why);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (Unit* victim = me->GetVictim())
{
summon->AI()->AttackStart(victim);
summon->AddThreat(victim, 1000.0f);
summon->SetInCombatWithZone();
}
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
DoCastSelf(SPELL_QUELL_RAGING_FLAMES, true);
}
};
enum raginFlames
struct npc_raging_flames : public ScriptedAI
{
SPELL_INFERNO = 35268,
SPELL_FIRE_TAIL = 35278,
SPELL_INFERNO_DAMAGE = 35283,
npc_raging_flames(Creature* creature) : ScriptedAI(creature) { }
EVENT_SPELL_FIRE_TAIL = 1,
EVENT_SPELL_INFERNO = 2
};
class npc_ragin_flames : public CreatureScript
{
public:
npc_ragin_flames() : CreatureScript("npc_ragin_flames") { }
struct npc_ragin_flamesAI : public ScriptedAI
void InitializeAI() override
{
npc_ragin_flamesAI(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
void Reset() override
{
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, true);
}
void JustEngagedWith(Unit*) override
{
events.ScheduleEvent(EVENT_SPELL_FIRE_TAIL, 500);
events.ScheduleEvent(EVENT_SPELL_INFERNO, urand(10000, 20000));
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_SPELL_INFERNO:
if (me->IsWithinCombatRange(me->GetVictim(), 5.0f))
{
me->CastSpell(me, SPELL_INFERNO, true);
events.ScheduleEvent(EVENT_SPELL_INFERNO, 20000);
}
else
events.ScheduleEvent(EVENT_SPELL_INFERNO, 1000);
break;
case EVENT_SPELL_FIRE_TAIL:
me->CastSpell(me, SPELL_FIRE_TAIL, true);
events.ScheduleEvent(EVENT_SPELL_FIRE_TAIL, 500);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetMechanarAI<npc_ragin_flamesAI>(creature);
me->SetCorpseDelay(20);
}
// It's more tricky actually
void FixateRandomTarget()
{
me->GetThreatMgr().ClearAllThreat();
if (TempSummon* summon = me->ToTempSummon())
if (Creature* summoner = summon->GetSummonerCreatureBase())
if (summoner->IsAIEnabled)
if (Unit* target = summoner->AI()->SelectTarget(SelectTargetMethod::Random, 1, 100.0f, true, false))
me->AddThreat(target, 1000000.0f);
}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
DoZoneInCombat();
DoCastSelf(SPELL_RAGING_FLAMES_AREA_AURA);
DoCastSelf(SPELL_INVIS_STEALTH_DETECTION);
FixateRandomTarget();
_scheduler.Schedule(15s, 25s, [this](TaskContext task)
{
DoCastSelf(SPELL_INFERNO);
FixateRandomTarget();
task.Repeat(20s, 30s);
});
}
void Reset() override
{
_scheduler.CancelAll();
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->KillSelf();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff);
DoMeleeAttackIfReady();
}
private:
TaskScheduler _scheduler;
};
class spell_ragin_flames_inferno : public SpellScriptLoader
class spell_ragin_flames_inferno : public AuraScript
{
public:
spell_ragin_flames_inferno() : SpellScriptLoader("spell_ragin_flames_inferno") { }
PrepareAuraScript(spell_ragin_flames_inferno);
class spell_ragin_flames_inferno_AuraScript : public AuraScript
void HandlePeriodic(AuraEffect const* aurEff)
{
PrepareAuraScript(spell_ragin_flames_inferno_AuraScript);
GetUnitOwner()->CastCustomSpell(SPELL_INFERNO_DAMAGE, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetUnitOwner(), TRIGGERED_FULL_MASK);
}
void HandlePeriodic(AuraEffect const* aurEff)
{
GetUnitOwner()->CastCustomSpell(SPELL_INFERNO_DAMAGE, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetUnitOwner(), TRIGGERED_FULL_MASK);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ragin_flames_inferno_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
void Register() override
{
return new spell_ragin_flames_inferno_AuraScript();
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ragin_flames_inferno::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
void AddSC_boss_nethermancer_sepethrea()
{
new boss_nethermancer_sepethrea();
new npc_ragin_flames();
new spell_ragin_flames_inferno();
RegisterMechanarCreatureAI(boss_nethermancer_sepethrea);
RegisterMechanarCreatureAI(npc_raging_flames);
RegisterSpellScript(spell_ragin_flames_inferno);
}
@@ -43,116 +43,77 @@ enum Spells
SPELL_SUMMON_NETHER_WRAITH_4 = 35288,
};
enum Events
struct boss_pathaleon_the_calculator : public BossAI
{
EVENT_SUMMON = 1,
EVENT_MANA_TAP = 2,
EVENT_ARCANE_TORRENT = 3,
EVENT_DOMINATION = 4,
EVENT_ARCANE_EXPLOSION = 5,
EVENT_FRENZY = 6,
};
class boss_pathaleon_the_calculator : public CreatureScript
{
public:
boss_pathaleon_the_calculator(): CreatureScript("boss_pathaleon_the_calculator") { }
struct boss_pathaleon_the_calculatorAI : public BossAI
boss_pathaleon_the_calculator(Creature* creature) : BossAI(creature, DATA_PATHALEON_THE_CALCULATOR)
{
boss_pathaleon_the_calculatorAI(Creature* creature) : BossAI(creature, DATA_PATHALEON_THE_CALCULATOR) { }
void InitializeAI() override
scheduler.SetValidator([this]
{
BossAI::InitializeAI();
}
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void JustEngagedWith(Unit* /*who*/) override
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
ScheduleHealthCheckEvent(20, [&]()
{
_JustEngagedWith();
events.ScheduleEvent(EVENT_SUMMON, 30000);
events.ScheduleEvent(EVENT_MANA_TAP, 12000);
events.ScheduleEvent(EVENT_ARCANE_TORRENT, 16000);
events.ScheduleEvent(EVENT_DOMINATION, 25000);
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 8000);
events.ScheduleEvent(EVENT_FRENZY, 1000);
Talk(SAY_AGGRO);
}
summons.DespawnAll();
DoCastSelf(SPELL_DISGRUNTLED_ANGER, true);
Talk(SAY_ENRAGE);
});
void KilledUnit(Unit* victim) override
scheduler.Schedule(30s, [this](TaskContext context)
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
for (uint8 i = 0; i < DUNGEON_MODE(3, 4); ++i)
me->CastSpell(me, SPELL_SUMMON_NETHER_WRAITH_1 + i, true);
void JustDied(Unit* /*killer*/) override
Talk(SAY_SUMMON);
context.Repeat(30s, 40s);
}).Schedule(12s, [this](TaskContext context)
{
_JustDied();
Talk(SAY_DEATH);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 40.0f, false)))
{
case EVENT_ARCANE_EXPLOSION:
me->CastSpell(me, SPELL_ARCANE_EXPLOSION, false);
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 12000);
break;
case EVENT_ARCANE_TORRENT:
me->RemoveAurasDueToSpell(SPELL_MANA_TAP);
me->ModifyPower(POWER_MANA, 5000);
me->CastSpell(me, SPELL_ARCANE_TORRENT, false);
events.ScheduleEvent(EVENT_ARCANE_TORRENT, 15000);
break;
case EVENT_MANA_TAP:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 40.0f, false)))
me->CastSpell(target, SPELL_MANA_TAP, false);
events.ScheduleEvent(EVENT_MANA_TAP, 18000);
break;
case EVENT_DOMINATION:
Talk(SAY_DOMINATION);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 50.0f))
me->CastSpell(target, SPELL_DOMINATION, false);
events.ScheduleEvent(EVENT_DOMINATION, 30000);
break;
case EVENT_FRENZY:
if (me->HealthBelowPct(20))
{
summons.DespawnAll();
me->CastSpell(me, SPELL_DISGRUNTLED_ANGER, true);
Talk(SAY_ENRAGE);
break;
}
events.ScheduleEvent(EVENT_FRENZY, 1000);
break;
case EVENT_SUMMON:
for (uint8 i = 0; i < DUNGEON_MODE(3, 4); ++i)
me->CastSpell(me, SPELL_SUMMON_NETHER_WRAITH_1 + i, true);
Talk(SAY_SUMMON);
events.ScheduleEvent(EVENT_SUMMON, urand(30000, 45000));
break;
DoCast(target, SPELL_MANA_TAP);
}
context.Repeat(18s);
}).Schedule(16s, [this](TaskContext context)
{
me->RemoveAurasDueToSpell(SPELL_MANA_TAP);
me->ModifyPower(POWER_MANA, 5000);
DoCastSelf(SPELL_ARCANE_TORRENT);
context.Repeat(15s);
}).Schedule(25s, [this](TaskContext context)
{
Talk(SAY_DOMINATION);
DoCastRandomTarget(SPELL_DOMINATION, 1, 50.0f);
context.Repeat(30s);
}).Schedule(8s, [this](TaskContext context)
{
DoCastAOE(SPELL_ARCANE_EXPLOSION);
context.Repeat(12s);
});
DoMeleeAttackIfReady();
}
};
Talk(SAY_AGGRO);
}
CreatureAI* GetAI(Creature* creature) const override
void KilledUnit(Unit* victim) override
{
return GetMechanarAI<boss_pathaleon_the_calculatorAI>(creature);
if (victim->IsPlayer())
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
};
void AddSC_boss_pathaleon_the_calculator()
{
new boss_pathaleon_the_calculator();
RegisterMechanarCreatureAI(boss_pathaleon_the_calculator);
}
@@ -72,4 +72,6 @@ inline AI* GetMechanarAI(T* obj)
return GetInstanceAI<AI>(obj, MechanarScriptName);
}
#define RegisterMechanarCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetMechanarAI)
#endif
@@ -15,146 +15,12 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Zangarmarsh
SD%Complete: 100
SDComment: Quest support: 9752, 9785, 9803, 10009. Mark Of ... buffs.
SDCategory: Zangarmarsh
EndScriptData */
/* ContentData
npcs_ashyen_and_keleth
npc_cooshcoosh
npc_elder_kuruti
npc_mortog_steamhead
npc_kayra_longmane
npc_timothy_daniels
EndContentData */
#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
#include "ScriptedGossip.h"
// Theirs
/*######
## npcs_ashyen_and_keleth
######*/
#define GOSSIP_ITEM_BLESS_ASH "Grant me your mark, wise ancient."
#define GOSSIP_ITEM_BLESS_KEL "Grant me your mark, mighty ancient."
enum AshyenAndKeleth
{
GOSSIP_REWARD_BLESS = 0,
NPC_ASHYEN = 17900,
NPC_KELETH = 17901,
SPELL_BLESS_ASH_EXA = 31815,
SPELL_BLESS_ASH_REV = 31811,
SPELL_BLESS_ASH_HON = 31810,
SPELL_BLESS_ASH_FRI = 31808,
SPELL_BLESS_KEL_EXA = 31814,
SPELL_BLESS_KEL_REV = 31813,
SPELL_BLESS_KEL_HON = 31812,
SPELL_BLESS_KEL_FRI = 31807
};
class npcs_ashyen_and_keleth : public CreatureScript
{
public:
npcs_ashyen_and_keleth() : CreatureScript("npcs_ashyen_and_keleth") { }
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->GetReputationRank(942) > REP_NEUTRAL)
{
if (creature->GetEntry() == NPC_ASHYEN)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_BLESS_ASH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (creature->GetEntry() == NPC_KELETH)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_BLESS_KEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
}
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
return true;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
ClearGossipMenuFor(player);
if (action == GOSSIP_ACTION_INFO_DEF + 1)
{
creature->setPowerType(POWER_MANA);
creature->SetMaxPower(POWER_MANA, 200); //set a "fake" mana value, we can't depend on database doing it in this case
creature->SetPower(POWER_MANA, 200);
if (creature->GetEntry() == NPC_ASHYEN) //check which Creature we are dealing with
{
uint32 spell = 0;
switch (player->GetReputationRank(942))
{
//mark of lore
case REP_FRIENDLY:
spell = SPELL_BLESS_ASH_FRI;
break;
case REP_HONORED:
spell = SPELL_BLESS_ASH_HON;
break;
case REP_REVERED:
spell = SPELL_BLESS_ASH_REV;
break;
case REP_EXALTED:
spell = SPELL_BLESS_ASH_EXA;
break;
default:
break;
}
if (spell)
{
creature->CastSpell(player, spell, true);
creature->AI()->Talk(GOSSIP_REWARD_BLESS);
}
}
if (creature->GetEntry() == NPC_KELETH)
{
uint32 spell = 0;
switch (player->GetReputationRank(942)) //mark of war
{
case REP_FRIENDLY:
spell = SPELL_BLESS_KEL_FRI;
break;
case REP_HONORED:
spell = SPELL_BLESS_KEL_HON;
break;
case REP_REVERED:
spell = SPELL_BLESS_KEL_REV;
break;
case REP_EXALTED:
spell = SPELL_BLESS_KEL_EXA;
break;
default:
break;
}
if (spell)
{
creature->CastSpell(player, spell, true);
creature->AI()->Talk(GOSSIP_REWARD_BLESS);
}
}
CloseGossipMenuFor(player);
player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
}
return true;
}
};
/*######
## npc_cooshcoosh
######*/
@@ -451,7 +317,6 @@ public:
void AddSC_zangarmarsh()
{
// Theirs
new npcs_ashyen_and_keleth();
new npc_cooshcoosh();
new npc_elder_kuruti();
new npc_mortog_steamhead();
+114 -11
View File
@@ -1785,19 +1785,29 @@ class spell_gen_elune_candle : public SpellScript
}
};
/* 29266, 57685, 58951, 70592, 70628, 74490 - Permanent Feign Death
31261 - Permanent Feign Death (Root)
35356, 35357 - Spawn Feign Death */
class spell_gen_creature_permanent_feign_death : public AuraScript
/*
There are only 3 possible flags Feign Death auras can apply: UNIT_DYNFLAG_DEAD, UNIT_FLAG2_FEIGN_DEATH
and UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT. Some auras can apply only 2 flags
spell_gen_feign_death_all_flags applies all 3 flags
spell_gen_feign_death_no_dyn_flag applies no UNIT_DYNFLAG_DEAD (does not make the creature appear dead)
spell_gen_feign_death_no_prevent_emotes applies no UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT
REACT_PASSIVE should be handled directly in scripts since not all creatures should be passive. Otherwise
creature will be not able to aggro or execute MoveInLineOfSight events. Removing may cause more issues
than already exists
*/
class spell_gen_feign_death_all_flags : public AuraScript
{
PrepareAuraScript(spell_gen_creature_permanent_feign_death);
PrepareAuraScript(spell_gen_feign_death_all_flags);
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
target->SetUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
target->SetImmuneToAll(true);
target->SetUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
if (target->GetTypeId() == TYPEID_UNIT)
target->ToCreature()->SetReactState(REACT_PASSIVE);
@@ -1808,16 +1818,83 @@ class spell_gen_creature_permanent_feign_death : public AuraScript
Unit* target = GetTarget();
target->RemoveDynamicFlag(UNIT_DYNFLAG_DEAD);
target->RemoveUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
target->SetImmuneToAll(false);
target->RemoveUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
if (target->GetTypeId() == TYPEID_UNIT)
target->ToCreature()->SetReactState(REACT_AGGRESSIVE);
target->ToCreature()->InitializeReactState();
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_gen_creature_permanent_feign_death::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectApplyFn(spell_gen_creature_permanent_feign_death::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectApply += AuraEffectApplyFn(spell_gen_feign_death_all_flags::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectApplyFn(spell_gen_feign_death_all_flags::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 35357 - Spawn Feign Death
// 51329 - Feign Death
class spell_gen_feign_death_no_dyn_flag : public AuraScript
{
PrepareAuraScript(spell_gen_feign_death_no_dyn_flag);
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->SetUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
target->SetUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
if (target->GetTypeId() == TYPEID_UNIT)
target->ToCreature()->SetReactState(REACT_PASSIVE);
}
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->RemoveUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
target->RemoveUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
if (target->GetTypeId() == TYPEID_UNIT)
target->ToCreature()->InitializeReactState();
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_gen_feign_death_no_dyn_flag::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectApplyFn(spell_gen_feign_death_no_dyn_flag::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 58951 - Permanent Feign Death
class spell_gen_feign_death_no_prevent_emotes : public AuraScript
{
PrepareAuraScript(spell_gen_feign_death_no_prevent_emotes);
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->SetUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
target->SetUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
if (target->GetTypeId() == TYPEID_UNIT)
target->ToCreature()->SetReactState(REACT_PASSIVE);
}
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->RemoveUnitFlag2(UNIT_FLAG2_FEIGN_DEATH);
target->RemoveUnitFlag(UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
if (target->GetTypeId() == TYPEID_UNIT)
target->ToCreature()->InitializeReactState();
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_gen_feign_death_no_prevent_emotes::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectApplyFn(spell_gen_feign_death_no_prevent_emotes::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
@@ -3689,6 +3766,29 @@ class spell_gen_paralytic_poison : public AuraScript
}
};
class spell_gen_prevent_emotes : public AuraScript
{
PrepareAuraScript(spell_gen_prevent_emotes);
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_gen_prevent_emotes::HandleEffectApply, EFFECT_FIRST_FOUND, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_gen_prevent_emotes::OnRemove, EFFECT_FIRST_FOUND, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL);
}
};
enum BladeWarding
{
SPELL_GEN_BLADE_WARDING_TRIGGERED = 64442
@@ -4753,7 +4853,9 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_parachute);
RegisterSpellScript(spell_gen_pet_summoned);
RegisterSpellScript(spell_gen_remove_flight_auras);
RegisterSpellScript(spell_gen_creature_permanent_feign_death);
RegisterSpellScript(spell_gen_feign_death_all_flags);
RegisterSpellScript(spell_gen_feign_death_no_dyn_flag);
RegisterSpellScript(spell_gen_feign_death_no_prevent_emotes);
RegisterSpellScript(spell_pvp_trinket_wotf_shared_cd);
RegisterSpellScript(spell_gen_animal_blood);
RegisterSpellScript(spell_gen_divine_storm_cd_reset);
@@ -4795,6 +4897,7 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_despawn_self);
RegisterSpellScript(spell_gen_bandage);
RegisterSpellScript(spell_gen_paralytic_poison);
RegisterSpellScript(spell_gen_prevent_emotes);
RegisterSpellScript(spell_gen_blade_warding);
RegisterSpellScriptWithArgs(spell_gen_lifebloom, "spell_hexlord_lifebloom", SPELL_HEXLORD_MALACRASS_LIFEBLOOM_FINAL_HEAL);
RegisterSpellScriptWithArgs(spell_gen_lifebloom, "spell_tur_ragepaw_lifebloom", SPELL_TUR_RAGEPAW_LIFEBLOOM_FINAL_HEAL);
+13 -1
View File
@@ -59,6 +59,7 @@ enum WarriorSpells
SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2 = 64850,
SPELL_WARRIOR_VIGILANCE_PROC = 50725,
SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665,
SPELL_WARRIOR_WHIRLWIND_MAIN = 50622,
SPELL_WARRIOR_WHIRLWIND_OFF = 44949
};
@@ -646,12 +647,18 @@ class spell_warr_sweeping_strikes : public AuraScript
case SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_2:
case SPELL_WARRIOR_WHIRLWIND_OFF:
return false;
case SPELL_WARRIOR_WHIRLWIND_MAIN:
if (actor->HasSpellCooldown(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1))
{
return false;
}
break;
default:
break;
}
}
_procTarget = eventInfo.GetActor()->SelectNearbyNoTotemTarget(eventInfo.GetProcTarget());
_procTarget = actor->SelectNearbyNoTotemTarget(eventInfo.GetProcTarget());
return _procTarget != nullptr;
}
@@ -668,6 +675,11 @@ class spell_warr_sweeping_strikes : public AuraScript
}
else
{
if (spellInfo && spellInfo->Id == SPELL_WARRIOR_WHIRLWIND_MAIN)
{
eventInfo.GetActor()->AddSpellCooldown(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, 0, 500);
}
int32 damage = damageInfo->GetUnmitigatedDamage();
GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, &damage, 0, 0, true, nullptr, aurEff);
}
+99 -96
View File
@@ -15,42 +15,57 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Npc_Taxi
SD%Complete: 0%
SDComment: To be used for taxi NPCs that are located globally.
SDCategory: NPCs
EndScriptData
*/
#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#define GOSSIP_NETHER_DRAKE "I'm ready to fly! Take me up, dragon!"
#define GOSSIP_IRONWING "I'd like to take a flight around Stormwind Harbor."
#define GOSSIP_DABIREE1 "Fly me to Murketh and Shaadraz Gateways"
#define GOSSIP_DABIREE2 "Fly me to Shatter Point"
#define GOSSIP_BRACK1 "Fly me to Murketh and Shaadraz Gateways"
#define GOSSIP_BRACK2 "Fly me to The Abyssal Shelf"
#define GOSSIP_BRACK3 "Fly me to Spinebreaker Post"
#define GOSSIP_IRENA "Fly me to Skettis please"
#define GOSSIP_CLOUDBREAKER1 "Speaking of action, I've been ordered to undertake an air strike."
#define GOSSIP_CLOUDBREAKER2 "I need to intercept the Dawnblade reinforcements."
#define GOSSIP_DRAGONHAWK "<Ride the dragonhawk to Sun's Reach>"
#define GOSSIP_VERONIA "Fly me to Manaforge Coruu please"
#define GOSSIP_DEESAK "Fly me to Ogri'la please"
#define GOSSIP_AFRASASTRASZ1 "I would like to take a flight to the ground, Lord Of Afrasastrasz."
#define GOSSIP_AFRASASTRASZ2 "My Lord, I must go to the upper floor of the temple."
#define GOSSIP_TARIOLSTRASZ1 "My Lord, I must go to the upper floor of the temple."
#define GOSSIP_TARIOLSTRASZ2 "Can you spare a drake to travel to Lord Of Afrasastrasz, in the middle of the temple?"
#define GOSSIP_TORASTRASZA1 "I would like to see Lord Of Afrasastrasz, in the middle of the temple."
#define GOSSIP_TORASTRASZA2 "Yes, Please. I would like to return to the ground floor of the temple."
#define GOSSIP_CRIMSONWING "<Ride the gryphons to Survey Alcaz Island>"
#define GOSSIP_WILLIAMKEILAR1 "Take me to Northpass Tower."
#define GOSSIP_WILLIAMKEILAR2 "Take me to Eastwall Tower."
#define GOSSIP_WILLIAMKEILAR3 "Take me to Crown Guard Tower."
enum Npcs
{
NPC_NETHER_DRAKE = 20903, // Netherstorm - Protectorate Nether Drake
NPC_IRONWING = 29154, // Stormwind City - Thargold Ironwing
NPC_DABIR = 19409, // Hellfire Peninsula - Wing Commander Dabir'ee
NPC_BRACK = 19401, // Hellfire Peninsula - Wing Commander Brack
NPC_IRENA = 23413, // Blade's Edge Mountains - Skyguard Handler Irena
NPC_AYREN = 25059, // Isle of Quel'Danas - Ayren Cloudbreaker
NPC_DRAGONHAWK = 25236, // Isle of Quel'Danas - Unrestrained Dragonhawk
NPC_VERONIA = 20162, // Netherstorm - Veronia
NPC_DEESAK = 23415, // Terokkar Forest - Skyguard Handler Deesak
NPC_AFRASASTRASZ = 27575, // Dragonblight - Lord Afrasastrasz
NPC_TARIOLSTRASZ = 26443, // Dragonblight - Tariolstrasz
NPC_TORASTRASZA = 26949, // Dragonblight - Torastrasza
NPC_CESSA = 23704, // Dustwallow Marsh - Cassa Crimsonwing
NPC_KIELAR = 17209, // William Kielar <Spectral Gryphon Master> - Eastern Plaguelands Towers
};
enum Misc
{
REP_SKYGUARD = 1031, // Sha'tari Skyguard Reputation
// Netherstorm
QUEST_NETHERY_WINGS = 10438, // On Nethery Wings
ITEM_DISRUPTOR = 29778, // Phase Disruptor (Needed for On Nethery Wings)
QUEST_BEHIND_ENEMY = 10652, // Behind Enemy Lines
// Hellfire Peninsula - Alliance
QUEST_GATEWAYS_A = 10146, // Mission: The Murketh and Shaadraz Gateways
QUEST_SHATTER_POINT = 10340, // Shatter Point
// Hellfire Peninsula - Horde
QUEST_GATEWAYS_H = 10129, // Mission: The Murketh and Shaadraz Gateways
QUEST_ABBYSAL = 10162, // Mission: The Abyssal Shelf
QUEST_ABBYSAL_DAILY = 10347, // Return to the Abyssal Shelf (Daily)
QUEST_SPINEBREAKER = 10242, // Spinebreaker Post
// Isle of Quel'Danas (Daily)
QUEST_DEAD_SCAR = 11532, // Mission: Distraction at the Dead Scar
QUEST_AIR_STRIKE = 11533, // The Air Strikes Must Continue
QUEST_INTERCEPT = 11542, // Mission: Intercept the Reinforcements
QUEST_KEEP_AT_BEY = 11543, // Keeping the Enemy at Bay
// Dustwallow Marsh
QUEST_SURVEY_ALCAZ = 11142, // Survey Alcaz Island
};
class npc_taxi : public CreatureScript
{
@@ -62,87 +77,84 @@ public:
if (creature->IsQuestGiver())
player->PrepareQuestMenu(creature->GetGUID());
uint32 gossipmenuid = 0;
gossipmenuid = creature->GetCreatureTemplate()->GossipMenuId;
switch (creature->GetEntry())
{
case 20903: // Netherstorm - Protectorate Nether Drake
if (player->GetQuestStatus(10438) == QUEST_STATUS_INCOMPLETE && player->HasItemCount(29778))
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_NETHER_DRAKE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
case NPC_NETHER_DRAKE:
if (player->GetQuestStatus(QUEST_NETHERY_WINGS) == QUEST_STATUS_INCOMPLETE && player->HasItemCount(ITEM_DISRUPTOR))
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
break;
case 29154: // Stormwind City - Thargold Ironwing
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_IRONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
case NPC_IRONWING:
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
break;
case 19409: // Hellfire Peninsula - Wing Commander Dabir'ee
//Mission: The Murketh and Shaadraz Gateways
if (player->GetQuestStatus(10146) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_DABIREE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
case NPC_DABIR:
if (player->GetQuestStatus(QUEST_GATEWAYS_A) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
//Shatter Point
if (!player->GetQuestRewardStatus(10340))
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_DABIREE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
if (!player->GetQuestRewardStatus(QUEST_SHATTER_POINT))
AddGossipItemFor(player, gossipmenuid, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
break;
case 19401: // Hellfire Peninsula - Wing Commander Brack
//Mission: The Murketh and Shaadraz Gateways
if (player->GetQuestStatus(10129) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BRACK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
case NPC_BRACK:
if (player->GetQuestStatus(QUEST_GATEWAYS_H) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, gossipmenuid, 5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
//Mission: The Abyssal Shelf || Return to the Abyssal Shelf
if (player->GetQuestStatus(10162) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10347) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BRACK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
if (player->GetQuestStatus(QUEST_ABBYSAL) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_ABBYSAL_DAILY) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
//Spinebreaker Post
if (player->GetQuestStatus(10242) == QUEST_STATUS_COMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BRACK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10);
if (player->GetQuestStatus(QUEST_SPINEBREAKER) == QUEST_STATUS_COMPLETE)
AddGossipItemFor(player, gossipmenuid, 4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10);
break;
case 23413: // Blade's Edge Mountains - Skyguard Handler Irena
if (player->GetReputationRank(1031) >= REP_HONORED)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_IRENA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
case NPC_IRENA:
if (player->GetReputationRank(REP_SKYGUARD) >= REP_HONORED)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
break;
case 25059: // Isle of Quel'Danas - Ayren Cloudbreaker
if (player->GetQuestStatus(11532) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11533) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12);
case NPC_AYREN:
if (player->GetQuestStatus(QUEST_DEAD_SCAR) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_AIR_STRIKE) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12);
if (player->GetQuestStatus(11542) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13);
if (player->GetQuestStatus(QUEST_INTERCEPT) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_KEEP_AT_BEY) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13);
break;
case 25236: // Isle of Quel'Danas - Unrestrained Dragonhawk
if (player->GetQuestStatus(11542) == QUEST_STATUS_COMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_COMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_DRAGONHAWK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14);
case NPC_DRAGONHAWK:
if (player->GetQuestStatus(QUEST_INTERCEPT) == QUEST_STATUS_COMPLETE || player->GetQuestStatus(QUEST_KEEP_AT_BEY) == QUEST_STATUS_COMPLETE)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14);
break;
case 20162: // Netherstorm - Veronia
//Behind Enemy Lines
if (player->GetQuestStatus(10652) != QUEST_STATUS_REWARDED)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_VERONIA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15);
case NPC_VERONIA:
if (player->GetQuestStatus(QUEST_BEHIND_ENEMY) != QUEST_STATUS_REWARDED)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15);
break;
case 23415: // Terokkar Forest - Skyguard Handler Deesak
if (player->GetReputationRank(1031) >= REP_HONORED)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_DEESAK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16);
case NPC_DEESAK:
if (player->GetReputationRank(REP_SKYGUARD) >= REP_HONORED)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16);
break;
case 27575: // Dragonblight - Lord Afrasastrasz
case NPC_AFRASASTRASZ:
// middle -> ground
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 17);
AddGossipItemFor(player, gossipmenuid, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 17);
// middle -> top
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 18);
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 18);
break;
case 26443: // Dragonblight - Tariolstrasz //need to check if quests are required before gossip available (12123, 12124)
case NPC_TARIOLSTRASZ:
// ground -> top
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 19);
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 19);
// ground -> middle
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20);
AddGossipItemFor(player, gossipmenuid, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20);
break;
case 26949: // Dragonblight - Torastrasza
case NPC_TORASTRASZA:
// top -> middle
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21);
AddGossipItemFor(player, gossipmenuid, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21);
// top -> ground
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
break;
case 23704: // Dustwallow Marsh - Cassa Crimsonwing
if (player->GetQuestStatus(11142) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25);
case NPC_CESSA:
if (player->GetQuestStatus(QUEST_SURVEY_ALCAZ) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25);
break;
case 17209:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 27);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28);
case NPC_KIELAR:
AddGossipItemFor(player, gossipmenuid, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); // Northpass Tower.
AddGossipItemFor(player, gossipmenuid, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 27); // Eastwall Tower.
AddGossipItemFor(player, gossipmenuid, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28); // Crown Guard Tower.
break;
}
@@ -231,15 +243,6 @@ public:
CloseGossipMenuFor(player);
player->ActivateTaxiPathTo(879);
break;
case GOSSIP_ACTION_INFO_DEF + 23:
CloseGossipMenuFor(player);
player->CastSpell(player, 43074, true); //TaxiPath 736
break;
case GOSSIP_ACTION_INFO_DEF + 24:
CloseGossipMenuFor(player);
//player->ActivateTaxiPathTo(738);
player->CastSpell(player, 43136, false);
break;
case GOSSIP_ACTION_INFO_DEF + 25:
CloseGossipMenuFor(player);
player->CastSpell(player, 42295, true);