aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp12
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h5
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp7
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp70
-rw-r--r--src/server/game/Achievements/AchievementMgr.h1
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp26
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h3
-rw-r--r--src/server/game/DataStores/DBCStructure.h6
-rw-r--r--src/server/game/DataStores/DBCfmt.h2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp1
-rw-r--r--src/server/game/Mails/Mail.cpp2
-rw-r--r--src/server/game/Maps/MapManager.cpp8
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/scripts/Commands/cs_character.cpp2
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp5
-rw-r--r--src/server/scripts/Commands/cs_titles.cpp6
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp773
18 files changed, 562 insertions, 371 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index bd51fe0a85b..49beb0ae86f 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -76,6 +76,7 @@ SmartScript::SmartScript()
goOrigGUID = 0;
mLastInvoker = 0;
mScriptType = SMART_SCRIPT_TYPE_CREATURE;
+ isProcessingTimedActionList = false;
}
SmartScript::~SmartScript()
@@ -3253,6 +3254,7 @@ void SmartScript::OnUpdate(uint32 const diff)
bool needCleanup = true;
if (!mTimedActionList.empty())
{
+ isProcessingTimedActionList = true;
for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
{
if ((*i).enableTimed)
@@ -3261,6 +3263,8 @@ void SmartScript::OnUpdate(uint32 const diff)
needCleanup = false;
}
}
+
+ isProcessingTimedActionList = false;
}
if (needCleanup)
mTimedActionList.clear();
@@ -3502,6 +3506,14 @@ Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly)
void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry)
{
+ //do NOT clear mTimedActionList if it's being iterated because it will invalidate the iterator and delete
+ // any SmartScriptHolder contained like the "e" parameter passed to this function
+ if (isProcessingTimedActionList)
+ {
+ TC_LOG_ERROR("scripts.ai", "Entry %d SourceType %u Event %u Action %u is trying to overwrite timed action list from a timed action, this is not allowed!.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
+ return;
+ }
+
mTimedActionList.clear();
mTimedActionList = sSmartScriptMgr->GetScript(entry, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST);
if (mTimedActionList.empty())
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index 2e1068d1bff..244728a3037 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -118,7 +118,7 @@ class SmartScript
smart = false;
if (!smart)
- TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action skipped to prevent crash.", c ? c->GetDBTableGUIDLow() : (me ? me->GetDBTableGUIDLow() : 0), c ? c->GetEntry() : (me ? me->GetEntry() : 0));
+ TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action called by Creature (GUID: %u Entry: %u) skipped to prevent crash.", c ? c->GetDBTableGUIDLow() : 0, c ? c->GetEntry() : 0, me ? me->GetDBTableGUIDLow() : 0, me ? me->GetEntry() : 0);
return smart;
}
@@ -132,7 +132,7 @@ class SmartScript
if (!go || go->GetAIName() != "SmartGameObjectAI")
smart = false;
if (!smart)
- TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetDBTableGUIDLow() : (go ? go->GetDBTableGUIDLow() : 0), g ? g->GetEntry() : (go ? go->GetEntry() : 0));
+ TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: %u Entry: %u) skipped to prevent crash.", g ? g->GetDBTableGUIDLow() : 0, g ? g->GetEntry() : 0, go ? go->GetDBTableGUIDLow() : 0, go ? go->GetEntry() : 0);
return smart;
}
@@ -222,6 +222,7 @@ class SmartScript
SmartAIEventList mEvents;
SmartAIEventList mInstallEvents;
SmartAIEventList mTimedActionList;
+ bool isProcessingTimedActionList;
Creature* me;
uint64 meOrigGUID;
GameObject* go;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index d912de2a72c..c6b73a468d2 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -887,6 +887,12 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
break;
}
+ case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST:
+ {
+ if (!IsMinMaxValid(e, e.action.randTimedActionList.entry1, e.action.randTimedActionList.entry2))
+ return false;
+ break;
+ }
case SMART_ACTION_SET_POWER:
case SMART_ACTION_ADD_POWER:
case SMART_ACTION_REMOVE_POWER:
@@ -986,7 +992,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_SIMPLE_TALK:
case SMART_ACTION_CROSS_CAST:
case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST:
- case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST:
case SMART_ACTION_RANDOM_MOVE:
case SMART_ACTION_SET_UNIT_FIELD_BYTES_1:
case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1:
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index b98ff3e4f01..a99da4050f6 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -297,7 +297,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
if (!sCharTitlesStore.LookupEntry(known_title.title_id))
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.",
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.",
criteria->ID, criteria->requiredType, dataType, known_title.title_id);
return false;
}
@@ -400,7 +400,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
{
TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u",
dataType, criteria_id, map->GetId());
- return false;
+ return false;
}
InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
if (!instance)
@@ -2082,25 +2082,30 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
// mail
if (reward->sender)
{
- Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL;
+ MailDraft draft(reward->mailTemplate);
- int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
-
- // subject and text
- std::string subject = reward->subject;
- std::string text = reward->text;
- if (loc_idx >= 0)
+ if (!reward->mailTemplate)
{
- if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement))
+ // subject and text
+ std::string subject = reward->subject;
+ std::string text = reward->text;
+
+ int locIdx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
+ if (locIdx >= 0)
{
- ObjectMgr::GetLocaleString(loc->subject, loc_idx, subject);
- ObjectMgr::GetLocaleString(loc->text, loc_idx, text);
+ if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement))
+ {
+ ObjectMgr::GetLocaleString(loc->subject, locIdx, subject);
+ ObjectMgr::GetLocaleString(loc->text, locIdx, text);
+ }
}
- }
- MailDraft draft(subject, text);
+ draft = MailDraft(subject, text);
+ }
SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL;
if (item)
{
// save new item before send
@@ -2441,8 +2446,8 @@ void AchievementGlobalMgr::LoadRewards()
m_achievementRewards.clear(); // need for reload case
- // 0 1 2 3 4 5 6
- QueryResult result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward");
+ // 0 1 2 3 4 5 6 7
+ QueryResult result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text, mailTemplate FROM achievement_reward");
if (!result)
{
@@ -2456,20 +2461,21 @@ void AchievementGlobalMgr::LoadRewards()
{
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
- const AchievementEntry* pAchievement = GetAchievement(entry);
- if (!pAchievement)
+ AchievementEntry const* achievement = GetAchievement(entry);
+ if (!achievement)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` has wrong achievement (Entry: %u), ignored.", entry);
continue;
}
AchievementReward reward;
- reward.titleId[0] = fields[1].GetUInt32();
- reward.titleId[1] = fields[2].GetUInt32();
- reward.itemId = fields[3].GetUInt32();
- reward.sender = fields[4].GetUInt32();
- reward.subject = fields[5].GetString();
- reward.text = fields[6].GetString();
+ reward.titleId[0] = fields[1].GetUInt32();
+ reward.titleId[1] = fields[2].GetUInt32();
+ reward.itemId = fields[3].GetUInt32();
+ reward.sender = fields[4].GetUInt32();
+ reward.subject = fields[5].GetString();
+ reward.text = fields[6].GetString();
+ reward.mailTemplate = fields[7].GetUInt32();
// must be title or mail at least
if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender)
@@ -2478,7 +2484,7 @@ void AchievementGlobalMgr::LoadRewards()
continue;
}
- if (pAchievement->requiredFaction == ACHIEVEMENT_FACTION_ANY && ((reward.titleId[0] == 0) != (reward.titleId[1] == 0)))
+ if (achievement->requiredFaction == ACHIEVEMENT_FACTION_ANY && (!reward.titleId[0] ^ !reward.titleId[1]))
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) for only one team.", entry, reward.titleId[0], reward.titleId[1]);
if (reward.titleId[0])
@@ -2520,6 +2526,20 @@ void AchievementGlobalMgr::LoadRewards()
if (!reward.text.empty())
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data but has mail text.", entry);
+
+ if (reward.mailTemplate)
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data but has mailTemplate.", entry);
+ }
+
+ if (reward.mailTemplate)
+ {
+ if (!sMailTemplateStore.LookupEntry(reward.mailTemplate))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) has invalid mailTemplate (%u).", entry, reward.mailTemplate);
+ reward.mailTemplate = 0;
+ }
+ else if (!reward.subject.empty() || !reward.text.empty())
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) has mailTemplate (%u) and mail subject/text.", entry, reward.mailTemplate);
}
if (reward.itemId)
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index c4216b2ee74..0a3e711e2ef 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -233,6 +233,7 @@ struct AchievementReward
uint32 sender;
std::string subject;
std::string text;
+ uint32 mailTemplate;
};
typedef UNORDERED_MAP<uint32, AchievementReward> AchievementRewards;
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 9d7a67ee0dc..ab69c950ff4 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -1082,6 +1082,17 @@ void BattlegroundMgr::LoadBattleMastersEntry()
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
+ if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
+ {
+ if ((cInfo->npcflag & UNIT_NPC_FLAG_BATTLEMASTER) == 0)
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) listed in `battlemaster_entry` is not a battlemaster.", entry);
+ }
+ else
+ {
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) listed in `battlemaster_entry` does not exist.", entry);
+ continue;
+ }
+
uint32 bgTypeId = fields[1].GetUInt32();
if (!sBattlemasterListStore.LookupEntry(bgTypeId))
{
@@ -1093,9 +1104,24 @@ void BattlegroundMgr::LoadBattleMastersEntry()
}
while (result->NextRow());
+ CheckBattleMasters();
+
TC_LOG_INFO("server.loading", ">> Loaded %u battlemaster entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void BattlegroundMgr::CheckBattleMasters()
+{
+ CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates();
+ for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
+ {
+ if ((itr->second.npcflag & UNIT_NPC_FLAG_BATTLEMASTER) && mBattleMastersMap.find(itr->second.Entry) == mBattleMastersMap.end())
+ {
+ TC_LOG_ERROR("sql.sql", "CreatureTemplate (Entry: %u) has UNIT_NPC_FLAG_BATTLEMASTER but no data in `battlemaster_entry` table. Removing flag!", itr->second.Entry);
+ const_cast<CreatureTemplate*>(&itr->second)->npcflag &= ~UNIT_NPC_FLAG_BATTLEMASTER;
+ }
+ }
+}
+
HolidayIds BattlegroundMgr::BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId)
{
switch (bgTypeId)
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index f10614baafc..42803620e27 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -126,12 +126,13 @@ class BattlegroundMgr
uint32 GetRatingDiscardTimer() const;
void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry();
+ void CheckBattleMasters();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
{
BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry);
if (itr != mBattleMastersMap.end())
return itr->second;
- return BATTLEGROUND_WS;
+ return BATTLEGROUND_TYPE_NONE;
}
private:
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 7fb82ac8e03..d1db4fb634d 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -651,9 +651,9 @@ struct CharTitlesEntry
{
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
//uint32 unk1; // 1 flags?
- char* name[16]; // 2-17
+ char* nameMale[16]; // 2-17
// 18 string flag, unused
- //char* name2[16]; // 19-34, unused
+ char* nameFemale[16]; // 19-34
// 35 string flag, unused
uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
};
@@ -1270,7 +1270,7 @@ struct MailTemplateEntry
uint32 ID; // 0
//char* subject[16]; // 1-16
// 17 name flags, unused
- char* content[16]; // 18-33
+ char* content[16]; // 18-33
};
struct MapEntry
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index a1ebaa70018..be4369399d4 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -33,7 +33,7 @@ char const BannedAddOnsfmt[] = "nxxxxxxxxxx";
char const BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
char const BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx";
char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
-char const CharTitlesEntryfmt[] = "nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
+char const CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi";
char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
char const ChrRacesEntryfmt[] = "nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index c5c97e74777..48e4411e035 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -20,6 +20,7 @@
#include "AchievementMgr.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
+#include "BattlegroundMgr.h"
#include "Chat.h"
#include "Common.h"
#include "DatabaseEnv.h"
diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp
index 8c82ef8f45b..2c65e363dd5 100644
--- a/src/server/game/Mails/Mail.cpp
+++ b/src/server/game/Mails/Mail.cpp
@@ -193,10 +193,12 @@ void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver,
expire_delay = DAY;
// default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master)
else
+ {
if (m_COD)
expire_delay = 3 * DAY;
else
expire_delay = pSender && pSender->IsGameMaster() ? 90 * DAY : 30 * DAY;
+ }
time_t expire_time = deliver_time + expire_delay;
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 2e10fdc374b..d8c8889da67 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -122,7 +122,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
{
MapEntry const* entry = sMapStore.LookupEntry(mapid);
if (!entry)
- return false;
+ return false;
if (!entry->IsDungeon())
return true;
@@ -220,12 +220,12 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
// players are only allowed to enter 5 instances per hour
if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup())))
{
- uint32 instaceIdToCheck = 0;
+ uint32 instanceIdToCheck = 0;
if (InstanceSave* save = player->GetInstanceSave(mapid, entry->IsRaid()))
- instaceIdToCheck = save->GetInstanceId();
+ instanceIdToCheck = save->GetInstanceId();
// instanceId can never be 0 - will not be found
- if (!player->CheckInstanceCount(instaceIdToCheck) && !player->isDead())
+ if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead())
{
player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES);
return false;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index e5d3a5312de..961a896a8f7 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -3324,7 +3324,7 @@ enum BattlegroundTypeId
BATTLEGROUND_DS = 10, // Dalaran Sewers
BATTLEGROUND_RV = 11, // Ring of Valor
BATTLEGROUND_IC = 30, // Isle of Conquest
- BATTLEGROUND_RB = 32 // Random Battleground
+ BATTLEGROUND_RB = 32 // Random Battleground
};
#define MAX_BATTLEGROUND_TYPE_ID 33
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index af2fb90ea1b..af84a16aa0b 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1633,7 +1633,7 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadGameObjectForQuests();
TC_LOG_INFO("server.loading", "Loading BattleMasters...");
- sBattlegroundMgr->LoadBattleMastersEntry();
+ sBattlegroundMgr->LoadBattleMastersEntry(); // must be after load CreatureTemplate
TC_LOG_INFO("server.loading", "Loading GameTeleports...");
sObjectMgr->LoadGameTele();
diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp
index f9ef827e8c3..87bb1fefdd2 100644
--- a/src/server/scripts/Commands/cs_character.cpp
+++ b/src/server/scripts/Commands/cs_character.cpp
@@ -277,7 +277,7 @@ public:
if (titleInfo && target->HasTitle(titleInfo))
{
- std::string name = titleInfo->name[loc];
+ std::string name = target->getGender() == GENDER_MALE ? titleInfo->nameMale[loc] : titleInfo->nameFemale[loc];
if (name.empty())
continue;
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index f2b4f54363b..57cf2cba260 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -1183,8 +1183,9 @@ public:
CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
if (titleInfo)
{
+ /// @todo: implement female support
int locale = handler->GetSessionDbcLocale();
- std::string name = titleInfo->name[locale];
+ std::string name = titleInfo->nameMale[locale];
if (name.empty())
continue;
@@ -1196,7 +1197,7 @@ public:
if (locale == handler->GetSessionDbcLocale())
continue;
- name = titleInfo->name[locale];
+ name = titleInfo->nameMale[locale];
if (name.empty())
continue;
diff --git a/src/server/scripts/Commands/cs_titles.cpp b/src/server/scripts/Commands/cs_titles.cpp
index 20bffdbb792..3d429deb3ef 100644
--- a/src/server/scripts/Commands/cs_titles.cpp
+++ b/src/server/scripts/Commands/cs_titles.cpp
@@ -96,7 +96,7 @@ public:
target->SetTitle(titleInfo); // to be sure that title now known
target->SetUInt32Value(PLAYER_CHOSEN_TITLE, titleInfo->bit_index);
- handler->PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[handler->GetSessionDbcLocale()], tNameLink.c_str());
+ handler->PSendSysMessage(LANG_TITLE_CURRENT_RES, id, target->getGender() == GENDER_MALE ? titleInfo->nameMale[handler->GetSessionDbcLocale()] : titleInfo->nameFemale[handler->GetSessionDbcLocale()], tNameLink.c_str());
return true;
}
@@ -139,7 +139,7 @@ public:
std::string tNameLink = handler->GetNameLink(target);
char titleNameStr[80];
- snprintf(titleNameStr, 80, titleInfo->name[handler->GetSessionDbcLocale()], target->GetName().c_str());
+ snprintf(titleNameStr, 80, target->getGender() == GENDER_MALE ? titleInfo->nameMale[handler->GetSessionDbcLocale()] : titleInfo->nameFemale[handler->GetSessionDbcLocale()], target->GetName().c_str());
target->SetTitle(titleInfo);
handler->PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str());
@@ -187,7 +187,7 @@ public:
std::string tNameLink = handler->GetNameLink(target);
char titleNameStr[80];
- snprintf(titleNameStr, 80, titleInfo->name[handler->GetSessionDbcLocale()], target->GetName().c_str());
+ snprintf(titleNameStr, 80, target->getGender() == GENDER_MALE ? titleInfo->nameMale[handler->GetSessionDbcLocale()] : titleInfo->nameFemale[handler->GetSessionDbcLocale()], target->GetName().c_str());
handler->PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str());
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
index 2fe619a5367..19e6b55b5c5 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp
@@ -26,30 +26,22 @@
enum Spells
{
SPELL_MIND_FLAY = 52586,
- H_SPELL_MIND_FLAY = 59367,
SPELL_CURSE_OF_FATIGUE = 52592,
- H_SPELL_CURSE_OF_FATIGUE = 59368,
SPELL_FRENZY = 28747, //maybe 53361
SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439
SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735
- H_SPELL_ACID_SPLASH = 59363,
SPELL_ACID_SPLASH = 52446,
SPELL_CHARGE = 16979, //maybe is another spell
SPELL_BACKSTAB = 52540,
SPELL_SHADOW_BOLT = 52534,
- H_SPELL_SHADOW_BOLT = 59357,
SPELL_SHADOW_NOVA = 52535,
- H_SPELL_SHADOW_NOVA = 59358,
SPELL_STRIKE = 52532,
SPELL_CLEAVE = 49806,
SPELL_ENRAGE = 52470,
SPELL_INFECTED_BITE = 52469,
- H_SPELL_INFECTED_BITE = 59364,
SPELL_WEB_WRAP = 52086, //the spell is not working properly
SPELL_BLINDING_WEBS = 52524,
- H_SPELL_BLINDING_WEBS = 59365,
- SPELL_POSION_SPRAY = 52493,
- H_SPELL_POSION_SPRAY = 59366
+ SPELL_POSION_SPRAY = 52493
};
enum Mobs
@@ -69,7 +61,7 @@ enum Yells
SAY_SEND_GROUP = 5
};
-const Position SpawnPoint[] =
+Position const SpawnPoint[] =
{
{ 566.164f, 682.087f, 769.079f, 2.21657f },
{ 529.042f, 706.941f, 777.298f, 1.0821f },
@@ -81,444 +73,573 @@ const Position SpawnPoint[] =
{ 552.625f, 706.408f, 777.177f, 3.4383f }
};
+enum Events
+{
+ EVENT_SUMMON = 1,
+ EVENT_MIND_FLAY,
+ EVENT_CURSE_FATIGUE
+};
+
class boss_krik_thir : public CreatureScript
{
-public:
- boss_krik_thir() : CreatureScript("boss_krik_thir") { }
+ public:
+ boss_krik_thir() : CreatureScript("boss_krik_thir") { }
- struct boss_krik_thirAI : public ScriptedAI
- {
- boss_krik_thirAI(Creature* creature) : ScriptedAI(creature)
+ struct boss_krik_thirAI : public BossAI
{
- instance = creature->GetInstanceScript();
- }
+ boss_krik_thirAI(Creature* creature) : BossAI(creature, DATA_KRIKTHIR_THE_GATEWATCHER) { }
- InstanceScript* instance;
+ void Reset() OVERRIDE
+ {
+ _Reset();
+ }
- uint32 uiMindFlayTimer;
- uint32 uiCurseFatigueTimer;
- uint32 uiSummonTimer;
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ Talk(SAY_AGGRO);
+ _EnterCombat();
+ Summon();
- void Reset() OVERRIDE
- {
- uiMindFlayTimer = 15*IN_MILLISECONDS;
- uiCurseFatigueTimer = 12*IN_MILLISECONDS;
+ events.ScheduleEvent(EVENT_SUMMON, 15000);
+ events.ScheduleEvent(EVENT_MIND_FLAY, 15000);
+ events.ScheduleEvent(EVENT_CURSE_FATIGUE, 12000);
+ }
- instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, NOT_STARTED);
- }
+ void Summon()
+ {
+ for (uint8 i = 0; i < 8; i++)
+ {
+ me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[i], TEMPSUMMON_TIMED_DESPAWN, 25000);
+ uint32 summon_entry = (i == 4 || i == 5 || i == 6) ? NPC_SKITTERING_INFECTIOR : NPC_SKITTERING_SWARMER;
+ me->SummonCreature(summon_entry, SpawnPoint[i], TEMPSUMMON_TIMED_DESPAWN, 25000);
+ }
+ }
- void EnterCombat(Unit* /*who*/) OVERRIDE
- {
- Talk(SAY_AGGRO);
- Summon();
- uiSummonTimer = 15*IN_MILLISECONDS;
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
- instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, IN_PROGRESS);
- }
+ events.Update(diff);
- void Summon()
- {
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[0], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[0], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[1], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[1], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[2], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[2], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[3], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[3], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_INFECTIOR, SpawnPoint[4], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[4], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_INFECTIOR, SpawnPoint[5], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[5], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_INFECTIOR, SpawnPoint[6], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[6], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[7], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- me->SummonCreature(NPC_SKITTERING_SWARMER, SpawnPoint[7], TEMPSUMMON_TIMED_DESPAWN, 25*IN_MILLISECONDS);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void UpdateAI(uint32 diff) OVERRIDE
- {
- if (!UpdateVictim())
- return;
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SUMMON:
+ Summon();
+ events.ScheduleEvent(EVENT_SUMMON, 15000);
+ break;
+ case EVENT_MIND_FLAY:
+ DoCastVictim(SPELL_MIND_FLAY);
+ events.ScheduleEvent(EVENT_MIND_FLAY, 15000);
+ break;
+ case EVENT_CURSE_FATIGUE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_CURSE_OF_FATIGUE);
+ events.ScheduleEvent(EVENT_CURSE_FATIGUE, 10000);
+ break;
+ default:
+ break;
+ }
+ }
- if (uiSummonTimer <= diff)
- {
- Summon();
- uiSummonTimer = 15*IN_MILLISECONDS;
- } else uiSummonTimer -= diff;
+ if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10))
+ DoCast(me, SPELL_FRENZY, true);
- if (uiMindFlayTimer <= diff)
- {
- DoCastVictim(SPELL_MIND_FLAY);
- uiMindFlayTimer = 15*IN_MILLISECONDS;
- } else uiMindFlayTimer -= diff;
+ DoMeleeAttackIfReady();
+ }
- if (uiCurseFatigueTimer <= diff)
+ void JustDied(Unit* /*killer*/) OVERRIDE
{
- //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically."
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_CURSE_OF_FATIGUE);
- if (Unit* tankTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true))
- DoCast(tankTarget, SPELL_CURSE_OF_FATIGUE);
-
- uiCurseFatigueTimer = 10*IN_MILLISECONDS;
- } else uiCurseFatigueTimer -= diff;
-
- if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10))
- DoCast(me, SPELL_FRENZY, true);
-
- DoMeleeAttackIfReady();
- }
- void JustDied(Unit* /*killer*/) OVERRIDE
- {
- Talk(SAY_DEATH);
+ Talk(SAY_DEATH);
+ _JustDied();
+ }
- instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, DONE);
- }
+ void KilledUnit(Unit* victim) OVERRIDE
+ {
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ return;
- void KilledUnit(Unit* victim) OVERRIDE
- {
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
+ Talk(SAY_SLAY);
+ }
- Talk(SAY_SLAY);
- }
+ void JustSummoned(Creature* summoned) OVERRIDE
+ {
+ summoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
+ }
+ };
- void JustSummoned(Creature* summoned) OVERRIDE
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- summoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
+ return GetAzjolNerubAI<boss_krik_thirAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return GetInstanceAI<boss_krik_thirAI>(creature);
- }
};
class npc_skittering_infector : public CreatureScript
{
-public:
- npc_skittering_infector() : CreatureScript("npc_skittering_infector") { }
+ public:
+ npc_skittering_infector() : CreatureScript("npc_skittering_infector") { }
+
+ struct npc_skittering_infectorAI : public ScriptedAI
+ {
+ npc_skittering_infectorAI(Creature* creature) : ScriptedAI(creature) { }
- struct npc_skittering_infectorAI : public ScriptedAI
- {
- npc_skittering_infectorAI(Creature* creature) : ScriptedAI(creature) { }
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ DoCastAOE(SPELL_ACID_SPLASH);
+ }
+ };
- void JustDied(Unit* /*killer*/) OVERRIDE
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- //The spell is not working propperly
- DoCastVictim(SPELL_ACID_SPLASH, true);
+ return GetAzjolNerubAI<npc_skittering_infectorAI>(creature);
}
- };
+};
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_skittering_infectorAI(creature);
- }
+enum TrashEvents
+{
+ // Anubar Skrimisher
+ EVENT_ANUBAR_CHARGE,
+ EVENT_BACKSTAB,
+
+ // Anubar Shadowcaster
+ EVENT_SHADOW_BOLT,
+ EVENT_SHADOW_NOVA,
+
+ // Anubar Warrior
+ EVENT_STRIKE,
+ EVENT_CLEAVE,
+
+ // Watcher Gashra
+ EVENT_WEB_WRAP_GASHRA,
+ EVENT_INFECTED_BITE_GASHRA,
+
+ // Watcher Narjil
+ EVENT_WEB_WRAP_NARJIL,
+ EVENT_INFECTED_BITE_NARJIL,
+ EVENT_BINDING_WEBS,
+
+ // Watcher Silthik
+ EVENT_WEB_WRAP_SILTHIK,
+ EVENT_INFECTED_BITE_SILTHIK,
+ EVENT_POISON_SPRAY
};
class npc_anub_ar_skirmisher : public CreatureScript
{
-public:
- npc_anub_ar_skirmisher() : CreatureScript("npc_anub_ar_skirmisher") { }
-
- struct npc_anub_ar_skirmisherAI : public ScriptedAI
- {
- npc_anub_ar_skirmisherAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 uiChargeTimer;
- uint32 uiBackstabTimer;
+ public:
+ npc_anub_ar_skirmisher() : CreatureScript("npc_anub_ar_skirmisher") { }
- void Reset() OVERRIDE
+ struct npc_anub_ar_skirmisherAI : public ScriptedAI
{
- uiChargeTimer = 11*IN_MILLISECONDS;
- uiBackstabTimer = 7*IN_MILLISECONDS;
- }
+ npc_anub_ar_skirmisherAI(Creature* creature) : ScriptedAI(creature) { }
- void UpdateAI(uint32 diff) OVERRIDE
- {
- if (!UpdateVictim())
- return;
+ void Reset() OVERRIDE
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ events.ScheduleEvent(EVENT_ANUBAR_CHARGE, 11000);
+ events.ScheduleEvent(EVENT_BACKSTAB, 7000);
+ }
- if (uiChargeTimer <= diff)
+ void UpdateAI(uint32 diff) OVERRIDE
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
{
- DoResetThreat();
- me->AddThreat(target, 1.0f);
- DoCast(target, SPELL_CHARGE, true);
+ switch (eventId)
+ {
+ case EVENT_ANUBAR_CHARGE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ {
+ DoResetThreat();
+ me->AddThreat(target, 1.0f);
+ DoCast(target, SPELL_CHARGE, true);
+ }
+ events.ScheduleEvent(EVENT_ANUBAR_CHARGE, 15000);
+ break;
+ case EVENT_BACKSTAB:
+ DoCastVictim(SPELL_BACKSTAB);
+ events.ScheduleEvent(EVENT_BACKSTAB, 12000);
+ break;
+ default:
+ break;
+ }
}
- uiChargeTimer = 15*IN_MILLISECONDS;
- } else uiChargeTimer -= diff;
- if (uiBackstabTimer <= diff)
- {
- DoCastVictim(SPELL_BACKSTAB);
- uiBackstabTimer = 12*IN_MILLISECONDS;
- } else uiBackstabTimer -= diff;
+ DoMeleeAttackIfReady();
+ }
- DoMeleeAttackIfReady();
+ private:
+ EventMap events;
+ };
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetAzjolNerubAI<npc_anub_ar_skirmisherAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_anub_ar_skirmisherAI(creature);
- }
};
class npc_anub_ar_shadowcaster : public CreatureScript
{
-public:
- npc_anub_ar_shadowcaster() : CreatureScript("npc_anub_ar_shadowcaster") { }
-
- struct npc_anub_ar_shadowcasterAI : public ScriptedAI
- {
- npc_anub_ar_shadowcasterAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 uiShadowBoltTimer;
- uint32 uiShadowNovaTimer;
+ public:
+ npc_anub_ar_shadowcaster() : CreatureScript("npc_anub_ar_shadowcaster") { }
- void Reset() OVERRIDE
+ struct npc_anub_ar_shadowcasterAI : public ScriptedAI
{
- uiShadowBoltTimer = 6*IN_MILLISECONDS;
- uiShadowNovaTimer = 15*IN_MILLISECONDS;
- }
+ npc_anub_ar_shadowcasterAI(Creature* creature) : ScriptedAI(creature) { }
- void UpdateAI(uint32 diff) OVERRIDE
- {
- if (!UpdateVictim())
- return;
+ void Reset() OVERRIDE
+ {
+ events.Reset();
+ }
- if (uiShadowBoltTimer <= diff)
+ void EnterCombat(Unit* /*who*/) OVERRIDE
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_SHADOW_BOLT, true);
- uiShadowBoltTimer = 15*IN_MILLISECONDS;
- } else uiShadowBoltTimer -= diff;
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 6000);
+ events.ScheduleEvent(EVENT_SHADOW_NOVA, 15000);
+ }
- if (uiShadowNovaTimer <= diff)
+ void UpdateAI(uint32 diff) OVERRIDE
{
- DoCastVictim(SPELL_SHADOW_NOVA, true);
- uiShadowNovaTimer = 17*IN_MILLISECONDS;
- } else uiShadowNovaTimer -= diff;
+ if (!UpdateVictim())
+ return;
- DoMeleeAttackIfReady();
- }
- };
+ events.Update(diff);
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_anub_ar_shadowcasterAI(creature);
- }
-};
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
-class npc_anub_ar_warrior : public CreatureScript
-{
-public:
- npc_anub_ar_warrior() : CreatureScript("npc_anub_ar_warrior") { }
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOW_BOLT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_SHADOW_BOLT, true);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000);
+ break;
+ case EVENT_SHADOW_NOVA:
+ DoCastVictim(SPELL_SHADOW_NOVA, true);
+ events.ScheduleEvent(EVENT_SHADOW_NOVA, 17000);
+ break;
+ default:
+ break;
+ }
+ }
- struct npc_anub_ar_warriorAI : public ScriptedAI
- {
- npc_anub_ar_warriorAI(Creature* creature) : ScriptedAI(creature){ }
+ DoMeleeAttackIfReady();
+ }
- uint32 uiCleaveTimer;
- uint32 uiStrikeTimer;
+ private:
+ EventMap events;
+ };
- void Reset() OVERRIDE
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- uiCleaveTimer = 11*IN_MILLISECONDS;
- uiStrikeTimer = 6*IN_MILLISECONDS;
+ return GetAzjolNerubAI<npc_anub_ar_shadowcasterAI>(creature);
}
+};
+
+class npc_anub_ar_warrior : public CreatureScript
+{
+ public:
+ npc_anub_ar_warrior() : CreatureScript("npc_anub_ar_warrior") { }
- void UpdateAI(uint32 diff) OVERRIDE
+ struct npc_anub_ar_warriorAI : public ScriptedAI
{
- if (!UpdateVictim())
- return;
+ npc_anub_ar_warriorAI(Creature* creature) : ScriptedAI(creature) { }
- if (uiStrikeTimer <= diff)
+ void Reset() OVERRIDE
{
- DoCastVictim(SPELL_STRIKE, true);
- uiStrikeTimer = 15*IN_MILLISECONDS;
- } else uiStrikeTimer -= diff;
+ events.Reset();
+ }
- if (uiCleaveTimer <= diff)
+ void EnterCombat(Unit* /*who*/) OVERRIDE
{
- DoCastVictim(SPELL_CLEAVE, true);
- uiCleaveTimer = 17*IN_MILLISECONDS;
- } else uiCleaveTimer -= diff;
+ events.ScheduleEvent(EVENT_CLEAVE, 11000);
+ events.ScheduleEvent(EVENT_STRIKE, 6000);
+ }
- DoMeleeAttackIfReady();
- }
- };
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_anub_ar_warriorAI(creature);
- }
-};
+ events.Update(diff);
-class npc_watcher_gashra : public CreatureScript
-{
-public:
- npc_watcher_gashra() : CreatureScript("npc_watcher_gashra") { }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- struct npc_watcher_gashraAI : public ScriptedAI
- {
- npc_watcher_gashraAI(Creature* creature) : ScriptedAI(creature) { }
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_STRIKE, true);
+ events.ScheduleEvent(EVENT_CLEAVE, 15000);
+ break;
+ case EVENT_STRIKE:
+ DoCastVictim(SPELL_CLEAVE, true);
+ events.ScheduleEvent(EVENT_STRIKE, 17000);
+ break;
+ default:
+ break;
+ }
+ }
- uint32 uiWebWrapTimer;
- uint32 uiInfectedBiteTimer;
+ DoMeleeAttackIfReady();
+ }
- void Reset() OVERRIDE
- {
- uiWebWrapTimer = 11*IN_MILLISECONDS;
- uiInfectedBiteTimer = 4*IN_MILLISECONDS;
- }
+ private:
+ EventMap events;
+ };
- void EnterCombat(Unit* /*who*/) OVERRIDE
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- DoCast(me, SPELL_ENRAGE, true);
+ return GetAzjolNerubAI<npc_anub_ar_warriorAI>(creature);
}
+};
+
+class npc_watcher_gashra : public CreatureScript
+{
+ public:
+ npc_watcher_gashra() : CreatureScript("npc_watcher_gashra") { }
- void UpdateAI(uint32 diff) OVERRIDE
+ struct npc_watcher_gashraAI : public ScriptedAI
{
- if (!UpdateVictim())
- return;
+ npc_watcher_gashraAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = creature->GetInstanceScript();
+ }
- if (uiWebWrapTimer <= diff)
+ void Reset() OVERRIDE
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_WEB_WRAP, true);
- uiWebWrapTimer = 17*IN_MILLISECONDS;
- } else uiWebWrapTimer -= diff;
+ _events.Reset();
+ }
- if (uiInfectedBiteTimer <= diff)
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ DoCast(me, SPELL_ENRAGE, true);
+ _events.ScheduleEvent(EVENT_WEB_WRAP_GASHRA, 11000);
+ _events.ScheduleEvent(EVENT_INFECTED_BITE_GASHRA, 4000);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
{
- DoCastVictim(SPELL_INFECTED_BITE, true);
- uiInfectedBiteTimer = 15*IN_MILLISECONDS;
- } else uiInfectedBiteTimer -= diff;
+ Creature* krikthir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KRIKTHIR_THE_GATEWATCHER));
+ if (krikthir && krikthir->IsAlive())
+ krikthir->AI()->Talk(SAY_PREFIGHT);
+ }
- DoMeleeAttackIfReady();
- }
- };
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_watcher_gashraAI(creature);
- }
-};
+ _events.Update(diff);
-class npc_watcher_narjil : public CreatureScript
-{
-public:
- npc_watcher_narjil() : CreatureScript("npc_watcher_narjil") { }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- struct npc_watcher_narjilAI : public ScriptedAI
- {
- npc_watcher_narjilAI(Creature* creature) : ScriptedAI(creature) { }
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WEB_WRAP_GASHRA:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_WEB_WRAP, true);
+ _events.ScheduleEvent(EVENT_WEB_WRAP_GASHRA, 17000);
+ break;
+ case EVENT_INFECTED_BITE_GASHRA:
+ DoCastVictim(SPELL_INFECTED_BITE, true);
+ _events.ScheduleEvent(EVENT_INFECTED_BITE_GASHRA, 15000);
+ break;
+ default:
+ break;
+ }
+ }
- uint32 uiWebWrapTimer;
- uint32 uiInfectedBiteTimer;
- uint32 uiBindingWebsTimer;
+ DoMeleeAttackIfReady();
+ }
- void Reset() OVERRIDE
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- uiWebWrapTimer = 11*IN_MILLISECONDS;
- uiInfectedBiteTimer = 4*IN_MILLISECONDS;
- uiBindingWebsTimer = 17*IN_MILLISECONDS;
+ return GetAzjolNerubAI<npc_watcher_gashraAI>(creature);
}
+};
+
+class npc_watcher_narjil : public CreatureScript
+{
+ public:
+ npc_watcher_narjil() : CreatureScript("npc_watcher_narjil") { }
- void UpdateAI(uint32 diff) OVERRIDE
+ struct npc_watcher_narjilAI : public ScriptedAI
{
- if (!UpdateVictim())
- return;
+ npc_watcher_narjilAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = creature->GetInstanceScript();
+ }
- if (uiWebWrapTimer <= diff)
+ void Reset() OVERRIDE
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_WEB_WRAP, true);
- uiWebWrapTimer = 15*IN_MILLISECONDS;
- } else uiWebWrapTimer -= diff;
+ _events.Reset();
+ }
- if (uiInfectedBiteTimer <= diff)
+ void EnterCombat(Unit* /*who*/) OVERRIDE
{
- DoCastVictim(SPELL_INFECTED_BITE, true);
- uiInfectedBiteTimer = 11*IN_MILLISECONDS;
- } else uiInfectedBiteTimer -= diff;
+ _events.ScheduleEvent(EVENT_WEB_WRAP_NARJIL, 11000);
+ _events.ScheduleEvent(EVENT_INFECTED_BITE_NARJIL, 4000);
+ _events.ScheduleEvent(EVENT_BINDING_WEBS, 17000);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ Creature* krikthir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KRIKTHIR_THE_GATEWATCHER));
+ if (krikthir && krikthir->IsAlive())
+ krikthir->AI()->Talk(SAY_PREFIGHT);
+ }
- if (uiBindingWebsTimer <= diff)
+ void UpdateAI(uint32 diff) OVERRIDE
{
- DoCastVictim(SPELL_BLINDING_WEBS, true);
- uiBindingWebsTimer = 17*IN_MILLISECONDS;
- } else uiBindingWebsTimer -= diff;
+ if (!UpdateVictim())
+ return;
- DoMeleeAttackIfReady();
- }
- };
+ _events.Update(diff);
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_watcher_narjilAI(creature);
- }
-};
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
-class npc_watcher_silthik : public CreatureScript
-{
-public:
- npc_watcher_silthik() : CreatureScript("npc_watcher_silthik") { }
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WEB_WRAP_NARJIL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_WEB_WRAP, true);
+ _events.ScheduleEvent(EVENT_WEB_WRAP_NARJIL, 15000);
+ break;
+ case EVENT_INFECTED_BITE_NARJIL:
+ DoCastVictim(SPELL_INFECTED_BITE, true);
+ _events.ScheduleEvent(EVENT_INFECTED_BITE_NARJIL, 11000);
+ break;
+ case EVENT_BINDING_WEBS:
+ DoCastVictim(SPELL_BLINDING_WEBS, true);
+ _events.ScheduleEvent(EVENT_BINDING_WEBS, 17000);
+ break;
+ default:
+ break;
+ }
+ }
- struct npc_watcher_silthikAI : public ScriptedAI
- {
- npc_watcher_silthikAI(Creature* creature) : ScriptedAI(creature) { }
+ DoMeleeAttackIfReady();
+ }
- uint32 uiWebWrapTimer;
- uint32 uiInfectedBiteTimer;
- uint32 uiPoisonSprayTimer;
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ };
- void Reset() OVERRIDE
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- uiWebWrapTimer = 11*IN_MILLISECONDS;
- uiInfectedBiteTimer = 4*IN_MILLISECONDS;
- uiPoisonSprayTimer = 15*IN_MILLISECONDS;
+ return GetAzjolNerubAI<npc_watcher_narjilAI>(creature);
}
+};
+
+class npc_watcher_silthik : public CreatureScript
+{
+ public:
+ npc_watcher_silthik() : CreatureScript("npc_watcher_silthik") { }
- void UpdateAI(uint32 diff) OVERRIDE
+ struct npc_watcher_silthikAI : public ScriptedAI
{
- if (!UpdateVictim())
- return;
+ npc_watcher_silthikAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = creature->GetInstanceScript();
+ }
- if (uiWebWrapTimer <= diff)
+ void Reset() OVERRIDE
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_WEB_WRAP, true);
+ _events.Reset();
+ }
- uiWebWrapTimer = 15*IN_MILLISECONDS;
- } else uiWebWrapTimer -= diff;
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ _events.ScheduleEvent(EVENT_WEB_WRAP_SILTHIK, 11000);
+ _events.ScheduleEvent(EVENT_INFECTED_BITE_SILTHIK, 4000);
+ _events.ScheduleEvent(EVENT_POISON_SPRAY, 15000);
+ }
- if (uiInfectedBiteTimer <= diff)
+ void JustDied(Unit* /*killer*/) OVERRIDE
{
- DoCastVictim(SPELL_INFECTED_BITE, true);
- uiInfectedBiteTimer = 15*IN_MILLISECONDS;
- } else uiInfectedBiteTimer -= diff;
+ Creature* krikthir = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KRIKTHIR_THE_GATEWATCHER));
+ if (krikthir && krikthir->IsAlive())
+ krikthir->AI()->Talk(SAY_PREFIGHT);
+ }
- if (uiPoisonSprayTimer <= diff)
+ void UpdateAI(uint32 diff) OVERRIDE
{
- DoCastVictim(SPELL_POSION_SPRAY, true);
- uiPoisonSprayTimer = 17*IN_MILLISECONDS;
- } else uiPoisonSprayTimer -= diff;
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- }
- };
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WEB_WRAP_SILTHIK:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_WEB_WRAP, true);
+ _events.ScheduleEvent(EVENT_WEB_WRAP_SILTHIK, 15000);
+ break;
+ case EVENT_INFECTED_BITE_SILTHIK:
+ DoCastVictim(SPELL_INFECTED_BITE, true);
+ _events.ScheduleEvent(EVENT_INFECTED_BITE_SILTHIK, 11000);
+ break;
+ case EVENT_POISON_SPRAY:
+ DoCastVictim(SPELL_POSION_SPRAY, true);
+ _events.ScheduleEvent(EVENT_POISON_SPRAY, 17000);
+ break;
+ default:
+ break;
+ }
+ }
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_watcher_silthikAI(creature);
- }
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return GetAzjolNerubAI<npc_watcher_silthikAI>(creature);
+ }
};
class achievement_watch_him_die : public AchievementCriteriaScript