aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Main.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp46
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp39
-rw-r--r--src/server/game/Accounts/AccountMgr.h50
-rw-r--r--src/server/game/DataStores/DBCStores.cpp13
-rw-r--r--src/server/game/DataStores/DBCStores.h2
-rw-r--r--src/server/game/DataStores/DBCStructure.h14
-rw-r--r--src/server/game/DataStores/DBCfmt.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp39
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp31
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp3
-rw-r--r--src/server/game/Miscellaneous/Language.h27
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp6
-rw-r--r--src/server/game/Server/WorldSession.cpp35
-rw-r--r--src/server/game/Server/WorldSession.h3
-rw-r--r--src/server/game/Server/WorldSocket.cpp199
-rw-r--r--src/server/game/Server/WorldSocket.h43
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp9
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp114
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h9
-rw-r--r--src/server/game/Spells/SpellMgr.cpp2
-rw-r--r--src/server/game/Spells/SpellScript.cpp67
-rw-r--r--src/server/game/Spells/SpellScript.h72
-rw-r--r--src/server/game/World/World.cpp4
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp44
-rw-r--r--src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp112
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp58
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp515
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp26
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp111
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h19
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_sholazar_basin.cpp97
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp3
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h3
-rw-r--r--src/server/shared/Logging/Appender.cpp4
-rw-r--r--src/server/shared/Logging/Appender.h2
-rw-r--r--src/server/shared/Logging/AppenderConsole.cpp2
-rw-r--r--src/server/shared/Logging/AppenderConsole.h2
-rw-r--r--src/server/shared/Logging/AppenderDB.cpp16
-rw-r--r--src/server/shared/Logging/AppenderDB.h11
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp3
-rw-r--r--src/server/shared/Logging/AppenderFile.h2
-rw-r--r--src/server/shared/Logging/Log.cpp33
-rw-r--r--src/server/shared/Logging/Log.h4
-rw-r--r--src/server/worldserver/Master.cpp2
-rw-r--r--src/server/worldserver/RemoteAccess/RASocket.cpp2
-rw-r--r--src/server/worldserver/worldserver.conf.dist8
51 files changed, 1212 insertions, 716 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index f4f73e2c33d..c87df4ef7ab 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -134,8 +134,6 @@ extern int main(int argc, char **argv)
if (!StartDB())
return 1;
- sLog->SetRealmID(0); // ensure we've set realm to 0 (authserver realmid)
-
// Get the list of realms for the server
sRealmList->Initialize(ConfigMgr::GetIntDefault("RealmsStateUpdateDelay", 20));
if (sRealmList->size() == 0)
@@ -272,7 +270,7 @@ bool StartDB()
}
sLog->outInfo(LOG_FILTER_AUTHSERVER, "Started auth database connection pool.");
- sLog->EnableDBAppenders();
+ sLog->SetRealmId(0); // Enables DB appenders when realm is set.
return true;
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index c08e085e816..84c9dffabd2 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2121,18 +2121,20 @@ SmartScriptHolder SmartScript::CreateEvent(SMART_EVENT e, uint32 event_flags, ui
ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*= NULL*/)
{
- Unit* trigger = NULL;
+ Unit* scriptTrigger = NULL;
if (invoker)
- trigger = invoker;
+ scriptTrigger = invoker;
else if (Unit* tempLastInvoker = GetLastInvoker())
- trigger = tempLastInvoker;
+ scriptTrigger = tempLastInvoker;
+
+ WorldObject* baseObject = GetBaseObject();
ObjectList* l = new ObjectList();
switch (e.GetTargetType())
{
case SMART_TARGET_SELF:
- if (GetBaseObject())
- l->push_back(GetBaseObject());
+ if (baseObject)
+ l->push_back(baseObject);
break;
case SMART_TARGET_VICTIM:
if (me && me->getVictim())
@@ -2160,17 +2162,17 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
break;
case SMART_TARGET_NONE:
case SMART_TARGET_ACTION_INVOKER:
- if (trigger)
- l->push_back(trigger);
+ if (scriptTrigger)
+ l->push_back(scriptTrigger);
break;
case SMART_TARGET_ACTION_INVOKER_VEHICLE:
- if (trigger && trigger->GetVehicle() && trigger->GetVehicle()->GetBase())
- l->push_back(trigger->GetVehicle()->GetBase());
+ if (scriptTrigger && scriptTrigger->GetVehicle() && scriptTrigger->GetVehicle()->GetBase())
+ l->push_back(scriptTrigger->GetVehicle()->GetBase());
break;
case SMART_TARGET_INVOKER_PARTY:
- if (trigger)
+ if (scriptTrigger)
{
- if (Player* player = trigger->ToPlayer())
+ if (Player* player = scriptTrigger->ToPlayer())
{
if (Group* group = player->GetGroup())
{
@@ -2182,7 +2184,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
// this even if there is a group (thus the else-check), it will add the
// same player to the list twice. We don't want that to happen.
else
- l->push_back(trigger);
+ l->push_back(scriptTrigger);
}
}
break;
@@ -2198,7 +2200,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
if (me && me == *itr)
continue;
- if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && GetBaseObject()->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist))
+ if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist))
l->push_back(*itr);
}
@@ -2255,7 +2257,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
if (go && go == *itr)
continue;
- if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && GetBaseObject()->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist))
+ if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist))
l->push_back(*itr);
}
@@ -2265,13 +2267,13 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_CREATURE_GUID:
{
Creature* target = NULL;
- if (!trigger && !GetBaseObject())
+ if (!scriptTrigger && !baseObject)
{
sLog->outError(LOG_FILTER_SQL, "SMART_TARGET_CREATURE_GUID can not be used without invoker");
break;
}
- target = FindCreatureNear(trigger ? trigger : GetBaseObject(), e.target.unitGUID.dbGuid);
+ target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid);
if (target && (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry))
l->push_back(target);
@@ -2280,13 +2282,13 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_GAMEOBJECT_GUID:
{
GameObject* target = NULL;
- if (!trigger && !GetBaseObject())
+ if (!scriptTrigger && !baseObject)
{
sLog->outError(LOG_FILTER_SQL, "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker");
break;
}
- target = FindGameObjectNear(trigger ? trigger : GetBaseObject(), e.target.goGUID.dbGuid);
+ target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid);
if (target && (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry))
l->push_back(target);
@@ -2296,9 +2298,9 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
{
// will always return a valid pointer, even if empty list
ObjectList* units = GetWorldObjectsInDist((float)e.target.playerRange.maxDist);
- if (!units->empty() && GetBaseObject())
+ if (!units->empty() && baseObject)
for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
- if (IsPlayer(*itr) && GetBaseObject()->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist))
+ if (IsPlayer(*itr) && baseObject->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist))
l->push_back(*itr);
delete units;
@@ -2325,14 +2327,14 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
}
case SMART_TARGET_CLOSEST_CREATURE:
{
- Creature* target = GetClosestCreatureWithEntry(GetBaseObject(), e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100), e.target.closest.dead ? false : true);
+ Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100), e.target.closest.dead ? false : true);
if (target)
l->push_back(target);
break;
}
case SMART_TARGET_CLOSEST_GAMEOBJECT:
{
- GameObject* target = GetClosestGameObjectWithEntry(GetBaseObject(), e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100));
+ GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100));
if (target)
l->push_back(target);
break;
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 01ba222d93b..3c3eded1f68 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -24,10 +24,11 @@
#include "SHA1.h"
#include "WorldSession.h"
-namespace AccountMgr
+AccountMgr::AccountMgr()
{
+}
-AccountOpResult CreateAccount(std::string username, std::string password)
+AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password)
{
if (utf8length(username) > MAX_ACCOUNT_STR)
return AOR_NAME_TOO_LONG; // username's too long
@@ -52,7 +53,7 @@ AccountOpResult CreateAccount(std::string username, std::string password)
return AOR_OK; // everything's fine
}
-AccountOpResult DeleteAccount(uint32 accountId)
+AccountOpResult AccountMgr::DeleteAccount(uint32 accountId)
{
// Check if accounts exists
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID);
@@ -124,7 +125,7 @@ AccountOpResult DeleteAccount(uint32 accountId)
return AOR_OK;
}
-AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword)
+AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword)
{
// Check if accounts exists
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID);
@@ -154,7 +155,7 @@ AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::s
return AOR_OK;
}
-AccountOpResult ChangePassword(uint32 accountId, std::string newPassword)
+AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPassword)
{
std::string username;
@@ -177,7 +178,7 @@ AccountOpResult ChangePassword(uint32 accountId, std::string newPassword)
return AOR_OK;
}
-uint32 GetId(std::string const& username)
+uint32 AccountMgr::GetId(std::string const& username)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME);
stmt->setString(0, username);
@@ -186,7 +187,7 @@ uint32 GetId(std::string const& username)
return (result) ? (*result)[0].GetUInt32() : 0;
}
-uint32 GetSecurity(uint32 accountId)
+uint32 AccountMgr::GetSecurity(uint32 accountId)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL);
stmt->setUInt32(0, accountId);
@@ -195,7 +196,7 @@ uint32 GetSecurity(uint32 accountId)
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
}
-uint32 GetSecurity(uint32 accountId, int32 realmId)
+uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
stmt->setUInt32(0, accountId);
@@ -205,7 +206,7 @@ uint32 GetSecurity(uint32 accountId, int32 realmId)
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
}
-bool GetName(uint32 accountId, std::string& name)
+bool AccountMgr::GetName(uint32 accountId, std::string& name)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_USERNAME_BY_ID);
stmt->setUInt32(0, accountId);
@@ -220,7 +221,7 @@ bool GetName(uint32 accountId, std::string& name)
return false;
}
-bool CheckPassword(uint32 accountId, std::string password)
+bool AccountMgr::CheckPassword(uint32 accountId, std::string password)
{
std::string username;
@@ -238,7 +239,7 @@ bool CheckPassword(uint32 accountId, std::string password)
return (result) ? true : false;
}
-uint32 GetCharactersCount(uint32 accountId)
+uint32 AccountMgr::GetCharactersCount(uint32 accountId)
{
// check character count
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
@@ -248,7 +249,7 @@ uint32 GetCharactersCount(uint32 accountId)
return (result) ? (*result)[0].GetUInt64() : 0;
}
-bool normalizeString(std::string& utf8String)
+bool AccountMgr::normalizeString(std::string& utf8String)
{
wchar_t buffer[MAX_ACCOUNT_STR+1];
@@ -266,7 +267,7 @@ bool normalizeString(std::string& utf8String)
return WStrToUtf8(buffer, maxLength, utf8String);
}
-std::string CalculateShaPassHash(std::string const& name, std::string const& password)
+std::string AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password)
{
SHA1Hash sha;
sha.Initialize();
@@ -278,29 +279,27 @@ std::string CalculateShaPassHash(std::string const& name, std::string const& pas
return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength());
}
-bool IsPlayerAccount(uint32 gmlevel)
+bool AccountMgr::IsPlayerAccount(uint32 gmlevel)
{
return gmlevel == SEC_PLAYER;
}
-bool IsModeratorAccount(uint32 gmlevel)
+bool AccountMgr::IsModeratorAccount(uint32 gmlevel)
{
return gmlevel >= SEC_MODERATOR && gmlevel <= SEC_CONSOLE;
}
-bool IsGMAccount(uint32 gmlevel)
+bool AccountMgr::IsGMAccount(uint32 gmlevel)
{
return gmlevel >= SEC_GAMEMASTER && gmlevel <= SEC_CONSOLE;
}
-bool IsAdminAccount(uint32 gmlevel)
+bool AccountMgr::IsAdminAccount(uint32 gmlevel)
{
return gmlevel >= SEC_ADMINISTRATOR && gmlevel <= SEC_CONSOLE;
}
-bool IsConsoleAccount(uint32 gmlevel)
+bool AccountMgr::IsConsoleAccount(uint32 gmlevel)
{
return gmlevel == SEC_CONSOLE;
}
-
-} // Namespace AccountMgr
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index 7154cf0e867..c8de5688e73 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -21,6 +21,7 @@
#include "Define.h"
#include <string>
+#include <ace/Singleton.h>
enum AccountOpResult
{
@@ -34,27 +35,34 @@ enum AccountOpResult
#define MAX_ACCOUNT_STR 16
-namespace AccountMgr
+class AccountMgr
{
- AccountOpResult CreateAccount(std::string username, std::string password);
- AccountOpResult DeleteAccount(uint32 accountId);
- AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
- AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
- bool CheckPassword(uint32 accountId, std::string password);
-
- uint32 GetId(std::string const& username);
- uint32 GetSecurity(uint32 accountId);
- uint32 GetSecurity(uint32 accountId, int32 realmId);
- bool GetName(uint32 accountId, std::string& name);
- uint32 GetCharactersCount(uint32 accountId);
- std::string CalculateShaPassHash(std::string const& name, std::string const& password);
-
- bool normalizeString(std::string& utf8String);
- bool IsPlayerAccount(uint32 gmlevel);
- bool IsModeratorAccount(uint32 gmlevel);
- bool IsGMAccount(uint32 gmlevel);
- bool IsAdminAccount(uint32 gmlevel);
- bool IsConsoleAccount(uint32 gmlevel);
-}
+ friend class ACE_Singleton<AccountMgr, ACE_Null_Mutex>;
+ private:
+ AccountMgr();
+
+ public:
+ static AccountOpResult CreateAccount(std::string username, std::string password);
+ static AccountOpResult DeleteAccount(uint32 accountId);
+ static AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
+ static AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
+ static bool CheckPassword(uint32 accountId, std::string password);
+
+ static uint32 GetId(std::string const& username);
+ static uint32 GetSecurity(uint32 accountId);
+ static uint32 GetSecurity(uint32 accountId, int32 realmId);
+ static bool GetName(uint32 accountId, std::string& name);
+ static uint32 GetCharactersCount(uint32 accountId);
+
+ static std::string CalculateShaPassHash(std::string const& name, std::string const& password);
+ static bool normalizeString(std::string& utf8String);
+ static bool IsPlayerAccount(uint32 gmlevel);
+ static bool IsModeratorAccount(uint32 gmlevel);
+ static bool IsGMAccount(uint32 gmlevel);
+ static bool IsAdminAccount(uint32 gmlevel);
+ static bool IsConsoleAccount(uint32 gmlevel);
+};
+
+#define sAccountMgr ACE_Singleton<AccountMgr, ACE_Null_Mutex>::instance()
#endif
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 3fdff8e11d6..853ecb4e786 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -62,6 +62,7 @@ DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEnt
DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt);
DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt);
DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt);
+std::map<uint32, CharStartOutfitEntry const*> sCharStartOutfitMap;
DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
@@ -284,6 +285,10 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc");
+ for (uint32 i = 0; i < sCharStartOutfitStore.GetNumRows(); ++i)
+ if (CharStartOutfitEntry const* outfit = sCharStartOutfitStore.LookupEntry(i))
+ sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit;
+
LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");
@@ -872,3 +877,11 @@ uint32 GetLiquidFlags(uint32 liquidType)
return 0;
}
+CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender)
+{
+ std::map<uint32, CharStartOutfitEntry const*>::const_iterator itr = sCharStartOutfitMap.find(race | (class_ << 8) | (gender << 16));
+ if (itr == sCharStartOutfitMap.end())
+ return NULL;
+
+ return itr->second;
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index c77d0ee32f1..48a2cb3fe4e 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -65,6 +65,8 @@ uint32 GetLiquidFlags(uint32 liquidType);
PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level);
PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id);
+CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
+
extern DBCStorage <AchievementEntry> sAchievementStore;
extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index aa19863ec29..529c84744bd 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -629,13 +629,13 @@ struct BattlemasterListEntry
struct CharStartOutfitEntry
{
//uint32 Id; // 0
- uint32 RaceClassGender; // 1 (UNIT_FIELD_BYTES_0 & 0x00FFFFFF) comparable (0 byte = race, 1 byte = class, 2 byte = gender)
- int32 ItemId[MAX_OUTFIT_ITEMS]; // 2-13
- //int32 ItemDisplayId[MAX_OUTFIT_ITEMS]; // 14-25 not required at server side
- //int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 26-37 not required at server side
- //uint32 Unknown1; // 38, unique values (index-like with gaps ordered in other way as ids)
- //uint32 Unknown2; // 39
- //uint32 Unknown3; // 40
+ uint8 Race; // 1
+ uint8 Class; // 2
+ uint8 Gender; // 3
+ //uint8 Unused; // 4
+ int32 ItemId[MAX_OUTFIT_ITEMS]; // 5-28
+ //int32 ItemDisplayId[MAX_OUTFIT_ITEMS]; // 29-52 not required at server side
+ //int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 53-76 not required at server side
};
struct CharTitlesEntry
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index b7d966757c8..c82fdf868b3 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -31,7 +31,7 @@ char const AuctionHouseEntryfmt[] = "niiixxxxxxxxxxxxxxxxx";
char const BankBagSlotPricesEntryfmt[] = "ni";
char const BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
char const BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx";
-char const CharStartOutfitEntryfmt[] = "xniiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const CharTitlesEntryfmt[] = "nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char const ChrClassesEntryfmt[] = "nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 5b3969c9b9d..93d4796f21a 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2148,7 +2148,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
if (HasAura(*itr))
{
if (!reload)
- sLog->outError(LOG_FILTER_SQL, "Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetGUIDLow(), GetEntry(), *itr);
+ sLog->outError(LOG_FILTER_SQL, "Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetDBTableGUIDLow(), GetEntry(), *itr);
continue;
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 5fee82c5ece..073fadde314 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1120,7 +1120,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
addActionButton(action_itr->button, action_itr->action, action_itr->type);
// original items
- if (CharStartOutfitEntry const* oEntry = sCharStartOutfitStore.LookupEntry(RaceClassGender))
+ if (CharStartOutfitEntry const* oEntry = GetCharStartOutfitEntry(createInfo->Race, createInfo->Class, createInfo->Gender))
{
for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j)
{
@@ -3432,6 +3432,19 @@ void Player::AddNewMailDeliverTime(time_t deliver_time)
}
}
+void DeleteSpellFromAllPlayers(uint32 spellId)
+{
+ CharacterDatabaseStatements stmts[2] = {CHAR_DEL_INVALID_SPELL_SPELLS, CHAR_DEL_INVALID_SPELL_TALENTS};
+ for (uint8 i = 0; i < 2; i++)
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(stmts[i]);
+
+ stmt->setUInt32(0, spellId);
+
+ CharacterDatabase.Execute(stmt);
+ }
+}
+
bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
@@ -3442,11 +3455,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
{
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.", spellId);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_SPELL);
-
- stmt->setUInt32(0, spellId);
-
- CharacterDatabase.Execute(stmt);
+ DeleteSpellFromAllPlayers(spellId);
}
else
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addSpell: Non-existed in SpellStore spell #%u request.", spellId);
@@ -3461,11 +3470,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
{
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addTalent: Broken spell #%u learning not allowed, deleting for all characters in `character_talent`.", spellId);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_SPELL);
-
- stmt->setUInt32(0, spellId);
-
- CharacterDatabase.Execute(stmt);
+ DeleteSpellFromAllPlayers(spellId);
}
else
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addTalent: Broken spell #%u learning not allowed.", spellId);
@@ -3515,11 +3520,7 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent
{
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.", spellId);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_SPELL);
-
- stmt->setUInt32(0, spellId);
-
- CharacterDatabase.Execute(stmt);
+ DeleteSpellFromAllPlayers(spellId);
}
else
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addSpell: Non-existed in SpellStore spell #%u request.", spellId);
@@ -3534,11 +3535,7 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent
{
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addSpell: Broken spell #%u learning not allowed, deleting for all characters in `character_spell`.", spellId);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_SPELL);
-
- stmt->setUInt32(0, spellId);
-
- CharacterDatabase.Execute(stmt);
+ DeleteSpellFromAllPlayers(spellId);
}
else
sLog->outError(LOG_FILTER_SPELLS_AURAS, "Player::addSpell: Broken spell #%u learning not allowed.", spellId);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index fe0a1e88885..49b86cff864 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -14452,7 +14452,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
Unit* actionTarget = !isVictim ? target : this;
DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE);
- ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, NULL /*HealInfo*/);
+ HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL);
+ ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, &healInfo);
ProcTriggeredList procTriggered;
// Fill procTriggered list
@@ -14483,6 +14484,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
continue;
+ // AuraScript Hook
+ if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))
+ continue;
+
// Triggered spells not triggering additional spells
bool triggered = !(spellProto->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?
(procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false;
@@ -14531,15 +14536,21 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
SpellInfo const* spellInfo = i->aura->GetSpellInfo();
uint32 Id = i->aura->GetId();
+ AuraApplication const* aurApp = i->aura->GetApplicationOfTarget(GetGUID());
+
+ bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);
+
// For players set spell cooldown if need
uint32 cooldown = 0;
- if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
+ if (prepare && GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
cooldown = i->spellProcEvent->cooldown;
// Note: must SetCantProc(false) before return
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(true);
+ i->aura->CallScriptProcHandlers(aurApp, eventInfo);
+
// This bool is needed till separate aura effect procs are still here
bool handled = false;
if (HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled))
@@ -14558,6 +14569,13 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
ASSERT(triggeredByAura);
+ bool prevented = i->aura->CallScriptEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
+ if (prevented)
+ {
+ takeCharges = true;
+ continue;
+ }
+
switch (triggeredByAura->GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
@@ -14725,13 +14743,16 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
takeCharges = true;
break;
} // switch (triggeredByAura->GetAuraType())
+ i->aura->CallScriptAfterEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
} // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
} // if (!handled)
// Remove charge (aura can be removed by triggers)
- if (useCharges && takeCharges)
+ if (prepare && useCharges && takeCharges)
i->aura->DropCharge();
+ i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
+
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(false);
}
@@ -14752,7 +14773,7 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
if (!(*itr)->GetRemoveMode())
if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo))
{
- (*itr)->GetBase()->PrepareProcToTrigger();
+ (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo);
aurasTriggeringProc.push_back(*itr);
}
}
@@ -14764,7 +14785,7 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
{
if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo))
{
- itr->second->GetBase()->PrepareProcToTrigger();
+ itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo);
aurasTriggeringProc.push_back(itr->second);
}
}
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 619d819bf9b..30257797470 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2956,10 +2956,9 @@ void ObjectMgr::PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint3
if (count < -1)
sLog->outError(LOG_FILTER_SQL, "Invalid count %i specified on item %u be removed from original player create info (use -1)!", count, itemId);
- uint32 RaceClass = (race_) | (class_ << 8);
for (uint32 gender = 0; gender < GENDER_NONE; ++gender)
{
- if (CharStartOutfitEntry const* entry = sCharStartOutfitStore.LookupEntry(RaceClass | (gender << 16)))
+ if (CharStartOutfitEntry const* entry = GetCharStartOutfitEntry(race_, class_, gender))
{
bool found = false;
for (uint8 x = 0; x < MAX_OUTFIT_ITEMS; ++x)
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 292833c3955..35b0a6f8569 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -742,7 +742,32 @@ enum TrinityStrings
LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818,
LANG_CHANNEL_CITY = 819,
- // Room for in-game strings 820-999 not used
+
+ LANG_NPCINFO_GOSSIP = 820,
+ LANG_NPCINFO_QUESTGIVER = 821,
+ LANG_NPCINFO_TRAINER_CLASS = 822,
+ LANG_NPCINFO_TRAINER_PROFESSION = 823,
+ LANG_NPCINFO_VENDOR_AMMO = 824,
+ LANG_NPCINFO_VENDOR_FOOD = 825,
+ LANG_NPCINFO_VENDOR_POISON = 826,
+ LANG_NPCINFO_VENDOR_REAGENT = 827,
+ LANG_NPCINFO_REPAIR = 828,
+ LANG_NPCINFO_FLIGHTMASTER = 829,
+ LANG_NPCINFO_SPIRITHEALER = 830,
+ LANG_NPCINFO_SPIRITGUIDE = 831,
+ LANG_NPCINFO_INNKEEPER = 832,
+ LANG_NPCINFO_BANKER = 833,
+ LANG_NPCINFO_PETITIONER = 834,
+ LANG_NPCINFO_TABARDDESIGNER = 835,
+ LANG_NPCINFO_BATTLEMASTER = 836,
+ LANG_NPCINFO_AUCTIONEER = 837,
+ LANG_NPCINFO_STABLEMASTER = 838,
+ LANG_NPCINFO_GUILD_BANKER = 839,
+ LANG_NPCINFO_SPELLCLICK = 840,
+ LANG_NPCINFO_MAILBOX = 841,
+ LANG_NPCINFO_PLAYER_VEHICLE = 842,
+
+ // Room for in-game strings 843-999 not used
// Level 4 (CLI only commands)
LANG_COMMAND_EXIT = 1000,
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index a1ac4ccb679..1958774380e 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -103,7 +103,6 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T &owner)
return;
*/
-
D::_addUnitStateMove(owner);
i_targetReached = false;
i_recalculateTravel = false;
@@ -111,6 +110,11 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T &owner)
Movement::MoveSplineInit init(owner);
init.MoveTo(x, y, z);
init.SetWalk(((D*)this)->EnableWalking());
+ // Using the same condition for facing target as the one that is used for SetInFront on movement end
+ // - applies to ChaseMovementGenerator mostly
+ if (i_angle == 0.f)
+ init.SetFacing(i_target.getTarget());
+
init.Launch();
}
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 990963b8c4d..6a26dafde79 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -95,17 +95,28 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
/// WorldSession constructor
WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
-m_muteTime(mute_time), m_timeOutTime(0), _player(NULL), m_Socket(sock),
-_security(sec), _accountId(id), m_expansion(expansion), _logoutTime(0),
-m_inQueue(false), m_playerLoading(false), m_playerLogout(false),
-m_playerRecentlyLogout(false), m_playerSave(false),
-m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
-m_sessionDbLocaleIndex(locale),
-m_latency(0), m_TutorialsChanged(false), recruiterId(recruiter),
-isRecruiter(isARecruiter), timeLastWhoCommand(0)
+ m_muteTime(mute_time),
+ m_timeOutTime(0),
+ _player(NULL),
+ m_Socket(sock),
+ _security(sec),
+ _accountId(id),
+ m_expansion(expansion),
+ _warden(NULL),
+ _logoutTime(0),
+ m_inQueue(false),
+ m_playerLoading(false),
+ m_playerLogout(false),
+ m_playerRecentlyLogout(false),
+ m_playerSave(false),
+ m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
+ m_sessionDbLocaleIndex(locale),
+ m_latency(0),
+ m_TutorialsChanged(false),
+ recruiterId(recruiter),
+ isRecruiter(isARecruiter),
+ timeLastWhoCommand(0)
{
- _warden = NULL;
-
if (sock)
{
m_Address = sock->GetRemoteAddress();
@@ -727,8 +738,8 @@ void WorldSession::SetAccountData(AccountDataType type, time_t tm, std::string c
void WorldSession::SendAccountDataTimes(uint32 mask)
{
- WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4 + 1 + 4 + 8 * 4); // changed in WotLK
- data << uint32(time(NULL)); // unix time of something
+ WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4 + 1 + 4 + NUM_ACCOUNT_DATA_TYPES * 4);
+ data << uint32(time(NULL)); // Server time
data << uint8(1);
data << uint32(mask); // type mask
for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 39f5425d9df..abe048279db 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -181,9 +181,6 @@ class CharacterCreateInfo
/// Server side data
uint8 CharCount;
-
- private:
- virtual ~CharacterCreateInfo(){};
};
/// Player session in the World
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index b47f801ab29..b9955fac523 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -159,27 +159,29 @@ int WorldSocket::SendPacket(WorldPacket const& pct)
if (closing_)
return -1;
- // Dump outgoing packet.
+ // Dump outgoing packet
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(pct, SERVER_TO_CLIENT);
+ WorldPacket const* pkt = &pct;
+
+
if (m_Session)
- sLog->outTrace(LOG_FILTER_OPCODES, "S->C %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(pct.GetOpcode()).c_str());
+ sLog->outTrace(LOG_FILTER_OPCODES, "S->C: %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(pkt->GetOpcode()).c_str());
- // Create a copy of the original packet; this is to avoid issues if a hook modifies it.
- sScriptMgr->OnPacketSend(this, WorldPacket(pct));
+ sScriptMgr->OnPacketSend(this, *pkt);
- ServerPktHeader header(pct.size()+2, pct.GetOpcode());
+ ServerPktHeader header(pkt->size()+2, pkt->GetOpcode());
m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength());
- if (m_OutBuffer->space() >= pct.size() + header.getHeaderLength() && msg_queue()->is_empty())
+ if (m_OutBuffer->space() >= pkt->size() + header.getHeaderLength() && msg_queue()->is_empty())
{
// Put the packet on the buffer.
if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1)
ACE_ASSERT (false);
- if (!pct.empty())
- if (m_OutBuffer->copy((char*) pct.contents(), pct.size()) == -1)
+ if (!pkt->empty())
+ if (m_OutBuffer->copy((char*) pkt->contents(), pkt->size()) == -1)
ACE_ASSERT (false);
}
else
@@ -187,12 +189,12 @@ int WorldSocket::SendPacket(WorldPacket const& pct)
// Enqueue the packet.
ACE_Message_Block* mb;
- ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size() + header.getHeaderLength()), -1);
+ ACE_NEW_RETURN(mb, ACE_Message_Block(pkt->size() + header.getHeaderLength()), -1);
mb->copy((char*) header.header, header.getHeaderLength());
- if (!pct.empty())
- mb->copy((const char*)pct.contents(), pct.size());
+ if (!pkt->empty())
+ mb->copy((const char*)pkt->contents(), pkt->size());
if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
{
@@ -245,20 +247,7 @@ int WorldSocket::open (void *a)
m_Address = remote_addr.get_host_addr();
- // Send startup packet.
- WorldPacket packet (SMSG_AUTH_CHALLENGE, 24);
- packet << uint32(1); // 1...31
- packet << m_Seed;
-
- BigNumber seed1;
- seed1.SetRand(16 * 8);
- packet.append(seed1.AsByteArray(16), 16); // new encryption seeds
-
- BigNumber seed2;
- seed2.SetRand(16 * 8);
- packet.append(seed2.AsByteArray(16), 16); // new encryption seeds
-
- if (SendPacket(packet) == -1)
+ if (HandleSendAuthSession() == -1)
return -1;
// Register with ACE Reactor
@@ -461,7 +450,7 @@ int WorldSocket::Update (void)
int ret;
do
- ret = handle_output (get_handle());
+ ret = handle_output(get_handle());
while (ret > 0);
return ret;
@@ -469,18 +458,18 @@ int WorldSocket::Update (void)
int WorldSocket::handle_input_header (void)
{
- ACE_ASSERT (m_RecvWPct == NULL);
+ ACE_ASSERT(m_RecvWPct == NULL);
- ACE_ASSERT (m_Header.length() == sizeof(ClientPktHeader));
+ ACE_ASSERT(m_Header.length() == sizeof(ClientPktHeader));
- m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr(), sizeof(ClientPktHeader));
+ m_Crypt.DecryptRecv ((uint8*)m_Header.rd_ptr(), sizeof(ClientPktHeader));
- ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr());
+ ClientPktHeader& header = *((ClientPktHeader*)m_Header.rd_ptr());
EndianConvertReverse(header.size);
EndianConvert(header.cmd);
- if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240))
+ if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240))
{
Player* _player = m_Session ? m_Session->GetPlayer() : NULL;
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::handle_input_header(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %d, cmd: %d)",
@@ -495,11 +484,11 @@ int WorldSocket::handle_input_header (void)
header.size -= 4;
- ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1);
+ ACE_NEW_RETURN(m_RecvWPct, WorldPacket ((uint16)header.cmd, header.size), -1);
if (header.size > 0)
{
- m_RecvWPct->resize (header.size);
+ m_RecvWPct->resize(header.size);
m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size());
}
else
@@ -666,7 +655,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
ACE_ASSERT (new_pct);
// manage memory ;)
- ACE_Auto_Ptr<WorldPacket> aptr (new_pct);
+ ACE_Auto_Ptr<WorldPacket> aptr(new_pct);
const ACE_UINT16 opcode = new_pct->GetOpcode();
@@ -677,15 +666,16 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(*new_pct, CLIENT_TO_SERVER);
+ std::string opcodeName = GetOpcodeNameForLogging(opcode);
if (m_Session)
- sLog->outTrace(LOG_FILTER_OPCODES, "C->S %s %s", m_Session->GetPlayerInfo().c_str(), GetOpcodeNameForLogging(new_pct->GetOpcode()).c_str());
+ sLog->outTrace(LOG_FILTER_OPCODES, "C->S: %s %s", m_Session->GetPlayerInfo().c_str(), opcodeName.c_str());
try
{
switch (opcode)
{
case CMSG_PING:
- return HandlePing (*new_pct);
+ return HandlePing(*new_pct);
case CMSG_AUTH_SESSION:
if (m_Session)
{
@@ -694,18 +684,17 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
}
sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
- return HandleAuthSession (*new_pct);
+ return HandleAuthSession(*new_pct);
case CMSG_KEEP_ALIVE:
- sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", GetOpcodeNameForLogging(opcode).c_str());
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", opcodeName.c_str());
sScriptMgr->OnPacketReceive(this, WorldPacket(*new_pct));
return 0;
default:
{
- ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
-
+ ACE_GUARD_RETURN(LockType, Guard, m_SessionLock, -1);
if (!m_Session)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
+ sLog->outError(LOG_FILTER_OPCODES, "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
return -1;
}
@@ -715,7 +704,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
// OK, give the packet to WorldSession
aptr.release();
- // WARNINIG here we call it with locks held.
+ // WARNING here we call it with locks held.
// Its possible to cause deadlock if QueuePacket calls back
m_Session->QueuePacket(new_pct);
return 0;
@@ -724,8 +713,8 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
}
catch (ByteBufferException &)
{
- sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.",
- opcode, GetRemoteAddress().c_str(), m_Session ? int32(m_Session->GetAccountId()) : -1);
+ sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet %s from client %s, accountid=%i. Disconnected client.",
+ opcodeName.c_str(), GetRemoteAddress().c_str(), m_Session ? int32(m_Session->GetAccountId()) : -1);
new_pct->hexlike();
return -1;
}
@@ -733,36 +722,47 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
ACE_NOTREACHED (return 0);
}
+int WorldSocket::HandleSendAuthSession()
+{
+ WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
+ packet << uint32(1); // 1...31
+ packet << uint32(m_Seed);
+
+ BigNumber seed1;
+ seed1.SetRand(16 * 8);
+ packet.append(seed1.AsByteArray(16), 16); // new encryption seeds
+
+ BigNumber seed2;
+ seed2.SetRand(16 * 8);
+ packet.append(seed2.AsByteArray(16), 16); // new encryption seeds
+ return SendPacket(packet);
+}
+
int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
- // NOTE: ATM the socket is singlethread, have this in mind ...
uint8 digest[20];
uint32 clientSeed;
- uint32 unk2, unk3, unk5, unk6, unk7;
- uint64 unk4;
- uint32 BuiltNumberClient;
- uint32 id, security;
- //uint8 expansion = 0;
+ uint8 security;
+ uint32 id;
LocaleConstant locale;
std::string account;
SHA1Hash sha;
+ uint32 clientBuild;
+ uint32 unk2, unk3, unk5, unk6, unk7;
+ uint64 unk4;
BigNumber v, s, g, N;
WorldPacket packet, SendAddonPacked;
-
BigNumber k;
if (sWorld->IsClosed())
{
- packet.Initialize(SMSG_AUTH_RESPONSE, 1);
- packet << uint8(AUTH_REJECT);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_REJECT);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: World closed, denying client (%s).", GetRemoteAddress().c_str());
return -1;
}
// Read the content of the packet
- recvPacket >> BuiltNumberClient; // for now no use
+ recvPacket >> clientBuild;
recvPacket >> unk2;
recvPacket >> account;
recvPacket >> unk3;
@@ -772,7 +772,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket.read(digest, 20);
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u",
- BuiltNumberClient,
+ clientBuild,
unk2,
account.c_str(),
unk3,
@@ -788,11 +788,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Stop if the account is not found
if (!result)
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
-
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
return -1;
}
@@ -810,37 +806,30 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
v.SetHexStr(fields[4].GetCString());
s.SetHexStr (fields[5].GetCString());
- const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free()
- const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free()
+ const char* sStr = s.AsHexStr(); // Must be freed by OPENSSL_free()
+ const char* vStr = v.AsHexStr(); // Must be freed by OPENSSL_free()
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: (s, v) check s: %s v: %s",
- sStr,
- vStr);
+ sStr,
+ vStr);
- OPENSSL_free ((void*) sStr);
- OPENSSL_free ((void*) vStr);
+ OPENSSL_free((void*)sStr);
+ OPENSSL_free((void*)vStr);
///- Re-check ip locking (same check as in realmd).
if (fields[3].GetUInt8() == 1) // if ip is locked
{
if (strcmp (fields[2].GetCString(), GetRemoteAddress().c_str()))
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_FAILED);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_FAILED);
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs).");
return -1;
}
}
id = fields[0].GetUInt32();
- /*
- if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB
- security = SEC_ADMINISTRATOR;
- */
- k.SetHexStr (fields[1].GetCString());
+ k.SetHexStr(fields[1].GetCString());
int64 mutetime = fields[7].GetInt64();
//! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now.
@@ -866,10 +855,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Must be done before WorldSession is created
if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED) && os != "Win" && os != "OSX")
{
- packet.Initialize(SMSG_AUTH_RESPONSE, 1);
- packet << uint8(AUTH_REJECT);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_REJECT);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", GetRemoteAddress().c_str(), os.c_str());
return -1;
}
@@ -900,10 +886,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
if (banresult) // if account banned
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_BANNED);
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_BANNED);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
return -1;
}
@@ -911,13 +894,9 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Check locked state for server
AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit();
sLog->outDebug(LOG_FILTER_NETWORKIO, "Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security));
- if (AccountTypes(security) < allowedAccountType)
+ if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType)
{
- WorldPacket Packet (SMSG_AUTH_RESPONSE, 1);
- Packet << uint8 (AUTH_UNAVAILABLE);
-
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_UNAVAILABLE);
sLog->outInfo(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
return -1;
}
@@ -926,29 +905,25 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint32 t = 0;
uint32 seed = m_Seed;
- sha.UpdateData (account);
- sha.UpdateData ((uint8 *) & t, 4);
- sha.UpdateData ((uint8 *) & clientSeed, 4);
- sha.UpdateData ((uint8 *) & seed, 4);
- sha.UpdateBigNumbers (&k, NULL);
+ sha.UpdateData(account);
+ sha.UpdateData((uint8*)&t, 4);
+ sha.UpdateData((uint8*)&clientSeed, 4);
+ sha.UpdateData((uint8*)&seed, 4);
+ sha.UpdateBigNumbers(&k, NULL);
sha.Finalize();
std::string address = GetRemoteAddress();
- if (memcmp (sha.GetDigest(), digest, 20))
+ if (memcmp(sha.GetDigest(), digest, 20))
{
- packet.Initialize (SMSG_AUTH_RESPONSE, 1);
- packet << uint8 (AUTH_FAILED);
-
- SendPacket(packet);
-
+ SendAuthResponseError(AUTH_FAILED);
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str());
return -1;
}
sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
- account.c_str(),
- address.c_str());
+ account.c_str(),
+ address.c_str());
// Check if this user is by any chance a recruiter
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_RECRUITER);
@@ -971,7 +946,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
LoginDatabase.Execute(stmt);
// NOTE ATM the socket is single-threaded, have this in mind ...
- ACE_NEW_RETURN (m_Session, WorldSession (id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1);
+ ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter), -1);
m_Crypt.Init(&k);
@@ -985,10 +960,9 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Sleep this Network thread for
uint32 sleepTime = sWorld->getIntConfig(CONFIG_SESSION_ADD_DELAY);
- ACE_OS::sleep (ACE_Time_Value (0, sleepTime));
-
- sWorld->AddSession (m_Session);
+ ACE_OS::sleep(ACE_Time_Value(0, sleepTime));
+ sWorld->AddSession(m_Session);
return 0;
}
@@ -1049,7 +1023,14 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
}
}
- WorldPacket packet (SMSG_PONG, 4);
+ WorldPacket packet(SMSG_PONG, 4);
packet << ping;
return SendPacket(packet);
}
+
+void WorldSocket::SendAuthResponseError(uint8 code)
+{
+ WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
+ packet << uint8(code);
+ SendPacket(packet);
+} \ No newline at end of file
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 6b59647bb6c..2d5762ef60e 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -97,13 +97,13 @@ class WorldSocket : public WorldHandler
typedef ACE_Guard<LockType> GuardType;
/// Check if socket is closed.
- bool IsClosed (void) const;
+ bool IsClosed(void) const;
/// Close the socket.
- void CloseSocket (void);
+ void CloseSocket(void);
/// Get address of connected peer.
- const std::string& GetRemoteAddress (void) const;
+ const std::string& GetRemoteAddress(void) const;
/// Send A packet on the socket, this function is reentrant.
/// @param pct packet to send
@@ -111,57 +111,60 @@ class WorldSocket : public WorldHandler
int SendPacket(const WorldPacket& pct);
/// Add reference to this object.
- long AddReference (void);
+ long AddReference(void);
/// Remove reference to this object.
- long RemoveReference (void);
+ long RemoveReference(void);
/// things called by ACE framework.
/// Called on open, the void* is the acceptor.
- virtual int open (void *);
+ virtual int open(void *);
/// Called on failures inside of the acceptor, don't call from your code.
- virtual int close (u_long);
+ virtual int close(u_long);
/// Called when we can read from the socket.
- virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
+ virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE);
/// Called when the socket can write.
- virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE);
+ virtual int handle_output(ACE_HANDLE = ACE_INVALID_HANDLE);
/// Called when connection is closed or error happens.
- virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE,
ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
/// Called by WorldSocketMgr/ReactorRunnable.
- int Update (void);
+ int Update(void);
private:
/// Helper functions for processing incoming data.
- int handle_input_header (void);
- int handle_input_payload (void);
- int handle_input_missing_data (void);
+ int handle_input_header(void);
+ int handle_input_payload(void);
+ int handle_input_missing_data(void);
/// Help functions to mark/unmark the socket for output.
/// @param g the guard is for m_OutBufferLock, the function will release it
- int cancel_wakeup_output (GuardType& g);
- int schedule_wakeup_output (GuardType& g);
+ int cancel_wakeup_output(GuardType& g);
+ int schedule_wakeup_output(GuardType& g);
/// Drain the queue if its not empty.
- int handle_output_queue (GuardType& g);
+ int handle_output_queue(GuardType& g);
/// process one incoming packet.
/// @param new_pct received packet, note that you need to delete it.
- int ProcessIncoming (WorldPacket* new_pct);
+ int ProcessIncoming(WorldPacket* new_pct);
/// Called by ProcessIncoming() on CMSG_AUTH_SESSION.
- int HandleAuthSession (WorldPacket& recvPacket);
+ int HandleAuthSession(WorldPacket& recvPacket);
/// Called by ProcessIncoming() on CMSG_PING.
- int HandlePing (WorldPacket& recvPacket);
+ int HandlePing(WorldPacket& recvPacket);
+
+ int HandleSendAuthSession();
private:
+ void SendAuthResponseError(uint8);
/// Time in which the last ping was received
ACE_Time_Value m_LastPingTime;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 05da36d2ccc..e440b2a0fbd 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -992,7 +992,10 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const
void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
- // TODO: effect script handlers here
+ bool prevented = GetBase()->CallScriptEffectProcHandlers(const_cast<AuraEffect const*>(this), const_cast<AuraApplication const*>(aurApp), eventInfo);
+ if (prevented)
+ return;
+
switch (GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
@@ -1013,6 +1016,8 @@ void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
default:
break;
}
+
+ GetBase()->CallScriptAfterEffectProcHandlers(const_cast<AuraEffect const*>(this), const_cast<AuraApplication const*>(aurApp), eventInfo);
}
void AuraEffect::CleanupTriggeredSpells(Unit* target)
@@ -1572,7 +1577,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
// call functions which may have additional effects after chainging state of unit
// phase auras normally not expected at BG but anyway better check
- if (apply && (mode & AURA_EFFECT_HANDLE_REAL))
+ if (apply)
{
// drop flag at invisibiliy in bg
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 24a83c7990c..a41d25eae09 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1940,9 +1940,12 @@ void Aura::AddProcCooldown(uint32 /*msec*/)
//m_procCooldown = time(NULL) + msec;
}
-void Aura::PrepareProcToTrigger()
+void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
- // TODO: allow scripts to prevent charge drop/cooldown
+ bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);
+ if (!prepare)
+ return;
+
// take one charge, aura expiration will be handled in Aura::TriggerProcOnEvent (if needed)
if (IsUsingCharges())
{
@@ -1981,14 +1984,18 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI
return false;
// do checks using conditions table
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetSpellInfo()->Id);
+ ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId());
ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
return false;
+ // AuraScript Hook
+ bool check = const_cast<Aura*>(this)->CallScriptCheckProcHandlers(aurApp, eventInfo);
+ if (!check)
+ return false;
+
// TODO:
- // - add DoCheckProc() AuraScript hook
- // to allow additional requirements for procs
+ // do allow additional requirements for procs
// this is needed because this is the last moment in which you can prevent aura charge drop on proc
// and possibly a way to prevent default checks (if there're going to be any)
@@ -2052,14 +2059,14 @@ float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& event
void Aura::TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
- // TODO: OnProc hook here
+ CallScriptProcHandlers(const_cast<AuraApplication const*>(aurApp), eventInfo);
+
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (aurApp->HasEffect(i))
- // TODO: OnEffectProc hook here (allowing prevention of selected effects)
+ // OnEffectProc / AfterEffectProc hooks handled in AuraEffect::HandleProc()
GetEffect(i)->HandleProc(aurApp, eventInfo);
- // TODO: AfterEffectProc hook here
- // TODO: AfterProc hook here
+ CallScriptAfterProcHandlers(const_cast<AuraApplication const*>(aurApp), eventInfo);
// Remove aura if we've used last charge to proc
if (IsUsingCharges() && !GetCharges())
@@ -2355,6 +2362,95 @@ void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication con
}
}
+bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
+ std::list<AuraScript::CheckProcHandler>::iterator hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ if (!(*hookItr).Call(*scritr, eventInfo))
+ return false;
+ (*scritr)->_FinishScriptCall();
+ }
+ return true;
+}
+
+bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ bool prepare = true;
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
+ std::list<AuraScript::AuraProcHandler>::iterator effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
+ for (; effItr != effEndItr; ++effItr)
+ (*effItr).Call(*scritr, eventInfo);
+
+ if (prepare && (*scritr)->_IsDefaultActionPrevented())
+ prepare = false;
+ (*scritr)->_FinishScriptCall();
+ }
+ return prepare;
+}
+
+void Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
+ std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ (*hookItr).Call(*scritr, eventInfo);
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
+void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
+ std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
+ for (; hookItr != hookItrEnd; ++hookItr)
+ (*hookItr).Call(*scritr, eventInfo);
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
+bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ bool preventDefault = false;
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
+ std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
+ for (; effItr != effEndItr; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
+ (*effItr).Call(*scritr, aurEff, eventInfo);
+ }
+ if (!preventDefault)
+ preventDefault = (*scritr)->_IsDefaultActionPrevented();
+ (*scritr)->_FinishScriptCall();
+ }
+ return preventDefault;
+}
+
+void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
+ std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
+ for (; effItr != effEndItr; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
+ (*effItr).Call(*scritr, aurEff, eventInfo);
+ }
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
UnitAura::UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, uint64 casterGUID)
: Aura(spellproto, owner, caster, castItem, casterGUID)
{
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 88ebee18981..bd351548255 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -194,7 +194,7 @@ class Aura
void AddProcCooldown(uint32 msec);
bool IsUsingCharges() const { return m_isUsingCharges; }
void SetUsingCharges(bool val) { m_isUsingCharges = val; }
- void PrepareProcToTrigger();
+ void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo);
bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const;
float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
void TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo);
@@ -218,6 +218,13 @@ class Aura
void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount);
+ // Spell Proc Hooks
+ bool CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ bool CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ void CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ void CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ bool CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ void CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
std::list<AuraScript*> m_loadedScripts;
private:
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 582f13284bb..b258f01ccd5 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3633,6 +3633,8 @@ void SpellMgr::LoadDbcDataCorrections()
case 49345: // Call Emerald Drake
spellInfo->Effect[1] = 0;
break;
+ case 24314: // Threatening Gaze
+ spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP;
default:
break;
}
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index c29b08242a0..89ed223545f 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -470,7 +470,7 @@ WorldLocation* SpellScript::GetHitDest()
{
if (!IsInEffectHook())
{
- sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
+ sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitDest was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return NULL;
}
return m_spell->destTarget;
@@ -679,6 +679,30 @@ bool AuraScript::_Validate(SpellInfo const* entry)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+ for (std::list<CheckProcHandler>::iterator itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraProcHandler>::iterator itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraProcHandler>::iterator itr = OnProc.begin(); itr != OnProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraProcHandler>::iterator itr = AfterProc.begin(); itr != AfterProc.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<EffectProcHandler>::iterator itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr)
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+
+ for (std::list<EffectProcHandler>::iterator itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr)
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+
return _SpellScript::_Validate(entry);
}
@@ -818,6 +842,37 @@ void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* au
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount);
}
+AuraScript::CheckProcHandler::CheckProcHandler(AuraCheckProcFnType handlerScript)
+{
+ _HandlerScript = handlerScript;
+}
+
+bool AuraScript::CheckProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo)
+{
+ return (auraScript->*_HandlerScript)(eventInfo);
+}
+
+AuraScript::AuraProcHandler::AuraProcHandler(AuraProcFnType handlerScript)
+{
+ _HandlerScript = handlerScript;
+}
+
+void AuraScript::AuraProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo)
+{
+ (auraScript->*_HandlerScript)(eventInfo);
+}
+
+AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName)
+ : AuraScript::EffectBase(effIndex, effName)
+{
+ _EffectHandlerScript = effectHandlerScript;
+}
+
+void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+{
+ (auraScript->*_EffectHandlerScript)(aurEff, eventInfo);
+}
+
bool AuraScript::_Load(Aura* aura)
{
m_aura = aura;
@@ -853,6 +908,8 @@ bool AuraScript::_IsDefaultActionPrevented()
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
+ case AURA_SCRIPT_HOOK_PREPARE_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
return m_defaultActionPrevented;
default:
ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place");
@@ -869,6 +926,8 @@ void AuraScript::PreventDefaultAction()
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
+ case AURA_SCRIPT_HOOK_PREPARE_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
m_defaultActionPrevented = true;
break;
default:
@@ -1051,6 +1110,12 @@ Unit* AuraScript::GetTarget() const
case AURA_SCRIPT_HOOK_EFFECT_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
+ case AURA_SCRIPT_HOOK_CHECK_PROC:
+ case AURA_SCRIPT_HOOK_PREPARE_PROC:
+ case AURA_SCRIPT_HOOK_PROC:
+ case AURA_SCRIPT_HOOK_AFTER_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
+ case AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC:
return m_auraApplication->GetTarget();
default:
sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId);
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 5791c701c07..6f1df2560dc 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -428,14 +428,22 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_SPLIT,
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
AURA_SCRIPT_HOOK_DISPEL,
- AURA_SCRIPT_HOOK_AFTER_DISPEL
+ AURA_SCRIPT_HOOK_AFTER_DISPEL,
+ // Spell Proc Hooks
+ AURA_SCRIPT_HOOK_CHECK_PROC,
+ AURA_SCRIPT_HOOK_PREPARE_PROC,
+ AURA_SCRIPT_HOOK_PROC,
+ AURA_SCRIPT_HOOK_EFFECT_PROC,
+ AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC,
+ AURA_SCRIPT_HOOK_AFTER_PROC,
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE, */
};
+/*
#define HOOK_AURA_EFFECT_START HOOK_AURA_EFFECT_APPLY
#define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1
#define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START
-
+*/
class AuraScript : public _SpellScript
{
// internal use classes & functions
@@ -453,6 +461,9 @@ class AuraScript : public _SpellScript
typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \
typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \
typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \
+ typedef bool(CLASSNAME::*AuraCheckProcFnType)(ProcEventInfo&); \
+ typedef void(CLASSNAME::*AuraProcFnType)(ProcEventInfo&); \
+ typedef void(CLASSNAME::*AuraEffectProcFnType)(AuraEffect const*, ProcEventInfo&); \
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
@@ -552,6 +563,30 @@ class AuraScript : public _SpellScript
private:
AuraEffectSplitFnType pEffectHandlerScript;
};
+ class CheckProcHandler
+ {
+ public:
+ CheckProcHandler(AuraCheckProcFnType handlerScript);
+ bool Call(AuraScript* auraScript, ProcEventInfo& eventInfo);
+ private:
+ AuraCheckProcFnType _HandlerScript;
+ };
+ class AuraProcHandler
+ {
+ public:
+ AuraProcHandler(AuraProcFnType handlerScript);
+ void Call(AuraScript* auraScript, ProcEventInfo& eventInfo);
+ private:
+ AuraProcFnType _HandlerScript;
+ };
+ class EffectProcHandler : public EffectBase
+ {
+ public:
+ EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName);
+ void Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo);
+ private:
+ AuraEffectProcFnType _EffectHandlerScript;
+ };
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \
@@ -565,6 +600,9 @@ class AuraScript : public _SpellScript
class EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectManaShieldFunction : public AuraScript::EffectManaShieldHandler { public: EffectManaShieldFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectManaShieldHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) {} }; \
+ class CheckProcHandlerFunction : public AuraScript::CheckProcHandler { public: CheckProcHandlerFunction(AuraCheckProcFnType handlerScript) : AuraScript::CheckProcHandler((AuraScript::AuraCheckProcFnType)handlerScript) {} }; \
+ class AuraProcHandlerFunction : public AuraScript::AuraProcHandler { public: AuraProcHandlerFunction(AuraProcFnType handlerScript) : AuraScript::AuraProcHandler((AuraScript::AuraProcFnType)handlerScript) {} }; \
+ class EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: EffectProcHandlerFunction(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)effectHandlerScript, effIndex, effName) {} }; \
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
@@ -695,6 +733,36 @@ class AuraScript : public _SpellScript
HookList<EffectSplitHandler> OnEffectSplit;
#define AuraEffectSplitFn(F, I) EffectSplitFunction(&F, I)
+ // executed when aura checks if it can proc
+ // example: DoCheckProc += AuraCheckProcFn(class::function);
+ // where function is: bool function (ProcEventInfo& eventInfo);
+ HookList<CheckProcHandler> DoCheckProc;
+ #define AuraCheckProcFn(F) CheckProcHandlerFunction(&F)
+
+ // executed before aura procs (possibility to prevent charge drop/cooldown)
+ // example: DoPrepareProc += AuraProcFn(class::function);
+ // where function is: void function (ProcEventInfo& eventInfo);
+ HookList<AuraProcHandler> DoPrepareProc;
+ // executed when aura procs
+ // example: OnProc += AuraProcFn(class::function);
+ // where function is: void function (ProcEventInfo& eventInfo);
+ HookList<AuraProcHandler> OnProc;
+ // executed after aura proced
+ // example: AfterProc += AuraProcFn(class::function);
+ // where function is: void function (ProcEventInfo& eventInfo);
+ HookList<AuraProcHandler> AfterProc;
+ #define AuraProcFn(F) AuraProcHandlerFunction(&F)
+
+ // executed when aura effect procs
+ // example: OnEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // where function is: void function (AuraEffect const* aurEff, ProcEventInfo& procInfo);
+ HookList<EffectProcHandler> OnEffectProc;
+ // executed after aura effect proced
+ // example: AfterEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // where function is: void function (AuraEffect const* aurEff, ProcEventInfo& procInfo);
+ HookList<EffectProcHandler> AfterEffectProc;
+ #define AuraEffectProcFn(F, I, N) EffectProcHandlerFunction(&F, I, N)
+
// AuraScript interface - hook/effect execution manipulators
// prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented)
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 068bca2692f..2536ad6f0b9 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1781,7 +1781,9 @@ void World::SetInitialWorldSettings()
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
sLog->outInfo(LOG_FILTER_WORLDSERVER, "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
- sLog->EnableDBAppenders();
+
+ if (uint32 realmId = ConfigMgr::GetIntDefault("RealmID", 0)) // 0 reserved for auth
+ sLog->SetRealmId(realmId);
}
void World::DetectDBCLang()
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 8679e288282..7ccd5ed1177 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -33,6 +33,42 @@ EndScriptData */
#include "Player.h"
#include "Pet.h"
+struct NpcFlagText
+{
+ uint32 flag;
+ int32 text;
+};
+
+#define NPCFLAG_COUNT 24
+
+const NpcFlagText npcFlagTexts[NPCFLAG_COUNT] =
+{
+ { UNIT_NPC_FLAG_AUCTIONEER, LANG_NPCINFO_AUCTIONEER },
+ { UNIT_NPC_FLAG_BANKER, LANG_NPCINFO_BANKER },
+ { UNIT_NPC_FLAG_BATTLEMASTER, LANG_NPCINFO_BATTLEMASTER },
+ { UNIT_NPC_FLAG_FLIGHTMASTER, LANG_NPCINFO_FLIGHTMASTER },
+ { UNIT_NPC_FLAG_GOSSIP, LANG_NPCINFO_GOSSIP },
+ { UNIT_NPC_FLAG_GUILD_BANKER, LANG_NPCINFO_GUILD_BANKER },
+ { UNIT_NPC_FLAG_INNKEEPER, LANG_NPCINFO_INNKEEPER },
+ { UNIT_NPC_FLAG_PETITIONER, LANG_NPCINFO_PETITIONER },
+ { UNIT_NPC_FLAG_PLAYER_VEHICLE, LANG_NPCINFO_PLAYER_VEHICLE },
+ { UNIT_NPC_FLAG_QUESTGIVER, LANG_NPCINFO_QUESTGIVER },
+ { UNIT_NPC_FLAG_REPAIR, LANG_NPCINFO_REPAIR },
+ { UNIT_NPC_FLAG_SPELLCLICK, LANG_NPCINFO_SPELLCLICK },
+ { UNIT_NPC_FLAG_SPIRITGUIDE, LANG_NPCINFO_SPIRITGUIDE },
+ { UNIT_NPC_FLAG_SPIRITHEALER, LANG_NPCINFO_SPIRITHEALER },
+ { UNIT_NPC_FLAG_STABLEMASTER, LANG_NPCINFO_STABLEMASTER },
+ { UNIT_NPC_FLAG_TABARDDESIGNER, LANG_NPCINFO_TABARDDESIGNER },
+ { UNIT_NPC_FLAG_TRAINER, LANG_NPCINFO_TRAINER },
+ { UNIT_NPC_FLAG_TRAINER_CLASS, LANG_NPCINFO_TRAINER_CLASS },
+ { UNIT_NPC_FLAG_TRAINER_PROFESSION, LANG_NPCINFO_TRAINER_PROFESSION },
+ { UNIT_NPC_FLAG_VENDOR, LANG_NPCINFO_VENDOR },
+ { UNIT_NPC_FLAG_VENDOR_AMMO, LANG_NPCINFO_VENDOR_AMMO },
+ { UNIT_NPC_FLAG_VENDOR_FOOD, LANG_NPCINFO_VENDOR_FOOD },
+ { UNIT_NPC_FLAG_VENDOR_POISON, LANG_NPCINFO_VENDOR_POISON },
+ { UNIT_NPC_FLAG_VENDOR_REAGENT, LANG_NPCINFO_VENDOR_REAGENT }
+};
+
class npc_commandscript : public CommandScript
{
public:
@@ -619,11 +655,9 @@ public:
handler->PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ()));
handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str());
- if (npcflags & UNIT_NPC_FLAG_VENDOR)
- handler->SendSysMessage(LANG_NPCINFO_VENDOR);
-
- if (npcflags & UNIT_NPC_FLAG_TRAINER)
- handler->SendSysMessage(LANG_NPCINFO_TRAINER);
+ for (uint8 i = 0; i < NPCFLAG_COUNT; i++)
+ if (npcflags & npcFlagTexts[i].flag)
+ handler->PSendSysMessage(npcFlagTexts[i].text, npcFlagTexts[i].flag);
return true;
}
diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp
index b0a2d48d053..19660cec4af 100644
--- a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp
+++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp
@@ -64,6 +64,12 @@ enum eMisc
KIRTONOS_PATH = 105061
};
+Position const PosMove[2] =
+{
+ { 299.4884f, 92.76137f, 105.6335f, 0.0f },
+ { 314.8673f, 90.30210f, 101.6459f, 0.0f }
+};
+
class boss_kirtonos_the_herald : public CreatureScript
{
public: boss_kirtonos_the_herald() : CreatureScript("boss_kirtonos_the_herald") { }
@@ -74,15 +80,11 @@ class boss_kirtonos_the_herald : public CreatureScript
void Reset()
{
- _introEvent = 0;
- _introTimer = 0;
_Reset();
}
void EnterCombat(Unit* /*who*/)
{
- _introTimer = 0;
- _introEvent = 0;
events.ScheduleEvent(EVENT_SWOOP, urand(8000, 8000));
events.ScheduleEvent(EVENT_WING_FLAP, urand(15000, 15000));
events.ScheduleEvent(EVENT_PIERCE_ARMOR, urand(18000, 18000));
@@ -120,12 +122,10 @@ class boss_kirtonos_the_herald : public CreatureScript
void IsSummonedBy(Unit* /*summoner*/)
{
+ events.ScheduleEvent(INTRO_1, 500);
me->SetDisableGravity(true);
me->SetReactState(REACT_PASSIVE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- _introEvent = INTRO_1;
- _introTimer = 1;
- _currentPoint = 0;
Talk(EMOTE_SUMMONED);
}
@@ -138,68 +138,58 @@ class boss_kirtonos_the_herald : public CreatureScript
{
if (type == WAYPOINT_MOTION_TYPE && id == POINT_KIRTONOS_LAND)
{
- _introTimer = 1500;
- _introEvent = INTRO_2;
+ events.ScheduleEvent(INTRO_2, 1500);
}
}
void UpdateAI(uint32 const diff)
{
- if (_introEvent)
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent() && !UpdateVictim())
{
- if (_introTimer <= diff)
+ switch (eventId)
{
- switch (_introEvent)
- {
- case INTRO_1:
- me->GetMotionMaster()->MovePath(KIRTONOS_PATH, false);
- _introEvent = 0;
- break;
- case INTRO_2:
- me->GetMotionMaster()->MovePoint(0, 299.4884f, 92.76137f, 105.6335f);
- _introTimer = 1000;
- _introEvent = INTRO_3;
- break;
- case INTRO_3:
- if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_GATE_KIRTONOS)))
- gate->SetGoState(GO_STATE_READY);
- me->SetFacingTo(0.01745329f);
- _introTimer = 3000;
- _introEvent = INTRO_4;
- break;
- case INTRO_4:
- if (GameObject* brazier = me->GetMap()->GetGameObject(instance->GetData64(GO_BRAZIER_OF_THE_HERALD)))
- brazier->SetGoState(GO_STATE_READY);
- me->SetWalk(true);
- me->SetDisableGravity(false);
- DoCast(me, SPELL_KIRTONOS_TRANSFORM);
- me->SetCanFly(false);
- _introTimer = 1000;
- _introEvent = INTRO_5;
- break;
- case INTRO_5:
- me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
- me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_KIRTONOS_STAFF));
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
- me->SetReactState(REACT_AGGRESSIVE);
- _introTimer = 5000;
- _introEvent = INTRO_6;
- case INTRO_6:
- me->GetMotionMaster()->MovePoint(0, 314.8673f, 90.3021f, 101.6459f);
- _introTimer = 0;
- _introEvent = 0;
+ case INTRO_1:
+ me->GetMotionMaster()->MovePath(KIRTONOS_PATH, false);
+ break;
+ case INTRO_2:
+ me->GetMotionMaster()->MovePoint(0, PosMove[0]);
+ events.ScheduleEvent(INTRO_3, 1000);
+ break;
+ case INTRO_3:
+ if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_GATE_KIRTONOS)))
+ gate->SetGoState(GO_STATE_READY);
+ me->SetFacingTo(0.01745329f);
+ events.ScheduleEvent(INTRO_4, 3000);
+ break;
+ case INTRO_4:
+ if (GameObject* brazier = me->GetMap()->GetGameObject(instance->GetData64(GO_BRAZIER_OF_THE_HERALD)))
+ brazier->SetGoState(GO_STATE_READY);
+ me->SetWalk(true);
+ me->SetDisableGravity(false);
+ DoCast(me, SPELL_KIRTONOS_TRANSFORM);
+ me->SetCanFly(false);
+ events.ScheduleEvent(INTRO_5, 1000);
+ break;
+ case INTRO_5:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_KIRTONOS_STAFF));
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ events.ScheduleEvent(INTRO_6, 5000);
+ break;
+ case INTRO_6:
+ me->GetMotionMaster()->MovePoint(0, PosMove[1]);
+ break;
+ default:
break;
- }
}
- else
- _introTimer -= diff;
}
if (!UpdateVictim())
return;
- events.Update(diff);
-
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -257,11 +247,6 @@ class boss_kirtonos_the_herald : public CreatureScript
DoMeleeAttackIfReady();
}
-
- private:
- uint8 _introEvent;
- uint32 _introTimer;
- uint32 _currentPoint;
};
CreatureAI* GetAI(Creature* creature) const
@@ -280,6 +265,11 @@ enum Brazier_Of_The_Herald
SOUND_SCREECH = 557
};
+Position const PosSummon[1] =
+{
+ { 315.028f, 70.53845f, 102.1496f, 0.3859715f }
+};
+
class go_brazier_of_the_herald : public GameObjectScript
{
public:
@@ -289,7 +279,7 @@ class go_brazier_of_the_herald : public GameObjectScript
{
go->UseDoorOrButton();
go->PlayDirectSound(SOUND_SCREECH, 0);
- player->SummonCreature(NPC_KIRTONOS, 315.028f, 70.53845f, 102.1496f, 0.3859715f, TEMPSUMMON_DEAD_DESPAWN, 900000);
+ player->SummonCreature(NPC_KIRTONOS, PosSummon[0], TEMPSUMMON_DEAD_DESPAWN, 900000);
return true;
}
};
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
index 1334d587464..51aab7c20d0 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
@@ -79,11 +79,7 @@ class boss_arlokk : public CreatureScript
struct boss_arlokkAI : public BossAI
{
- boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) {}
-
- uint32 summonCount;
- // Unit* markedTarget;
- uint64 markedTargetGUID;
+ boss_arlokkAI(Creature* creature) : BossAI(creature, DATA_ARLOKK) { }
void Reset()
{
@@ -113,13 +109,15 @@ class boss_arlokk : public CreatureScript
void JustReachedHome()
{
- if (instance)
- instance->SetData(DATA_ARLOKK, NOT_STARTED);
+ instance->SetBossState(DATA_ARLOKK, NOT_STARTED);
me->DespawnOrUnsummon();
}
void DoSummonPhanters()
{
+ if (summonCount > 30)
+ return;
+
if (markedTargetGUID)
Talk(SAY_FEAST_PANTHER, markedTargetGUID);
me->SummonCreature(NPC_ZULIAN_PROWLER, PosSummonProwlers[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
@@ -152,7 +150,8 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 15000, 0, PHASE_ONE);
break;
case EVENT_MARK:
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_MARK);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_MARK);
events.ScheduleEvent(EVENT_MARK, 15000, 0, PHASE_ONE);
break;
case EVENT_CLEAVE:
@@ -164,8 +163,7 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_GOUGE, urand(17000, 27000), 0, PHASE_TWO);
break;
case EVENT_SUMMON:
- if (summonCount <= 30)
- DoSummonPhanters();
+ DoSummonPhanters();
events.ScheduleEvent(EVENT_SUMMON, 5000);
break;
case EVENT_VANISH:
@@ -176,21 +174,21 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_VISIBLE, 6000);
break;
case EVENT_VISIBLE:
- {
- me->SetDisplayId(MODEL_ID_PANTHER);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
- me->UpdateDamagePhysical(BASE_ATTACK);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- AttackStart(target);
- events.ScheduleEvent(EVENT_VANISH, 39000);
- events.ScheduleEvent(EVENT_CLEAVE, 0, PHASE_TWO);
- events.ScheduleEvent(EVENT_GOUGE, 14000, 0, PHASE_TWO);
- events.SetPhase(PHASE_TWO);
- break;
- }
+ {
+ me->SetDisplayId(MODEL_ID_PANTHER);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ const CreatureTemplate* cinfo = me->GetCreatureTemplate();
+ me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
+ me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
+ me->UpdateDamagePhysical(BASE_ATTACK);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ AttackStart(target);
+ events.ScheduleEvent(EVENT_VANISH, 39000);
+ events.ScheduleEvent(EVENT_CLEAVE, 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_GOUGE, 14000, 0, PHASE_TWO);
+ events.SetPhase(PHASE_TWO);
+ break;
+ }
default:
break;
}
@@ -198,11 +196,15 @@ class boss_arlokk : public CreatureScript
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 summonCount;
+ uint64 markedTargetGUID;
};
CreatureAI* GetAI(Creature* creature) const
{
- return new boss_arlokkAI(creature);
+ return GetZulGurubAI<boss_arlokkAI>(creature);
}
};
@@ -214,9 +216,9 @@ class go_gong_of_bethekk : public GameObjectScript
{
if (InstanceScript* instance = go->GetInstanceScript())
{
- if (instance->GetData(DATA_ARLOKK) == DONE || instance->GetData(DATA_ARLOKK) == IN_PROGRESS)
+ if (instance->GetBossState(DATA_ARLOKK) == DONE || instance->GetBossState(DATA_ARLOKK) == IN_PROGRESS)
return true;
- instance->SetData(DATA_ARLOKK, IN_PROGRESS);
+ instance->SetBossState(DATA_ARLOKK, IN_PROGRESS);
return true;
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
index 8003f4a1ed7..68aac7547df 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
@@ -90,15 +90,15 @@ class boss_hakkar : public CreatureScript
events.ScheduleEvent(EVENT_CAUSE_INSANITY, 17000);
events.ScheduleEvent(EVENT_WILL_OF_HAKKAR, 17000);
events.ScheduleEvent(EVENT_ENRAGE, 600000);
- if (instance->GetData(DATA_JEKLIK) != DONE)
+ if (instance->GetBossState(DATA_JEKLIK) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_JEKLIK, 4000);
- if (instance->GetData(DATA_VENOXIS) != DONE)
+ if (instance->GetBossState(DATA_VENOXIS) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_VENOXIS, 7000);
- if (instance->GetData(DATA_MARLI) != DONE)
+ if (instance->GetBossState(DATA_MARLI) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000);
- if (instance->GetData(DATA_THEKAL) != DONE)
+ if (instance->GetBossState(DATA_THEKAL) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_THEKAL, 8000);
- if (instance->GetData(DATA_ARLOKK) != DONE)
+ if (instance->GetBossState(DATA_ARLOKK) != DONE)
events.ScheduleEvent(EVENT_ASPECT_OF_ARLOKK, 18000);
Talk(SAY_AGGRO);
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
index 7f19962e719..dc02c895327 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
@@ -271,7 +271,7 @@ class mob_batrider : public CreatureScript
{
if (instance)
{
- if (instance->GetData(DATA_JEKLIK) == DONE)
+ if (instance->GetBossState(DATA_JEKLIK) == DONE)
{
me->setDeathState(JUST_DIED);
me->RemoveCorpse();
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
index 258dda26c11..e402480609b 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
@@ -25,6 +25,9 @@ EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
+#include "SpellAuras.h"
+#include "SpellScript.h"
#include "zulgurub.h"
enum Says
@@ -32,23 +35,73 @@ enum Says
SAY_AGGRO = 0,
SAY_DING_KILL = 1,
SAY_WATCH = 2,
- SAY_WATCH_WHISPER = 3, // is this text for real? easter egg?
+ SAY_WATCH_WHISPER = 3,
+ SAY_OHGAN_DEAD = 4,
SAY_GRATS_JINDO = 0,
};
enum Spells
{
- SPELL_CHARGE = 24408,
- SPELL_CLEAVE = 7160,
+ SPELL_CHARGE = 24408, // seen
+ SPELL_OVERPOWER = 24407, // Seen
SPELL_FEAR = 29321,
- SPELL_WHIRLWIND = 15589,
- SPELL_MORTAL_STRIKE = 16856,
- SPELL_ENRAGE = 24318,
- SPELL_WATCH = 24314,
- SPELL_LEVEL_UP = 24312,
- SPELL_SWIFT_ORANGE_RAPTOR = 23243,
- // Ohgans Spell
- SPELL_SUNDERARMOR = 24317
+ SPELL_WHIRLWIND = 13736, // Triggers 15589
+ SPELL_MORTAL_STRIKE = 16856, // Seen
+ SPELL_FRENZY = 24318, // seen
+ SPELL_WATCH = 24314, // seen 24315, 24316
+ SPELL_WATCH_CHARGE = 24315, // Triggers 24316
+ SPELL_LEVEL_UP = 24312 //
+};
+
+enum Events
+{
+ EVENT_CHECK_SPEAKER = 1,
+ EVENT_CHECK_START = 2,
+ EVENT_STARTED = 3,
+ EVENT_OVERPOWER = 4,
+ EVENT_MORTAL_STRIKE = 5,
+ EVENT_WHIRLWIND = 6,
+ EVENT_CHECK_OHGAN = 7,
+ EVENT_WATCH_PLAYER = 8,
+ EVENT_CHARGE_PLAYER = 9
+};
+
+enum Misc
+{
+ MODEL_OHGAN_MOUNT = 15271,
+ PATH_MANDOKIR = 492861,
+ POINT_MANDOKIR_END = 24,
+ CHAINED_SPIRT_COUNT = 20
+};
+
+Position const PosSummonChainedSpirits[CHAINED_SPIRT_COUNT] =
+{
+ { -12167.17f, -1979.330f, 133.0992f, 2.268928f },
+ { -12262.74f, -1953.394f, 133.5496f, 0.593412f },
+ { -12176.89f, -1983.068f, 133.7841f, 2.129302f },
+ { -12226.45f, -1977.933f, 132.7982f, 1.466077f },
+ { -12204.74f, -1890.431f, 135.7569f, 4.415683f },
+ { -12216.70f, -1891.806f, 136.3496f, 4.677482f },
+ { -12236.19f, -1892.034f, 134.1041f, 5.044002f },
+ { -12248.24f, -1893.424f, 134.1182f, 5.270895f },
+ { -12257.36f, -1897.663f, 133.1484f, 5.462881f },
+ { -12265.84f, -1903.077f, 133.1649f, 5.654867f },
+ { -12158.69f, -1972.707f, 133.8751f, 2.408554f },
+ { -12178.82f, -1891.974f, 134.1786f, 3.944444f },
+ { -12193.36f, -1890.039f, 135.1441f, 4.188790f },
+ { -12275.59f, -1932.845f, 134.9017f, 0.174533f },
+ { -12273.51f, -1941.539f, 136.1262f, 0.314159f },
+ { -12247.02f, -1963.497f, 133.9476f, 0.872665f },
+ { -12238.68f, -1969.574f, 133.6273f, 1.134464f },
+ { -12192.78f, -1982.116f, 132.6966f, 1.919862f },
+ { -12210.81f, -1979.316f, 133.8700f, 1.797689f },
+ { -12283.51f, -1924.839f, 133.5170f, 0.069813f }
+};
+
+Position const PosMandokir[2] =
+{
+ { -12167.8f, -1927.25f, 153.73f, 3.76991f },
+ { -12197.86f, -1949.392f, 130.2745f, 0.0f }
};
class boss_mandokir : public CreatureScript
@@ -57,298 +110,319 @@ class boss_mandokir : public CreatureScript
struct boss_mandokirAI : public BossAI
{
- boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) {}
-
- uint32 KillCount;
- uint32 Watch_Timer;
- uint32 TargetInRange;
- uint32 Cleave_Timer;
- uint32 Whirlwind_Timer;
- uint32 Fear_Timer;
- uint32 MortalStrike_Timer;
- uint32 Check_Timer;
- float targetX;
- float targetY;
- float targetZ;
-
- InstanceScript* instance;
-
- bool endWatch;
- bool someWatched;
- bool RaptorDead;
- bool CombatStart;
- bool SpeakerDead;
-
- uint64 WatchTarget;
+ boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) { }
void Reset()
{
- KillCount = 0;
- Watch_Timer = 33000;
- Cleave_Timer = 7000;
- Whirlwind_Timer = 20000;
- Fear_Timer = 1000;
- MortalStrike_Timer = 1000;
- Check_Timer = 1000;
-
- targetX = 0.0f;
- targetY = 0.0f;
- targetZ = 0.0f;
- TargetInRange = 0;
-
- WatchTarget = 0;
-
- someWatched = false;
- endWatch = false;
- RaptorDead = false;
- CombatStart = false;
- SpeakerDead = false;
-
- DoCast(me, 23243);
+ if (me->GetPositionZ() > 140.0f)
+ {
+ _Reset();
+ killCount = 0;
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
+ events.ScheduleEvent(EVENT_CHECK_START, 1000);
+ if (Creature* speaker = Creature::GetCreature(*me, instance->GetData64(NPC_VILEBRANCH_SPEAKER)))
+ if (!speaker->isAlive())
+ speaker->Respawn(true);
+ }
+ summons.DespawnAll();
+ me->Mount(MODEL_OHGAN_MOUNT);
}
void JustDied(Unit* /*killer*/)
{
- _JustDied();
+ // Do not want to unsummon Ohgan
+ for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
+ if (Creature* unsummon = Creature::GetCreature(*me, chainedSpirtGUIDs[i]))
+ unsummon->DespawnOrUnsummon();
+ instance->SetBossState(DATA_MANDOKIR, DONE);
+ instance->SaveToDB();
}
- void KilledUnit(Unit* victim)
+ void EnterCombat(Unit* /*who*/)
{
- if (victim->GetTypeId() == TYPEID_PLAYER)
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_OVERPOWER, urand(7000, 9000));
+ events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000));
+ events.ScheduleEvent(EVENT_WHIRLWIND, urand(24000, 30000));
+ events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
+ events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(13000, 15000));
+ events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(33000, 38000));
+ me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
+ Talk(SAY_AGGRO);
+ me->Dismount();
+ // Summon Ohgan (Spell missing) TEMP HACK
+ me->SummonCreature(NPC_OHGAN, me->GetPositionX()-3, me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
+ // Summon Chained Spirits
+ for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
{
- ++KillCount;
-
- if (KillCount == 3)
- {
- Talk(SAY_DING_KILL);
-
- if (instance)
- {
- uint64 JindoGUID = instance->GetData64(DATA_JINDO);
- if (JindoGUID)
- {
- if (Creature* jTemp = Creature::GetCreature(*me, JindoGUID))
- {
- if (jTemp->isAlive())
- jTemp->AI()->Talk(SAY_GRATS_JINDO);
- }
- }
- }
- DoCast(me, SPELL_LEVEL_UP, true);
- KillCount = 0;
- }
+ Creature* chainedSpirt = me->SummonCreature(NPC_CHAINED_SPIRT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
+ chainedSpirtGUIDs[i] = chainedSpirt->GetGUID();
}
+ DoZoneInCombat();
}
- void EnterCombat(Unit* /*who*/)
+ void KilledUnit(Unit* victim)
{
- _EnterCombat();
- Talk(SAY_AGGRO);
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (++killCount == 3)
+ {
+ Talk(SAY_DING_KILL);
+ if (Creature* jindo = Creature::GetCreature(*me, instance->GetData64(DATA_JINDO)))
+ if (jindo->isAlive())
+ jindo->AI()->Talk(SAY_GRATS_JINDO);
+ DoCast(me, SPELL_LEVEL_UP, true);
+ killCount = 0;
+ }
}
- void UpdateAI(const uint32 diff)
+ void MovementInform(uint32 type, uint32 id)
{
- if (!SpeakerDead)
+ if (type == WAYPOINT_MOTION_TYPE)
{
- if (!me->FindNearestCreature(NPC_SPEAKER, 100.0f, true))
+ me->SetWalk(false);
+ if (id == POINT_MANDOKIR_END)
{
- me->GetMotionMaster()->MovePoint(0, -12196.3f, -1948.37f, 130.36f);
- SpeakerDead = true;
+ me->SetHomePosition(PosMandokir[0]);
+ instance->SetBossState(DATA_MANDOKIR, NOT_STARTED);
+ me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe.
}
}
+ }
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE && SpeakerDead)
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ void UpdateAI(uint32 const diff)
+ {
+ events.Update(diff);
if (!UpdateVictim())
- return;
-
- if (me->getVictim() && me->isAlive())
{
- if (!CombatStart)
+ if (instance->GetBossState(DATA_MANDOKIR) == NOT_STARTED || instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
{
- //At combat Start Mandokir is mounted so we must unmount it first
- me->Dismount();
-
- //And summon his raptor
- me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
- CombatStart = true;
- }
-
- if (Watch_Timer <= diff) //Every 20 Sec Mandokir will check this
- {
- if (WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him
+ while (uint32 eventId = events.ExecuteEvent())
{
- Unit* unit = Unit::GetUnit(*me, WatchTarget);
-
- if (unit && (
- targetX != unit->GetPositionX() ||
- targetY != unit->GetPositionY() ||
- targetZ != unit->GetPositionZ() ||
- unit->isInCombat()))
+ switch (eventId)
{
- if (me->IsWithinMeleeRange(unit))
- {
- DoCast(unit, 24316);
- }
- else
- {
- DoCast(unit, SPELL_CHARGE);
- //me->SendMonsterMove(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), 0, true, 1);
- AttackStart(unit);
- }
+ case EVENT_CHECK_START:
+ if (instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
+ {
+ me->GetMotionMaster()->MovePoint(0, PosMandokir[1].m_positionX, PosMandokir[1].m_positionY, PosMandokir[1].m_positionZ);
+ events.ScheduleEvent(EVENT_STARTED, 6000);
+ }
+ else
+ events.ScheduleEvent(EVENT_CHECK_START, 1000);
+ break;
+ case EVENT_STARTED:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
+ me->GetMotionMaster()->MovePath(PATH_MANDOKIR, false);
+ break;
+ default:
+ break;
}
}
- someWatched = false;
- Watch_Timer = 20000;
- } else Watch_Timer -= diff;
-
- if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target
- {
- if (Unit* p = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- Talk(SAY_WATCH, p->GetGUID());
- DoCast(p, SPELL_WATCH);
- WatchTarget = p->GetGUID();
- someWatched = true;
- endWatch = true;
- }
}
+ return;
+ }
- if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position
- {
- Unit* unit = Unit::GetUnit(*me, WatchTarget);
- if (unit)
- {
- targetX = unit->GetPositionX();
- targetY = unit->GetPositionY();
- targetZ = unit->GetPositionZ();
- }
- endWatch = false;
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (!someWatched)
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- //Cleave
- if (Cleave_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_CLEAVE);
- Cleave_Timer = 7000;
- } else Cleave_Timer -= diff;
-
- //Whirlwind
- if (Whirlwind_Timer <= diff)
- {
+ case EVENT_OVERPOWER:
+ DoCastVictim(SPELL_OVERPOWER, true);
+ events.ScheduleEvent(EVENT_OVERPOWER, urand(6000, 12000));
+ break;
+ case EVENT_MORTAL_STRIKE:
+ if (me->getVictim() && me->getVictim()->HealthBelowPct(50))
+ DoCastVictim(SPELL_MORTAL_STRIKE, true);
+ events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000));
+ break;
+ case EVENT_WHIRLWIND:
DoCast(me, SPELL_WHIRLWIND);
- Whirlwind_Timer = 18000;
- } else Whirlwind_Timer -= diff;
-
- //If more then 3 targets in melee range mandokir will cast fear
- if (Fear_Timer <= diff)
- {
- TargetInRange = 0;
-
- std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
- for (; i != me->getThreatManager().getThreatList().end(); ++i)
+ events.ScheduleEvent(EVENT_WHIRLWIND, urand(22000, 26000));
+ break;
+ case EVENT_CHECK_OHGAN:
+ if (instance->GetBossState(DATA_OHGAN) == DONE)
{
- Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid());
- if (unit && me->IsWithinMeleeRange(unit))
- ++TargetInRange;
+ DoCast(me, SPELL_FRENZY);
+ Talk(SAY_OHGAN_DEAD);
}
-
- if (TargetInRange > 3)
- DoCast(me->getVictim(), SPELL_FEAR);
-
- Fear_Timer = 4000;
- } else Fear_Timer -=diff;
-
- //Mortal Strike if target below 50% hp
- if (me->getVictim() && me->getVictim()->HealthBelowPct(50))
- {
- if (MortalStrike_Timer <= diff)
- {
- DoCast(me->getVictim(), SPELL_MORTAL_STRIKE);
- MortalStrike_Timer = 15000;
- } else MortalStrike_Timer -= diff;
- }
- }
- //Checking if Ohgan is dead. If yes Mandokir will enrage.
- if (Check_Timer <= diff)
- {
- if (instance)
- {
- if (instance->GetData(DATA_OHGAN) == DONE)
+ else
+ events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
+ break;
+ case EVENT_WATCH_PLAYER:
+ if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
- if (!RaptorDead)
- {
- DoCast(me, SPELL_ENRAGE);
- RaptorDead = true;
- }
+ DoCast(player, SPELL_WATCH);
+ Talk(SAY_WATCH, player->GetGUID());
}
- }
-
- Check_Timer = 1000;
- } else Check_Timer -= diff;
-
- DoMeleeAttackIfReady();
+ events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(12000, 15000));
+ break;
+ case EVENT_CHARGE_PLAYER:
+ DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true), SPELL_CHARGE);
+ events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(22000, 30000));
+ break;
+ default:
+ break;
+ }
}
+
+ DoMeleeAttackIfReady();
}
+
+ private:
+ uint8 killCount;
+ uint64 chainedSpirtGUIDs[CHAINED_SPIRT_COUNT];
};
CreatureAI* GetAI(Creature* creature) const
{
- return new boss_mandokirAI(creature);
+ return GetZulGurubAI<boss_mandokirAI>(creature);
}
};
// Ohgan
+
+enum OhganSpells
+{
+ SPELL_SUNDERARMOR = 24317
+};
+
class mob_ohgan : public CreatureScript
{
public: mob_ohgan() : CreatureScript("mob_ohgan") {}
struct mob_ohganAI : public ScriptedAI
{
- mob_ohganAI(Creature* creature) : ScriptedAI(creature)
+ mob_ohganAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
+
+ void Reset()
{
- instance = creature->GetInstanceScript();
+ SunderArmor_Timer = 5000;
}
+ void EnterCombat(Unit* /*who*/) {}
+
+ void JustDied(Unit* /*killer*/)
+ {
+ instance->SetBossState(DATA_OHGAN, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ // Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ if (SunderArmor_Timer <= diff)
+ {
+ DoCastVictim(SPELL_SUNDERARMOR, true);
+ SunderArmor_Timer = urand(10000, 15000);
+ } else SunderArmor_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
uint32 SunderArmor_Timer;
InstanceScript* instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetZulGurubAI<mob_ohganAI>(creature);
+ }
+};
+
+enum VilebranchSpells
+{
+ SPELL_DEMORALIZING_SHOUT = 13730,
+ SPELL_CLEAVE = 15284
+};
+
+class mob_vilebranch_speaker : public CreatureScript
+{
+ public: mob_vilebranch_speaker() : CreatureScript("mob_vilebranch_speaker") {}
+
+ struct mob_vilebranch_speakerAI : public ScriptedAI
+ {
+ mob_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
void Reset()
{
- SunderArmor_Timer = 5000;
+ demoralizing_Shout_Timer = urand (2000, 4000);
+ cleave_Timer = urand (5000, 8000);
}
void EnterCombat(Unit* /*who*/) {}
void JustDied(Unit* /*killer*/)
{
- if (instance)
- instance->SetData(DATA_OHGAN, DONE);
+ instance->SetBossState(DATA_MANDOKIR, SPECIAL);
}
- void UpdateAI (const uint32 diff)
+ void UpdateAI(const uint32 diff)
{
- //Return since we have no target
+ // Return since we have no target
if (!UpdateVictim())
return;
- //SunderArmor_Timer
- if (SunderArmor_Timer <= diff)
+ if (demoralizing_Shout_Timer <= diff)
{
- DoCast(me->getVictim(), SPELL_SUNDERARMOR);
- SunderArmor_Timer = urand(10000, 15000);
- } else SunderArmor_Timer -= diff;
+ DoCast(me, SPELL_DEMORALIZING_SHOUT);
+ demoralizing_Shout_Timer = urand(22000, 30000);
+ } else demoralizing_Shout_Timer -= diff;
+
+ if (cleave_Timer <= diff)
+ {
+ DoCastVictim(SPELL_CLEAVE, true);
+ cleave_Timer = urand(6000, 9000);
+ } else cleave_Timer -= diff;
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 demoralizing_Shout_Timer;
+ uint32 cleave_Timer;
+ InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const
{
- return new mob_ohganAI(creature);
+ return new mob_vilebranch_speakerAI(creature);
+ }
+};
+
+class spell_threatening_gaze : public SpellScriptLoader
+{
+ public:
+ spell_threatening_gaze() : SpellScriptLoader("spell_threatening_gaze") { }
+
+ class spell_threatening_gaze_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_threatening_gaze_AuraScript);
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ if(Unit* target = GetTarget())
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
+ caster->CastSpell(target, SPELL_WATCH_CHARGE);
+ }
+
+ void Register()
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_threatening_gaze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_threatening_gaze_AuraScript();
}
};
@@ -356,5 +430,6 @@ void AddSC_boss_mandokir()
{
new boss_mandokir();
new mob_ohgan();
+ new mob_vilebranch_speaker();
+ new spell_threatening_gaze();
}
-
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
index ab45162fc35..61eb695719a 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
@@ -113,7 +113,7 @@ class boss_thekal : public CreatureScript
void JustReachedHome()
{
if (instance)
- instance->SetData(DATA_THEKAL, NOT_STARTED);
+ instance->SetBossState(DATA_THEKAL, NOT_STARTED);
}
void UpdateAI(uint32 const diff)
@@ -167,7 +167,7 @@ class boss_thekal : public CreatureScript
{
if (instance)
{
- if (instance->GetData(DATA_LORKHAN) == SPECIAL)
+ if (instance->GetBossState(DATA_LORKHAN) == SPECIAL)
{
//Resurrect LorKhan
if (Unit* pLorKhan = Unit::GetUnit(*me, instance->GetData64(DATA_LORKHAN)))
@@ -180,7 +180,7 @@ class boss_thekal : public CreatureScript
}
}
- if (instance->GetData(DATA_ZATH) == SPECIAL)
+ if (instance->GetBossState(DATA_ZATH) == SPECIAL)
{
//Resurrect Zath
if (Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH)))
@@ -189,7 +189,7 @@ class boss_thekal : public CreatureScript
pZath->setFaction(14);
pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
pZath->SetFullHealth();
- instance->SetData(DATA_ZATH, DONE);
+ instance->SetBossState(DATA_ZATH, DONE);
}
}
}
@@ -241,7 +241,7 @@ class boss_thekal : public CreatureScript
me->SetStandState(UNIT_STAND_STATE_SLEEP);
me->AttackStop();
if (instance)
- instance->SetData(DATA_THEKAL, SPECIAL);
+ instance->SetBossState(DATA_THEKAL, SPECIAL);
WasDead=true;
}
}
@@ -288,7 +288,7 @@ class mob_zealot_lorkhan : public CreatureScript
FakeDeath = false;
if (instance)
- instance->SetData(DATA_LORKHAN, NOT_STARTED);
+ instance->SetBossState(DATA_LORKHAN, NOT_STARTED);
me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
@@ -356,7 +356,7 @@ class mob_zealot_lorkhan : public CreatureScript
{
if (instance)
{
- if (instance->GetData(DATA_THEKAL) == SPECIAL)
+ if (instance->GetBossState(DATA_THEKAL) == SPECIAL)
{
//Resurrect Thekal
if (Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL)))
@@ -368,7 +368,7 @@ class mob_zealot_lorkhan : public CreatureScript
}
}
- if (instance->GetData(DATA_ZATH) == SPECIAL)
+ if (instance->GetBossState(DATA_ZATH) == SPECIAL)
{
//Resurrect Zath
if (Unit* pZath = Unit::GetUnit(*me, instance->GetData64(DATA_ZATH)))
@@ -395,7 +395,7 @@ class mob_zealot_lorkhan : public CreatureScript
me->AttackStop();
if (instance)
- instance->SetData(DATA_LORKHAN, SPECIAL);
+ instance->SetBossState(DATA_LORKHAN, SPECIAL);
FakeDeath = true;
}
@@ -450,7 +450,7 @@ class mob_zealot_zath : public CreatureScript
FakeDeath = false;
if (instance)
- instance->SetData(DATA_ZATH, NOT_STARTED);
+ instance->SetBossState(DATA_ZATH, NOT_STARTED);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
@@ -509,7 +509,7 @@ class mob_zealot_zath : public CreatureScript
{
if (instance)
{
- if (instance->GetData(DATA_LORKHAN) == SPECIAL)
+ if (instance->GetBossState(DATA_LORKHAN) == SPECIAL)
{
//Resurrect LorKhan
if (Unit* pLorKhan = Unit::GetUnit(*me, instance->GetData64(DATA_LORKHAN)))
@@ -521,7 +521,7 @@ class mob_zealot_zath : public CreatureScript
}
}
- if (instance->GetData(DATA_THEKAL) == SPECIAL)
+ if (instance->GetBossState(DATA_THEKAL) == SPECIAL)
{
//Resurrect Thekal
if (Unit* pThekal = Unit::GetUnit(*me, instance->GetData64(DATA_THEKAL)))
@@ -548,7 +548,7 @@ class mob_zealot_zath : public CreatureScript
me->AttackStop();
if (instance)
- instance->SetData(DATA_ZATH, SPECIAL);
+ instance->SetBossState(DATA_ZATH, SPECIAL);
FakeDeath = true;
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
index b997d277c95..19a2ba39578 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
@@ -29,7 +29,7 @@ EndScriptData */
class instance_zulgurub : public InstanceMapScript
{
- public: instance_zulgurub(): InstanceMapScript("instance_zulgurub", 309) {}
+ public: instance_zulgurub(): InstanceMapScript(ZGScriptName, 309) {}
struct instance_zulgurub_InstanceMapScript : public InstanceScript
{
@@ -38,24 +38,18 @@ class instance_zulgurub : public InstanceMapScript
SetBossNumber(EncounterCount);
}
- //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too.
- //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too.
- uint64 LorKhanGUID;
- uint64 ZathGUID;
- uint64 ThekalGUID;
- uint64 JindoGUID;
-
void Initialize()
{
- LorKhanGUID = 0;
- ZathGUID = 0;
- ThekalGUID = 0;
- JindoGUID = 0;
+ ZealotLorkhanGUID = 0;
+ ZealotZathGUID = 0;
+ HighPriestTekalGUID = 0;
+ JindoTheHexxerGUID = 0;
+ VilebranchSpeakerGUID = 0;
}
bool IsEncounterInProgress() const
{
- //not active in Zul'Gurub
+ // not active in Zul'Gurub
return false;
}
@@ -63,78 +57,44 @@ class instance_zulgurub : public InstanceMapScript
{
switch (creature->GetEntry())
{
- case NPC_ZEALOT_LORKHAN: LorKhanGUID = creature->GetGUID(); break;
- case NPC_ZEALOT_ZATH: ZathGUID = creature->GetGUID(); break;
- case NPC_HIGH_PRIEST_THEKAL: ThekalGUID = creature->GetGUID(); break;
- case NPC_JINDO_THE_HEXXER: JindoGUID = creature->GetGUID(); break;
- }
- }
-
- bool SetBossState(uint32 type, EncounterState state)
- {
- if (!InstanceScript::SetBossState(type, state))
- return false;
-
- switch (type)
- {
- case DATA_JEKLIK:
- case DATA_VENOXIS:
- case DATA_MARLI:
- case DATA_ARLOKK:
- case DATA_HAKKAR:
- case DATA_MANDOKIR:
- case DATA_JINDO:
- case DATA_GAHZRANKA:
- case DATA_EDGE_OF_MADNESS:
- case DATA_THEKAL:
- case DATA_LORKHAN:
- case DATA_ZATH:
- case DATA_OHGAN:
+ case NPC_ZEALOT_LORKHAN:
+ ZealotLorkhanGUID = creature->GetGUID();
break;
- default:
+ case NPC_ZEALOT_ZATH:
+ ZealotZathGUID = creature->GetGUID();
break;
- }
-
- return true;
- }
-
- uint32 GetData(uint32 type) const
- {
- switch (type)
- {
- case DATA_JEKLIK: return GetBossState(DATA_JEKLIK);
- case DATA_VENOXIS: return GetBossState(DATA_VENOXIS);
- case DATA_MARLI: return GetBossState(DATA_MARLI);
- case DATA_ARLOKK: return GetBossState(DATA_ARLOKK);
- case DATA_HAKKAR: return GetBossState(DATA_HAKKAR);
- case DATA_MANDOKIR: return GetBossState(DATA_MANDOKIR);
- case DATA_JINDO: return GetBossState(DATA_JINDO);
- case DATA_GAHZRANKA: return GetBossState(DATA_GAHZRANKA);
- case DATA_EDGE_OF_MADNESS: return GetBossState(DATA_EDGE_OF_MADNESS);
- case DATA_THEKAL: return GetBossState(DATA_THEKAL);
- case DATA_LORKHAN: return GetBossState(DATA_LORKHAN);
- case DATA_ZATH: return GetBossState(DATA_ZATH);
- case DATA_OHGAN: return GetBossState(DATA_OHGAN);
+ case NPC_HIGH_PRIEST_THEKAL:
+ HighPriestTekalGUID = creature->GetGUID();
+ break;
+ case NPC_JINDO_THE_HEXXER:
+ JindoTheHexxerGUID = creature->GetGUID();
break;
- default:
+ case NPC_VILEBRANCH_SPEAKER:
+ VilebranchSpeakerGUID = creature->GetGUID();
break;
+ case NPC_MANDOKIR:
+ if (GetBossState(DATA_MANDOKIR) == DONE)
+ creature->DespawnOrUnsummon();
+ break;
+ }
}
- return 0;
- }
-
uint64 GetData64(uint32 uiData) const
{
switch (uiData)
{
case DATA_LORKHAN:
- return LorKhanGUID;
+ return ZealotLorkhanGUID;
+ break;
case DATA_ZATH:
- return ZathGUID;
+ return ZealotZathGUID;
+ break;
case DATA_THEKAL:
- return ThekalGUID;
+ return HighPriestTekalGUID;
+ break;
case DATA_JINDO:
- return JindoGUID;
+ return JindoTheHexxerGUID;
+ break;
}
return 0;
}
@@ -181,6 +141,15 @@ class instance_zulgurub : public InstanceMapScript
OUT_LOAD_INST_DATA_COMPLETE;
}
+ private:
+ //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too.
+ //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too.
+
+ uint64 ZealotLorkhanGUID;
+ uint64 ZealotZathGUID;
+ uint64 HighPriestTekalGUID;
+ uint64 JindoTheHexxerGUID;
+ uint64 VilebranchSpeakerGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
index 2544e4f4d5f..34680447cd7 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h
@@ -20,6 +20,8 @@
uint32 const EncounterCount = 13;
+#define ZGScriptName "instance_zulgurub"
+
enum DataTypes
{
DATA_JEKLIK = 0, // Main boss
@@ -45,9 +47,22 @@ enum CreatureIds
NPC_JINDO_THE_HEXXER = 11380,
NPC_NIGHTMARE_ILLUSION = 15163,
NPC_ZULIAN_PROWLER = 15101,
- NPC_SPEAKER = 11391,
+ NPC_VILEBRANCH_SPEAKER = 11391,
NPC_SHADE_OF_JINDO = 14986,
- NPC_SACRIFICED_TROLL = 14826
+ NPC_SACRIFICED_TROLL = 14826,
+ NPC_OHGAN = 14988,
+ NPC_CHAINED_SPIRT = 15117,
+ NPC_MANDOKIR = 11382
};
+template<class AI>
+CreatureAI* GetZulGurubAI(Creature* creature)
+{
+ if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
+ if (instance->GetInstanceScript())
+ if (instance->GetScriptId() == sObjectMgr->GetScriptId(ZGScriptName))
+ return new AI(creature);
+ return NULL;
+}
+
#endif
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index 7f8108e5e71..6039e01b901 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -359,7 +359,7 @@ class boss_halion : public CreatureScript
if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TWILIGHT_HALION)))
if (twilightHalion->isAlive())
twilightHalion->Kill(twilightHalion);
-
+
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HALION_CONTROLLER)))
if (controller->isAlive())
controller->Kill(controller);
diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp
index f3afc03e68a..7db2ae4707b 100644
--- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp
+++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp
@@ -1033,6 +1033,102 @@ public:
}
};
+/*######
+## Quest: Reconnaissance Flight (12671)
+######*/
+enum ReconnaissanceFlight
+{
+ NPC_PLANE = 28710, // Vic's Flying Machine
+ NPC_PILOT = 28646,
+
+ VIC_SAY_0 = 0,
+ VIC_SAY_1 = 1,
+ VIC_SAY_2 = 2,
+ VIC_SAY_3 = 3,
+ VIC_SAY_4 = 4,
+ VIC_SAY_5 = 5,
+ VIC_SAY_6 = 6,
+ PLANE_EMOTE = 0,
+
+ AURA_ENGINE = 52255, // Engine on Fire
+
+ SPELL_LAND = 52226, // Land Flying Machine
+ SPELL_CREDIT = 53328 // Land Flying Machine Credit
+};
+
+class npc_vics_flying_machine : public CreatureScript
+{
+public:
+ npc_vics_flying_machine() : CreatureScript("npc_vics_flying_machine") { }
+
+ struct npc_vics_flying_machineAI : public VehicleAI
+ {
+ npc_vics_flying_machineAI(Creature* creature) : VehicleAI(creature) {}
+
+ void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply)
+ {
+ if (apply && passenger->GetTypeId() == TYPEID_PLAYER)
+ me->GetMotionMaster()->MovePath(NPC_PLANE, false);
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type != WAYPOINT_MOTION_TYPE)
+ return;
+
+ if (Creature* pilot = GetClosestCreatureWithEntry(me, NPC_PILOT, 10))
+ switch (id)
+ {
+ case 5:
+ pilot->AI()->Talk(VIC_SAY_0);
+ break;
+ case 11:
+ pilot->AI()->Talk(VIC_SAY_1);
+ break;
+ case 12:
+ pilot->AI()->Talk(VIC_SAY_2);
+ break;
+ case 14:
+ pilot->AI()->Talk(VIC_SAY_3);
+ break;
+ case 15:
+ pilot->AI()->Talk(VIC_SAY_4);
+ break;
+ case 17:
+ pilot->AI()->Talk(VIC_SAY_5);
+ break;
+ case 21:
+ pilot->AI()->Talk(VIC_SAY_6);
+ break;
+ case 25:
+ me->AI()->Talk(PLANE_EMOTE);
+ me->AI()->DoCast(AURA_ENGINE);
+ break;
+ }
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_LAND)
+ {
+ Unit* passenger = me->GetVehicleKit()->GetPassenger(1); // player should be on seat 1
+ if (passenger && passenger->GetTypeId() == TYPEID_PLAYER)
+ {
+ passenger->CastSpell(passenger, SPELL_CREDIT, true);
+ passenger->ExitVehicle();
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 /*diff*/) {}
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_vics_flying_machineAI(creature);
+ }
+};
+
void AddSC_sholazar_basin()
{
new npc_injured_rainspeaker_oracle();
@@ -1045,4 +1141,5 @@ void AddSC_sholazar_basin()
new spell_q12620_the_lifewarden_wrath();
new spell_q12589_shoot_rjr();
new npc_haiphoon();
+ new npc_vics_flying_machine();
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index cfbd4b2bc45..1c2410b8b53 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -374,7 +374,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_GROUP_DIFFICULTY, "UPDATE groups SET difficulty = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_GROUP_RAID_DIFFICULTY, "UPDATE groups SET raiddifficulty = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ALL_GM_TICKETS, "TRUNCATE TABLE gm_tickets", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_INVALID_SPELL, "DELETE FROM character_talent WHERE spell = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_SPELL_TALENTS, "DELETE FROM character_talent WHERE spell = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_SPELL_SPELLS, "DELETE FROM character_spell WHERE spell = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_DELETE_INFO, "UPDATE characters SET deleteInfos_Name = name, deleteInfos_Account = account, deleteDate = UNIX_TIMESTAMP(), name = '', account = 0 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UDP_RESTORE_DELETE_INFO, "UPDATE characters SET name = ?, account = ?, deleteDate = NULL, deleteInfos_Name = NULL, deleteInfos_Account = NULL WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ZONE, "UPDATE characters SET zone = ? WHERE guid = ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index bfa7bc48cf5..e4728e19934 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -315,7 +315,8 @@ enum CharacterDatabaseStatements
CHAR_UPD_GROUP_MEMBER_FLAG,
CHAR_UPD_GROUP_DIFFICULTY,
CHAR_UPD_GROUP_RAID_DIFFICULTY,
- CHAR_DEL_INVALID_SPELL,
+ CHAR_DEL_INVALID_SPELL_SPELLS,
+ CHAR_DEL_INVALID_SPELL_TALENTS,
CHAR_UPD_DELETE_INFO,
CHAR_UDP_RESTORE_DELETE_INFO,
CHAR_UPD_ZONE,
diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp
index f2f5da53dae..1d215e1212e 100644
--- a/src/server/shared/Logging/Appender.cpp
+++ b/src/server/shared/Logging/Appender.cpp
@@ -73,10 +73,7 @@ void Appender::setLogLevel(LogLevel _level)
void Appender::write(LogMessage& message)
{
if (!level || level > message.level)
- {
- //fprintf(stderr, "Appender::write: Appender %s, Level %s. Msg %s Level %s Type %s WRONG LEVEL MASK\n", getName().c_str(), getLogLevelString(level), message.text.c_str(), getLogLevelString(message.level), getLogFilterTypeString(message.type)); // DEBUG - RemoveMe
return;
- }
message.prefix.clear();
if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
@@ -222,5 +219,6 @@ char const* Appender::getLogFilterTypeString(LogFilterType type)
default:
break;
}
+
return "???";
}
diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h
index 6a0f0bdac26..a8854a8abc6 100644
--- a/src/server/shared/Logging/Appender.h
+++ b/src/server/shared/Logging/Appender.h
@@ -143,7 +143,7 @@ class Appender
static const char* getLogFilterTypeString(LogFilterType type);
private:
- virtual void _write(LogMessage& /*message*/) = 0;
+ virtual void _write(LogMessage const& /*message*/) = 0;
uint8 id;
std::string name;
diff --git a/src/server/shared/Logging/AppenderConsole.cpp b/src/server/shared/Logging/AppenderConsole.cpp
index d0af761188c..a1212bd135b 100644
--- a/src/server/shared/Logging/AppenderConsole.cpp
+++ b/src/server/shared/Logging/AppenderConsole.cpp
@@ -154,7 +154,7 @@ void AppenderConsole::ResetColor(bool stdout_stream)
#endif
}
-void AppenderConsole::_write(LogMessage& message)
+void AppenderConsole::_write(LogMessage const& message)
{
bool stdout_stream = message.level == LOG_LEVEL_ERROR || message.level == LOG_LEVEL_FATAL;
diff --git a/src/server/shared/Logging/AppenderConsole.h b/src/server/shared/Logging/AppenderConsole.h
index 3319c84e887..6f3fcca901c 100644
--- a/src/server/shared/Logging/AppenderConsole.h
+++ b/src/server/shared/Logging/AppenderConsole.h
@@ -51,7 +51,7 @@ class AppenderConsole: public Appender
private:
void SetColor(bool stdout_stream, ColorTypes color);
void ResetColor(bool stdout_stream);
- void _write(LogMessage& message);
+ void _write(LogMessage const& message);
bool _colored;
ColorTypes _colors[MaxLogLevels];
};
diff --git a/src/server/shared/Logging/AppenderDB.cpp b/src/server/shared/Logging/AppenderDB.cpp
index 86677eeedd8..ae5fc17de73 100644
--- a/src/server/shared/Logging/AppenderDB.cpp
+++ b/src/server/shared/Logging/AppenderDB.cpp
@@ -18,8 +18,8 @@
#include "AppenderDB.h"
#include "Database/DatabaseEnv.h"
-AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, uint32 realmId)
- : Appender(id, name, APPENDER_DB, level), realm(realmId), enable(false)
+AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level)
+ : Appender(id, name, APPENDER_DB, level), realmId(0), enabled(false)
{
}
@@ -27,10 +27,11 @@ AppenderDB::~AppenderDB()
{
}
-void AppenderDB::_write(LogMessage& message)
+void AppenderDB::_write(LogMessage const& message)
{
- if (!enable)
+ if (!enabled)
return;
+
switch (message.type)
{
case LOG_FILTER_SQL:
@@ -40,7 +41,7 @@ void AppenderDB::_write(LogMessage& message)
default:
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
stmt->setUInt64(0, message.mtime);
- stmt->setUInt32(1, realm);
+ stmt->setUInt32(1, realmId);
stmt->setUInt8(2, uint8(message.type));
stmt->setUInt8(3, uint8(message.level));
stmt->setString(4, message.text);
@@ -49,7 +50,8 @@ void AppenderDB::_write(LogMessage& message)
}
}
-void AppenderDB::setEnable(bool _enable)
+void AppenderDB::setRealmId(uint32 _realmId)
{
- enable = _enable;
+ enabled = true;
+ realmId = _realmId;
}
diff --git a/src/server/shared/Logging/AppenderDB.h b/src/server/shared/Logging/AppenderDB.h
index 5ab9a1ee423..f9dde0a1e82 100644
--- a/src/server/shared/Logging/AppenderDB.h
+++ b/src/server/shared/Logging/AppenderDB.h
@@ -23,14 +23,15 @@
class AppenderDB: public Appender
{
public:
- AppenderDB(uint8 _id, std::string const& _name, LogLevel level, uint32 realmId);
+ AppenderDB(uint8 _id, std::string const& _name, LogLevel level);
~AppenderDB();
- void setEnable(bool enable);
+
+ void setRealmId(uint32 realmId);
private:
- uint32 realm;
- bool enable;
- void _write(LogMessage& message);
+ uint32 realmId;
+ bool enabled;
+ void _write(LogMessage const& message);
};
#endif
diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp
index 7b0bac03d03..8189237bb4e 100644
--- a/src/server/shared/Logging/AppenderFile.cpp
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -39,7 +39,7 @@ AppenderFile::~AppenderFile()
}
}
-void AppenderFile::_write(LogMessage& message)
+void AppenderFile::_write(LogMessage const& message)
{
if (dynamicName)
{
@@ -70,5 +70,6 @@ FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mod
newName.append(LogMessage::getTimeStr(time(NULL)));
rename(filename.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
}
+
return fopen((logDir + filename).c_str(), mode.c_str());
}
diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h
index 934370d70b4..a3fe285cc7d 100644
--- a/src/server/shared/Logging/AppenderFile.h
+++ b/src/server/shared/Logging/AppenderFile.h
@@ -28,7 +28,7 @@ class AppenderFile: public Appender
FILE* OpenFile(std::string const& _name, std::string const& _mode, bool _backup);
private:
- void _write(LogMessage& message);
+ void _write(LogMessage const& message);
FILE* logfile;
std::string filename;
std::string logDir;
diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp
index 60320d049ac..96c72b5eb74 100644
--- a/src/server/shared/Logging/Log.cpp
+++ b/src/server/shared/Logging/Log.cpp
@@ -31,7 +31,6 @@
Log::Log() : worker(NULL)
{
- SetRealmID(0);
m_logsTimestamp = "_" + GetTimestampStr();
LoadFromConfig();
}
@@ -154,7 +153,7 @@ void Log::CreateAppenderFromConfig(const char* name)
case APPENDER_DB:
{
uint8 id = NextAppenderId();
- appenders[id] = new AppenderDB(id, name, level, realm);
+ appenders[id] = new AppenderDB(id, name, level);
break;
}
default:
@@ -265,13 +264,6 @@ void Log::ReadLoggersFromConfig()
loggers[LOG_FILTER_GENERAL].Create("root", LOG_FILTER_GENERAL, LOG_LEVEL_DISABLED);
}
-void Log::EnableDBAppenders()
-{
- for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
- if (it->second && it->second->getType() == APPENDER_DB)
- ((AppenderDB *)it->second)->setEnable(true);
-}
-
void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list argptr)
{
char text[MAX_QUERY_LEN];
@@ -281,12 +273,16 @@ void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list ar
void Log::write(LogMessage* msg)
{
+ if (loggers.empty())
+ return;
+
+ msg->text.append("\n");
+ Logger* logger = GetLoggerByType(msg->type);
+
if (worker)
- {
- msg->text.append("\n");
- Logger* logger = GetLoggerByType(msg->type);
worker->enqueue(new LogOperation(logger, msg));
- }
+ else
+ logger->write(*msg);
}
std::string Log::GetTimestampStr()
@@ -463,9 +459,11 @@ void Log::outCommand(uint32 account, const char * str, ...)
write(msg);
}
-void Log::SetRealmID(uint32 id)
+void Log::SetRealmId(uint32 id)
{
- realm = id;
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
+ if (it->second && it->second->getType() == APPENDER_DB)
+ ((AppenderDB *)it->second)->setRealmId(id);
}
void Log::Close()
@@ -484,7 +482,10 @@ void Log::Close()
void Log::LoadFromConfig()
{
Close();
- worker = new LogWorker();
+
+ if (ConfigMgr::GetBoolDefault("Log.Async.Enable", false))
+ worker = new LogWorker();
+
AppenderId = 0;
m_logsDir = ConfigMgr::GetStringDefault("LogsDir", "");
if (!m_logsDir.empty())
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 6d6cfe715e8..46aaea4bad1 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -52,12 +52,11 @@ class Log
void outError(LogFilterType f, char const* str, ...) ATTR_PRINTF(3, 4);
void outFatal(LogFilterType f, char const* str, ...) ATTR_PRINTF(3, 4);
- void EnableDBAppenders();
void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
void outCharDump(char const* str, uint32 account_id, uint32 guid, char const* name);
static std::string GetTimestampStr();
- void SetRealmID(uint32 id);
+ void SetRealmId(uint32 id);
private:
void vlog(LogFilterType f, LogLevel level, char const* str, va_list argptr);
@@ -78,7 +77,6 @@ class Log
std::string m_logsDir;
std::string m_logsTimestamp;
- uint32 realm;
LogWorker* worker;
};
diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp
index fe872c1977f..56dd64bc45a 100644
--- a/src/server/worldserver/Master.cpp
+++ b/src/server/worldserver/Master.cpp
@@ -438,8 +438,6 @@ bool Master::_StartDB()
}
sLog->outInfo(LOG_FILTER_WORLDSERVER, "Realm running as realm ID %d", realmID);
- sLog->SetRealmID(realmID);
-
///- Clean the database before starting
ClearOnlineAccounts();
diff --git a/src/server/worldserver/RemoteAccess/RASocket.cpp b/src/server/worldserver/RemoteAccess/RASocket.cpp
index 95fdad9ad44..e0f4e7f0de6 100644
--- a/src/server/worldserver/RemoteAccess/RASocket.cpp
+++ b/src/server/worldserver/RemoteAccess/RASocket.cpp
@@ -71,7 +71,7 @@ int RASocket::send(const std::string& line)
ssize_t n = peer().send(line.c_str(), line.length());
#endif // MSG_NOSIGNAL
- return n == line.length() ? 0 : -1;
+ return n == ssize_t(line.length()) ? 0 : -1;
}
int RASocket::recv_line(ACE_Message_Block& buffer)
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 68cf3994e3b..505a65771fa 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2824,4 +2824,12 @@ Logger.Opcodes=41,6,Console Server
Loggers=Root Chat DBErrors GM RA Warden Character Load WorldServer Opcodes
#
+# Log.Async.Enable
+# Description: Enables asyncronous message logging.
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+Log.Async.Enable = 0
+
+#
###################################################################################################