aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/BoundingIntervalHierarchy.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp16
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp61
-rw-r--r--src/server/game/Accounts/AccountMgr.h1
-rw-r--r--src/server/game/Accounts/RBAC.cpp162
-rw-r--r--src/server/game/Accounts/RBAC.h8
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp1
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp4
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h1
-rw-r--r--src/server/game/Entities/Object/Object.cpp10
-rw-r--r--src/server/game/Entities/Object/Object.h2
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp12
-rw-r--r--src/server/game/Entities/Player/Player.cpp73
-rw-r--r--src/server/game/Entities/Player/Player.h15
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp14
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp2
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp22
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h6
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp6
-rw-r--r--src/server/game/Globals/ObjectMgr.h41
-rw-r--r--src/server/game/Handlers/MailHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp8
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp4
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp8
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp39
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp2
-rw-r--r--src/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Quests/QuestDef.cpp8
-rw-r--r--src/server/game/Quests/QuestDef.h44
-rw-r--r--src/server/game/Server/WorldSession.cpp23
-rw-r--r--src/server/game/Server/WorldSession.h1
-rw-r--r--src/server/game/Spells/Spell.cpp58
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp6
-rw-r--r--src/server/game/Spells/SpellInfo.cpp57
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp21
-rw-r--r--src/server/game/Spells/SpellMgr.h8
-rw-r--r--src/server/game/World/World.cpp8
-rw-r--r--src/server/game/World/World.h3
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp6
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp22
-rw-r--r--src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp10
-rw-r--r--src/server/scripts/World/areatrigger_scripts.cpp10
-rw-r--r--src/server/shared/Common.h2
-rw-r--r--src/server/shared/Database/DatabaseWorkerPool.h14
-rw-r--r--src/server/shared/Logging/Appender.cpp2
-rw-r--r--src/server/shared/Logging/Appender.h3
-rw-r--r--src/server/worldserver/worldserver.conf.dist1
49 files changed, 605 insertions, 228 deletions
diff --git a/src/server/collision/BoundingIntervalHierarchy.cpp b/src/server/collision/BoundingIntervalHierarchy.cpp
index bca738d1ff6..4c1f449da25 100644
--- a/src/server/collision/BoundingIntervalHierarchy.cpp
+++ b/src/server/collision/BoundingIntervalHierarchy.cpp
@@ -20,6 +20,8 @@
#if defined __APPLE__
#define isnan std::isnan
+#elif defined __CYGWIN__
+ #define isnan std::isnan
#elif defined _MSC_VER
#define isnan _isnan
#endif
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index 5ef9ee09f1d..e36916decae 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -515,35 +515,35 @@ bool BossAI::CheckBoundary(Unit* who)
switch (itr->first)
{
case BOUNDARY_N:
- if (me->GetPositionX() > itr->second)
+ if (who->GetPositionX() > itr->second)
return false;
break;
case BOUNDARY_S:
- if (me->GetPositionX() < itr->second)
+ if (who->GetPositionX() < itr->second)
return false;
break;
case BOUNDARY_E:
- if (me->GetPositionY() < itr->second)
+ if (who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_W:
- if (me->GetPositionY() > itr->second)
+ if (who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_NW:
- if (me->GetPositionX() + me->GetPositionY() > itr->second)
+ if (who->GetPositionX() + who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SE:
- if (me->GetPositionX() + me->GetPositionY() < itr->second)
+ if (who->GetPositionX() + who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_NE:
- if (me->GetPositionX() - me->GetPositionY() > itr->second)
+ if (who->GetPositionX() - who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SW:
- if (me->GetPositionX() - me->GetPositionY() < itr->second)
+ if (who->GetPositionX() - who->GetPositionY() < itr->second)
return false;
break;
default:
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 7172efaac0e..83f1252e1f1 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -31,14 +31,7 @@ AccountMgr::AccountMgr()
AccountMgr::~AccountMgr()
{
- for (RBACPermissionsContainer::iterator itr = _permissions.begin(); itr != _permissions.end(); ++itr)
- delete itr->second;
-
- for (RBACRolesContainer::iterator itr = _roles.begin(); itr != _roles.end(); ++itr)
- delete itr->second;
-
- for (RBACGroupsContainer::iterator itr = _groups.begin(); itr != _groups.end(); ++itr)
- delete itr->second;
+ ClearRBAC();
}
AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password)
@@ -337,11 +330,15 @@ bool AccountMgr::IsConsoleAccount(uint32 gmlevel)
void AccountMgr::LoadRBAC()
{
+ ClearRBAC();
+
+ sLog->outInfo(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC");
uint32 oldMSTime = getMSTime();
uint32 count1 = 0;
uint32 count2 = 0;
uint32 count3 = 0;
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading permissions");
QueryResult result = LoginDatabase.Query("SELECT id, name FROM rbac_permissions");
if (!result)
{
@@ -358,6 +355,7 @@ void AccountMgr::LoadRBAC()
}
while (result->NextRow());
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading roles");
result = LoginDatabase.Query("SELECT id, name FROM rbac_roles");
if (!result)
{
@@ -374,6 +372,7 @@ void AccountMgr::LoadRBAC()
}
while (result->NextRow());
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading role permissions");
result = LoginDatabase.Query("SELECT roleId, permissionId FROM rbac_role_permissions");
if (!result)
{
@@ -390,6 +389,7 @@ void AccountMgr::LoadRBAC()
}
while (result->NextRow());
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading groups");
result = LoginDatabase.Query("SELECT id, name FROM rbac_groups");
if (!result)
{
@@ -406,6 +406,7 @@ void AccountMgr::LoadRBAC()
}
while (result->NextRow());
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading group roles");
result = LoginDatabase.Query("SELECT groupId, roleId FROM rbac_group_roles");
if (!result)
{
@@ -422,6 +423,7 @@ void AccountMgr::LoadRBAC()
}
while (result->NextRow());
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading security level groups");
result = LoginDatabase.Query("SELECT secId, groupId FROM rbac_security_level_groups ORDER by secId ASC");
if (!result)
{
@@ -445,6 +447,7 @@ void AccountMgr::LoadRBAC()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u permission definitions, %u role definitions and %u group definitions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime));
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::LoadRBAC: Loading default groups");
// Load default groups to be added to any RBAC Object.
std::string defaultGroups = ConfigMgr::GetStringDefault("RBAC.DefaultGroups", "");
Tokenizer tokens(defaultGroups, ',');
@@ -518,42 +521,68 @@ void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 sec
}
}
-RBACGroup const* AccountMgr::GetRBACGroup(uint32 group) const
+RBACGroup const* AccountMgr::GetRBACGroup(uint32 groupId) const
{
- RBACGroupsContainer::const_iterator it = _groups.find(group);
+ sLog->outTrace(LOG_FILTER_RBAC, "AccountMgr::GetRBACGroup: groupId: %u", groupId);
+ RBACGroupsContainer::const_iterator it = _groups.find(groupId);
if (it != _groups.end())
return it->second;
return NULL;
}
-RBACRole const* AccountMgr::GetRBACRole(uint32 role) const
+RBACRole const* AccountMgr::GetRBACRole(uint32 roleId) const
{
- RBACRolesContainer::const_iterator it = _roles.find(role);
+ sLog->outTrace(LOG_FILTER_RBAC, "AccountMgr::GetRBACRole: roleId: %u", roleId);
+ RBACRolesContainer::const_iterator it = _roles.find(roleId);
if (it != _roles.end())
return it->second;
return NULL;
}
-RBACPermission const* AccountMgr::GetRBACPermission(uint32 permission) const
+RBACPermission const* AccountMgr::GetRBACPermission(uint32 permissionId) const
{
- RBACPermissionsContainer::const_iterator it = _permissions.find(permission);
+ sLog->outTrace(LOG_FILTER_RBAC, "AccountMgr::GetRBACPermission: roleId: %u", permissionId);
+ RBACPermissionsContainer::const_iterator it = _permissions.find(permissionId);
if (it != _permissions.end())
return it->second;
return NULL;
}
-bool AccountMgr::HasPermission(uint32 accountId, uint32 permission, uint32 realmId)
+bool AccountMgr::HasPermission(uint32 accountId, uint32 permissionId, uint32 realmId)
{
if (!accountId)
+ {
+ sLog->outError(LOG_FILTER_RBAC, "AccountMgr::HasPermission: Wrong accountId 0");
return false;
+ }
RBACData* rbac = new RBACData(accountId, "", realmId);
rbac->LoadFromDB();
- bool hasPermission = rbac->HasPermission(permission);
+ bool hasPermission = rbac->HasPermission(permissionId);
delete rbac;
+ sLog->outDebug(LOG_FILTER_RBAC, "AccountMgr::HasPermission [AccountId: %u, PermissionId: %u, realmId: %d]: %u",
+ accountId, permissionId, realmId, hasPermission);
return hasPermission;
}
+
+void AccountMgr::ClearRBAC()
+{
+ for (RBACPermissionsContainer::iterator itr = _permissions.begin(); itr != _permissions.end(); ++itr)
+ delete itr->second;
+
+ for (RBACRolesContainer::iterator itr = _roles.begin(); itr != _roles.end(); ++itr)
+ delete itr->second;
+
+ for (RBACGroupsContainer::iterator itr = _groups.begin(); itr != _groups.end(); ++itr)
+ delete itr->second;
+
+ _permissions.clear();
+ _roles.clear();
+ _groups.clear();
+ _defaultGroups.clear();
+ _defaultSecGroups.clear();
+}
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index 28373456994..16b4355585a 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -82,6 +82,7 @@ class AccountMgr
RBACGroupContainer const& GetRBACDefaultGroups() const { return _defaultGroups; }
private:
+ void ClearRBAC();
RBACPermissionsContainer _permissions;
RBACRolesContainer _roles;
RBACGroupsContainer _groups;
diff --git a/src/server/game/Accounts/RBAC.cpp b/src/server/game/Accounts/RBAC.cpp
index 121c9faae76..d26d557e2f4 100644
--- a/src/server/game/Accounts/RBAC.cpp
+++ b/src/server/game/Accounts/RBAC.cpp
@@ -19,21 +19,67 @@
#include "AccountMgr.h"
#include "DatabaseEnv.h"
+void RBACRole::GrantPermission(uint32 permissionId)
+{
+ if (permissionId < RBAC_PERM_MAX)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACRole::GrantPermission (Role %u, Permission %u). Ok", GetId(), permissionId);
+ _perms.set(permissionId);
+ }
+ else
+ sLog->outError(LOG_FILTER_RBAC, "RBACRole::GrantPermission (Role %u, Permission %u). Permission not lower than %u",
+ GetId(), permissionId, RBAC_PERM_MAX);
+}
+
+void RBACRole::RevokePermission(uint32 permissionId)
+{
+ if (permissionId < RBAC_PERM_MAX)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACRole::RevokePermission (Role %u, Permission %u). Ok", GetId(), permissionId);
+ _perms.reset(permissionId);
+ }
+ else
+ sLog->outError(LOG_FILTER_RBAC, "RBACRole::RevokePermission (Role %u, Permission %u). Permission not lower than %u",
+ GetId(), permissionId, RBAC_PERM_MAX);
+}
+
+void RBACGroup::GrantRole(uint32 roleId)
+{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACRole::GrantPermission (Role %u, Permission %u). Ok", GetId(), roleId);
+ _roles.insert(roleId);
+}
+
+void RBACGroup::RevokeRole(uint32 roleId)
+{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACRole::GrantPermission (Role %u, Permission %u). Ok", GetId(), roleId);
+ _roles.erase(roleId);
+}
+
RBACCommandResult RBACData::AddGroup(uint32 groupId, int32 realmId /* = 0 */)
{
// Check if group Id exists
RBACGroup const* group = sAccountMgr->GetRBACGroup(groupId);
if (!group)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::AddGroup [Id: %u Name: %s] (Group %u, RealmId %d). Group does not exists",
+ GetId(), GetName().c_str(), groupId, realmId);
return RBAC_ID_DOES_NOT_EXISTS;
+ }
// Already added?
std::pair<std::set<uint32>::iterator, bool> ret = _groups.insert(groupId);
if (!ret.second)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::AddGroup [Id: %u Name: %s] (Group %u, RealmId %d). Group Already added",
+ GetId(), GetName().c_str(), groupId, realmId);
return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::AddGroup [Id: %u Name: %s] (Group %u, RealmId %d). Added and DB updated",
+ GetId(), GetName().c_str(), groupId, realmId);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_RBAC_ACCOUNT_GROUP);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, groupId);
@@ -42,6 +88,9 @@ RBACCommandResult RBACData::AddGroup(uint32 groupId, int32 realmId /* = 0 */)
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::AddGroup [Id: %u Name: %s] (Group %u, RealmId %d). Added",
+ GetId(), GetName().c_str(), groupId, realmId);
return RBAC_OK;
}
@@ -50,11 +99,17 @@ RBACCommandResult RBACData::RemoveGroup(uint32 groupId, int32 realmId /* = 0 */)
{
// could remove it?
if (!_groups.erase(groupId))
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RemoveGroup [Id: %u Name: %s] (Group %u, RealmId %d). Group not in list",
+ GetId(), GetName().c_str(), groupId, realmId);
return RBAC_CANT_REVOKE_NOT_IN_LIST;
+ }
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RemoveGroup [Id: %u Name: %s] (Group %u, RealmId %d). Removed and DB updated",
+ GetId(), GetName().c_str(), groupId, realmId);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_RBAC_ACCOUNT_GROUP);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, groupId);
@@ -63,6 +118,9 @@ RBACCommandResult RBACData::RemoveGroup(uint32 groupId, int32 realmId /* = 0 */)
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RemoveGroup [Id: %u Name: %s] (Group %u, RealmId %d). Removed",
+ GetId(), GetName().c_str(), groupId, realmId);
return RBAC_OK;
}
@@ -72,23 +130,40 @@ RBACCommandResult RBACData::GrantRole(uint32 roleId, int32 realmId /* = 0*/)
// Check if role Id exists
RBACRole const* role = sAccountMgr->GetRBACRole(roleId);
if (!role)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantRole [Id: %u Name: %s] (Role %u, RealmId %d). Role does not exists",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_ID_DOES_NOT_EXISTS;
+ }
// Check if already added in denied list
if (_deniedRoles.find(roleId) != _deniedRoles.end())
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantRole [Id: %u Name: %s] (Role %u, RealmId %d). Role in deny list",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_IN_DENIED_LIST;
+ }
// Already added?
std::pair<std::set<uint32>::iterator, bool> ret = _grantedRoles.insert(roleId);
if (!ret.second)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantRole [Id: %u Name: %s] (Role %u, RealmId %d). Role already granted",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantRole [Id: %u Name: %s] (Role %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), roleId, realmId);
SaveRole(roleId, true, realmId);
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantRole [Id: %u Name: %s] (Role %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_OK;
}
@@ -98,23 +173,40 @@ RBACCommandResult RBACData::DenyRole(uint32 roleId, int32 realmId /* = 0*/)
// Check if role Id exists
RBACRole const* role = sAccountMgr->GetRBACRole(roleId);
if (!role)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyRole [Id: %u Name: %s] (Role %u, RealmId %d). Role does not exists",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_ID_DOES_NOT_EXISTS;
+ }
// Check if already added in granted list
if (_grantedRoles.find(roleId) != _grantedRoles.end())
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyRole [Id: %u Name: %s] (Role %u, RealmId %d). Role in grant list",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_IN_GRANTED_LIST;
+ }
// Already added?
std::pair<std::set<uint32>::iterator, bool> ret = _deniedRoles.insert(roleId);
if (!ret.second)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyRole [Id: %u Name: %s] (Role %u, RealmId %d). Role already denied",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyRole [Id: %u Name: %s] (Role %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), roleId, realmId);
SaveRole(roleId, false, realmId);
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyRole [Id: %u Name: %s] (Role %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_OK;
}
@@ -135,11 +227,17 @@ RBACCommandResult RBACData::RevokeRole(uint32 roleId, int32 realmId /* = 0*/)
// could remove it?
if (!revoked)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RevokeRole [Id: %u Name: %s] (Role %u, RealmId %d). Not granted or revoked",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_CANT_REVOKE_NOT_IN_LIST;
+ }
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RevokeRole [Id: %u Name: %s] (Role %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), roleId, realmId);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_RBAC_ACCOUNT_ROLE);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, roleId);
@@ -148,6 +246,9 @@ RBACCommandResult RBACData::RevokeRole(uint32 roleId, int32 realmId /* = 0*/)
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RevokeRole [Id: %u Name: %s] (Role %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), roleId, realmId);
return RBAC_OK;
}
@@ -157,24 +258,41 @@ RBACCommandResult RBACData::GrantPermission(uint32 permissionId, int32 realmId /
// Check if permission Id exists
RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId);
if (!perm)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission does not exists",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_ID_DOES_NOT_EXISTS;
+ }
// Check if already added in denied list
if (_deniedPerms.test(permissionId))
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission in deny list",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_IN_DENIED_LIST;
+ }
// Already added?
if (_grantedPerms.test(permissionId))
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission already granted",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
_grantedPerms.set(permissionId);
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), permissionId, realmId);
SavePermission(permissionId, true, realmId);
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::GrantPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_OK;
}
@@ -184,24 +302,41 @@ RBACCommandResult RBACData::DenyPermission(uint32 permissionId, int32 realmId /*
// Check if permission Id exists
RBACPermission const* perm = sAccountMgr->GetRBACPermission(permissionId);
if (!perm)
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission does not exists",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_ID_DOES_NOT_EXISTS;
+ }
// Check if already added in granted list
if (_grantedPerms.test(permissionId))
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission in grant list",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_IN_GRANTED_LIST;
+ }
// Already added?
if (_deniedPerms.test(permissionId))
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Permission already denied",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_CANT_ADD_ALREADY_ADDED;
+ }
_deniedPerms.set(permissionId);
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), permissionId, realmId);
SavePermission(permissionId, false, realmId);
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::DenyPermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_OK;
}
@@ -216,32 +351,44 @@ void RBACData::SavePermission(uint32 permission, bool granted, int32 realmId)
LoginDatabase.Execute(stmt);
}
-RBACCommandResult RBACData::RevokePermission(uint32 permission, int32 realmId /* = 0*/)
+RBACCommandResult RBACData::RevokePermission(uint32 permissionId, int32 realmId /* = 0*/)
{
// Check if it's present in any list
- if (!_grantedPerms.test(permission) && !_deniedPerms.test(permission))
+ if (!_grantedPerms.test(permissionId) && !_deniedPerms.test(permissionId))
+ {
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Not granted or revoked",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_CANT_REVOKE_NOT_IN_LIST;
+ }
- _grantedPerms.reset(permission);
- _deniedPerms.reset(permission);
+ _grantedPerms.reset(permissionId);
+ _deniedPerms.reset(permissionId);
// Do not save to db when loading data from DB (realmId = 0)
if (realmId)
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok and DB updated",
+ GetId(), GetName().c_str(), permissionId, realmId);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION);
stmt->setUInt32(0, GetId());
- stmt->setUInt32(1, permission);
+ stmt->setUInt32(1, permissionId);
stmt->setInt32(2, realmId);
LoginDatabase.Execute(stmt);
CalculateNewPermissions();
}
+ else
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::RevokePermission [Id: %u Name: %s] (Permission %u, RealmId %d). Ok",
+ GetId(), GetName().c_str(), permissionId, realmId);
return RBAC_OK;
}
void RBACData::LoadFromDB()
{
+ sLog->outInfo(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]", GetId(), GetName().c_str());
+ sLog->outDebug(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]: Loading groups", GetId(), GetName().c_str());
+
// Load account group that affect current realm
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_GROUPS);
stmt->setUInt32(0, GetId());
@@ -258,6 +405,7 @@ void RBACData::LoadFromDB()
while (result->NextRow());
}
+ sLog->outDebug(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]: Loading roles", GetId(), GetName().c_str());
// Load account roles (granted and denied) that affect current realm
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_ROLES);
stmt->setUInt32(0, GetId());
@@ -277,6 +425,7 @@ void RBACData::LoadFromDB()
while (result->NextRow());
}
+ sLog->outDebug(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]: Loading permissions", GetId(), GetName().c_str());
// Load account permissions (granted and denied) that affect current realm
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS);
stmt->setUInt32(0, GetId());
@@ -296,11 +445,13 @@ void RBACData::LoadFromDB()
while (result->NextRow());
}
+ sLog->outDebug(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]: Adding default groups", GetId(), GetName().c_str());
// Add default groups
RBACGroupContainer const& groups = sAccountMgr->GetRBACDefaultGroups();
for (RBACGroupContainer::const_iterator itr = groups.begin(); itr != groups.end(); ++itr)
AddGroup(*itr);
+ sLog->outDebug(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]: Calculating global permissions", GetId(), GetName().c_str());
// Force calculation of permissions, it wasn't performed at load time
// while adding groups, roles and permissions
CalculateNewPermissions();
@@ -308,6 +459,7 @@ void RBACData::LoadFromDB()
void RBACData::CalculateNewPermissions()
{
+ sLog->outTrace(LOG_FILTER_RBAC, "RBACData::LoadFromDB [Id: %u Name: %s]: Calculating global permissions", GetId(), GetName().c_str());
// Get the list of directly granted roles
RBACRoleContainer tempGrantedRoles = GetGrantedRoles();
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 0bd193d3841..779b0ece021 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -146,9 +146,9 @@ class RBACRole: public RBACObject
/// Gets the Permissions assigned to this role
RBACPermissionContainer const& GetPermissions() const { return _perms; }
/// Grants a Permission (Adds)
- void GrantPermission(uint32 id) { _perms.set(id); }
+ void GrantPermission(uint32 id);
/// Revokes a Permission (Removes)
- void RevokePermission(uint32 id) { _perms.reset(id); }
+ void RevokePermission(uint32 id);
private:
RBACPermissionContainer _perms; ///> Set of permissions
@@ -164,9 +164,9 @@ class RBACGroup: public RBACObject
/// Gets the Roles assigned to this group
RBACRoleContainer const& GetRoles() const { return _roles; }
/// Grants a Role (Adds)
- void GrantRole(uint32 role) { _roles.insert(role); }
+ void GrantRole(uint32 role);
/// Revokes a Role (Removes)
- void RevokeRole(uint32 role) { _roles.erase(role); }
+ void RevokeRole(uint32 role);
private:
RBACRoleContainer _roles; ///> Set of Roles
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 5f6bc8b7865..34c8054256c 100644
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -352,7 +352,6 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b
void Channel::UnBan(Player const* player, std::string const& badname)
{
- uint32 sec = player->GetSession()->GetSecurity();
uint64 good = player->GetGUID();
if (!IsOn(good))
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 39534c1c2bf..4d549b3b046 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -322,8 +322,8 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data
SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
// Load creature equipment
- if (!data || data->equipmentId == 0) // use default from the template
- LoadEquipment(GetOriginalEquipmentId());
+ if (!data || data->equipmentId == 0)
+ LoadEquipment(); // use default equipment (if available)
else if (data && data->equipmentId != 0) // override, 0 means no equipment
{
m_originalEquipmentId = data->equipmentId;
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index dc3347c5b4f..a28874c51e7 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -72,6 +72,7 @@ class Minion : public TempSummon
float GetFollowAngle() const { return m_followAngle; }
void SetFollowAngle(float angle) { m_followAngle = angle; }
bool IsPetGhoul() const {return GetEntry() == 26125;} // Ghoul may be guardian or pet
+ bool IsSpiritWolf() const {return GetEntry() == 29264;} // Spirit wolf from feral spirits
bool IsGuardianPet() const;
protected:
Unit* const m_owner;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 79bf656c318..cd8ae5056ba 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2322,7 +2322,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
* @param list List to store pointers to summoned creatures.
*/
-void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
+void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= NULL*/)
{
std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetId(), SUMMONER_TYPE_MAP, group);
if (!data)
@@ -2330,7 +2330,8 @@ void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, NULL, itr->time))
- list.push_back(summon);
+ if (list)
+ list->push_back(summon);
}
void WorldObject::SetZoneScript()
@@ -2418,7 +2419,7 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3
* @param group Id of group to summon.
* @param list List to store pointers to summoned creatures.
*/
-void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
+void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= NULL*/)
{
ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!");
@@ -2428,7 +2429,8 @@ void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, itr->type, itr->time))
- list.push_back(summon);
+ if (list)
+ list->push_back(summon);
}
Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index ae788621368..dfd2ff73ae9 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -793,7 +793,7 @@ class WorldObject : public Object, public WorldLocation
}
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
- void SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list);
+ void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = NULL);
Creature* FindNearestCreature(uint32 entry, float range, bool alive = true) const;
GameObject* FindNearestGameObject(uint32 entry, float range) const;
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index d11f6d94734..e4981ee8483 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1003,15 +1003,11 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
if (!pInfo)
SetCreateHealth(30*petlevel);
- float dmg_multiplier = 0.3f;
- if (m_owner->GetAuraEffect(63271, 0)) // Glyph of Feral Spirit
- dmg_multiplier = 0.6f;
+ // wolf attack speed is 1.5s
+ SetAttackTime(BASE_ATTACK, cinfo->baseattacktime);
- SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier));
-
- // 14AP == 1dps, wolf's strike speed == 2s so dmg = basedmg + AP / 14 * 2
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14)));
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14)));
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel)));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel)));
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(m_owner->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor)
SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(m_owner->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a8a500c093a..8647d9d6f5e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7417,17 +7417,17 @@ void Player::UpdateArea(uint32 newArea)
m_areaUpdateId = newArea;
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
- pvpInfo.inFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
+ pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
UpdatePvPState(true);
UpdateAreaDependentAuras(newArea);
// previously this was in UpdateZone (but after UpdateArea) so nothing will break
- pvpInfo.inNoPvPArea = false;
+ pvpInfo.IsInNoPvPArea = false;
if (area && area->IsSanctuary()) // in sanctuary
{
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
- pvpInfo.inNoPvPArea = true;
+ pvpInfo.IsInNoPvPArea = true;
CombatStopWithPets();
}
else
@@ -7482,29 +7482,32 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
switch (zone->team)
{
case AREATEAM_ALLY:
- pvpInfo.inHostileArea = GetTeam() != ALLIANCE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
+ pvpInfo.IsInHostileArea = GetTeam() != ALLIANCE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break;
case AREATEAM_HORDE:
- pvpInfo.inHostileArea = GetTeam() != HORDE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
+ pvpInfo.IsInHostileArea = GetTeam() != HORDE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break;
case AREATEAM_NONE:
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
- pvpInfo.inHostileArea = sWorld->IsPvPRealm() || InBattleground() || zone->flags & AREA_FLAG_WINTERGRASP;
+ pvpInfo.IsInHostileArea = sWorld->IsPvPRealm() || InBattleground() || zone->flags & AREA_FLAG_WINTERGRASP;
break;
default: // 6 in fact
- pvpInfo.inHostileArea = false;
+ pvpInfo.IsInHostileArea = false;
break;
}
+ // Treat players having a quest flagging for PvP as always in hostile area
+ pvpInfo.IsHostile = pvpInfo.IsInHostileArea || HasPvPForcingQuest();
+
if (zone->flags & AREA_FLAG_CAPITAL) // Is in a capital city
{
- if (!pvpInfo.inHostileArea || zone->IsSanctuary())
+ if (!pvpInfo.IsHostile || zone->IsSanctuary())
{
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_IN_CITY);
InnEnter(time(0), GetMapId(), 0, 0, 0);
}
- pvpInfo.inNoPvPArea = true;
+ pvpInfo.IsInNoPvPArea = true;
}
else
{
@@ -15046,6 +15049,12 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
else
questStatusData.Timer = 0;
+ if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
+ {
+ pvpInfo.IsHostile = true;
+ UpdatePvPState();
+ }
+
SetQuestSlot(log_slot, quest_id, qtime);
m_QuestStatusSave[quest_id] = true;
@@ -15067,7 +15076,7 @@ void Player::CompleteQuest(uint32 quest_id)
if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id))
{
- if (qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED))
+ if (qInfo->HasFlag(QUEST_FLAGS_TRACKING))
RewardQuest(qInfo, 0, this, false);
else
SendQuestComplete(quest_id);
@@ -15242,6 +15251,12 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
+ if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
+ {
+ pvpInfo.IsHostile = pvpInfo.IsInHostileArea || HasPvPForcingQuest();
+ UpdatePvPState();
+ }
+
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
}
@@ -16555,6 +16570,25 @@ void Player::SendQuestUpdateAddPlayer(Quest const* quest, uint16 old_count, uint
SetQuestSlotCounter(log_slot, QUEST_PVP_KILL_SLOT, GetQuestSlotCounter(log_slot, QUEST_PVP_KILL_SLOT) + add_count);
}
+bool Player::HasPvPForcingQuest() const
+{
+ for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
+ {
+ uint32 questId = GetQuestSlotQuestId(i);
+ if (questId == 0)
+ continue;
+
+ Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
+ if (!quest)
+ continue;
+
+ if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
+ return true;
+ }
+
+ return false;
+}
+
/*********************************************************/
/*** LOAD SYSTEM ***/
/*********************************************************/
@@ -19887,7 +19921,8 @@ void Player::UpdatePvPFlag(time_t currTime)
{
if (!IsPvP())
return;
- if (pvpInfo.endTimer == 0 || currTime < (pvpInfo.endTimer + 300) || pvpInfo.inHostileArea)
+
+ if (!pvpInfo.EndTimer || currTime < (pvpInfo.EndTimer + 300) || pvpInfo.IsHostile)
return;
UpdatePvP(false);
@@ -21333,8 +21368,8 @@ void Player::UpdatePvPState(bool onlyFFA)
{
// TODO: should we always synchronize UNIT_FIELD_BYTES_2, 1 of controller and controlled?
// no, we shouldn't, those are checked for affecting player by client
- if (!pvpInfo.inNoPvPArea && !isGameMaster()
- && (pvpInfo.inFFAPvPArea || sWorld->IsFFAPvPRealm()))
+ if (!pvpInfo.IsInNoPvPArea && !isGameMaster()
+ && (pvpInfo.IsInFFAPvPArea || sWorld->IsFFAPvPRealm()))
{
if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
@@ -21353,15 +21388,15 @@ void Player::UpdatePvPState(bool onlyFFA)
if (onlyFFA)
return;
- if (pvpInfo.inHostileArea) // in hostile area
+ if (pvpInfo.IsHostile) // in hostile area
{
- if (!IsPvP() || pvpInfo.endTimer != 0)
+ if (!IsPvP() || pvpInfo.EndTimer)
UpdatePvP(true, true);
}
else // in friendly area
{
- if (IsPvP() && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP) && pvpInfo.endTimer == 0)
- pvpInfo.endTimer = time(0); // start toggle-off
+ if (IsPvP() && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP) && !pvpInfo.EndTimer)
+ pvpInfo.EndTimer = time(NULL); // start toggle-off
}
}
@@ -21370,11 +21405,11 @@ void Player::UpdatePvP(bool state, bool override)
if (!state || override)
{
SetPvP(state);
- pvpInfo.endTimer = 0;
+ pvpInfo.EndTimer = 0;
}
else
{
- pvpInfo.endTimer = time(NULL);
+ pvpInfo.EndTimer = time(NULL);
SetPvP(state);
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 3f1bd277d0c..a3327e20c93 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -270,12 +270,13 @@ struct PlayerInfo
struct PvPInfo
{
- PvPInfo() : inHostileArea(false), inNoPvPArea(false), inFFAPvPArea(false), endTimer(0) {}
+ PvPInfo() : IsHostile(false), IsInHostileArea(false), IsInNoPvPArea(false), IsInFFAPvPArea(false), EndTimer(0) {}
- bool inHostileArea;
- bool inNoPvPArea;
- bool inFFAPvPArea;
- time_t endTimer;
+ bool IsHostile;
+ bool IsInHostileArea; ///> Marks if player is in an area which forces PvP flag
+ bool IsInNoPvPArea; ///> Marks if player is in a sanctuary or friendly capital city
+ bool IsInFFAPvPArea; ///> Marks if player is in an FFAPvP area (such as Gurubashi Arena)
+ time_t EndTimer; ///> Time when player unflags himself for PvP (flag removed after 5 minutes)
};
struct DuelInfo
@@ -393,7 +394,7 @@ enum PlayerFlags
PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
- PLAYER_FLAGS_UNK19 = 0x00080000,
+ PLAYER_FLAGS_UBER = 0x00080000,
PLAYER_FLAGS_UNK20 = 0x00100000,
PLAYER_FLAGS_UNK21 = 0x00200000,
PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
@@ -1505,6 +1506,8 @@ class Player : public Unit, public GridObject<Player>
void AddTimedQuest(uint32 quest_id) { m_timedquests.insert(quest_id); }
void RemoveTimedQuest(uint32 quest_id) { m_timedquests.erase(quest_id); }
+ bool HasPvPForcingQuest() const;
+
/*********************************************************/
/*** LOAD SYSTEM ***/
/*********************************************************/
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 0024d726060..c30fa910f76 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -441,6 +441,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
Pet* pet = GetPet(); //update pet's AP
+ Guardian* guardian = GetGuardianPet();
//automatically update weapon damage after attack power modification
if (ranged)
{
@@ -456,8 +457,11 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness
UpdateSpellDamageAndHealingBonus();
- if (pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet
+ if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet
pet->UpdateAttackPowerAndDamage();
+
+ if (guardian && guardian->IsSpiritWolf()) // At melee attack power change for Shaman feral spirit
+ guardian->UpdateAttackPowerAndDamage();
}
}
@@ -1305,6 +1309,14 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.22f;
SetBonusDamage(int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.1287f));
}
+ else if (IsSpiritWolf()) //wolf benefit from shaman's attack power
+ {
+ float dmg_multiplier = 0.31f;
+ if (m_owner->GetAuraEffect(63271, 0)) // Glyph of Feral Spirit
+ dmg_multiplier = 0.61f;
+ bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier;
+ SetBonusDamage(int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier));
+ }
//demons benefit from warlocks shadow or fire damage
else if (isPet())
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 00f771b1f54..508f4b602de 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -11665,7 +11665,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
if (Player const* playerAttacker = ToPlayer())
{
- if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UNK19))
+ if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UBER))
return false;
}
// check flags
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index f3844d96069..bfffc84671f 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -576,6 +576,26 @@ void Vehicle::Dismiss()
}
/**
+ * @fn bool Vehicle::IsVehicleInUse() const
+ *
+ * @brief Returns information whether the vehicle is currently used by any unit
+ *
+ * @author Shauren
+ * @date 26-2-2013
+ *
+ * @return true if any passenger is boarded on vehicle, false otherwise.
+ */
+
+bool Vehicle::IsVehicleInUse() const
+{
+ for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
+ if (itr->second.Passenger)
+ return true;
+
+ return false;
+}
+
+/**
* @fn void Vehicle::InitMovementInfoForBase()
*
* @brief Sets correct MovementFlags2 based on VehicleFlags from DBC.
@@ -613,7 +633,7 @@ void Vehicle::InitMovementInfoForBase()
* @return null if passenger not found on vehicle, else the DBC record for the seat.
*/
-VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger)
+VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit const* passenger)
{
SeatMap::iterator itr;
for (itr = Seats.begin(); itr != Seats.end(); ++itr)
diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h
index 8b67b82cfa3..f9bf3c21ef4 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.h
+++ b/src/server/game/Entities/Vehicle/Vehicle.h
@@ -63,14 +63,14 @@ class Vehicle : public TransportBase
void RelocatePassengers();
void RemoveAllPassengers();
void Dismiss();
- bool IsVehicleInUse() { return Seats.begin() != Seats.end(); }
+ bool IsVehicleInUse() const;
void SetLastShootPos(Position const& pos) { _lastShootPos.Relocate(pos); }
- Position GetLastShootPos() { return _lastShootPos; }
+ Position const& GetLastShootPos() const { return _lastShootPos; }
SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones.
- VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger);
+ VehicleSeatEntry const* GetSeatForPassenger(Unit const* passenger);
protected:
friend class VehicleJoinEvent;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 222331c48f8..c82ea46f0f7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1425,6 +1425,8 @@ void ObjectMgr::LoadTempSummons()
{
uint32 oldMSTime = getMSTime();
+ _tempSummonDataStore.clear(); // needed for reload case
+
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = WorldDatabase.Query("SELECT summonerId, summonerType, groupId, entry, position_x, position_y, position_z, orientation, summonType, summonTime FROM creature_summon_groups");
@@ -3811,14 +3813,14 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->Flags & QUEST_FLAGS_AUTO_REWARDED)
+ if (qinfo->Flags & QUEST_FLAGS_TRACKING)
{
// at auto-reward can be rewarded only RewardChoiceItemId[0]
for (int j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j )
{
if (uint32 id = qinfo->RewardChoiceItemId[j])
{
- sLog->outError(LOG_FILTER_SQL, "Quest %u has `RewardChoiceItemId%d` = %u but item from `RewardChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_AUTO_REWARDED.",
+ sLog->outError(LOG_FILTER_SQL, "Quest %u has `RewardChoiceItemId%d` = %u but item from `RewardChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_TRACKING.",
qinfo->GetQuestId(), j+1, id, j+1);
// no changes, quest ignore this data
}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 12df01fc350..0a5b878e8fa 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -63,6 +63,26 @@ struct PageText
uint16 NextPage;
};
+/// Key for storing temp summon data in TempSummonDataContainer
+struct TempSummonGroupKey
+{
+ TempSummonGroupKey(uint32 summonerEntry, SummonerType summonerType, uint8 group)
+ : _summonerEntry(summonerEntry), _summonerType(summonerType), _summonGroup(group)
+ {
+ }
+
+ bool operator<(TempSummonGroupKey const& rhs) const
+ {
+ // memcmp is only reliable if struct doesn't have any padding (packed)
+ return memcmp(this, &rhs, sizeof(TempSummonGroupKey)) < 0;
+ }
+
+private:
+ uint32 _summonerEntry; ///< Summoner's entry
+ SummonerType _summonerType; ///< Summoner's type, see SummonerType for available types
+ uint8 _summonGroup; ///< Summon's group id
+};
+
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack()
@@ -417,25 +437,6 @@ struct TrinityStringLocale
StringVector Content;
};
-/// Key for storing temp summon data in TempSummonDataContainer
-struct TempSummonGroupKey
-{
- TempSummonGroupKey(uint32 summonerEntry, SummonerType summonerType, uint8 group)
- : _summonerEntry(summonerEntry), _summonerType(summonerType), _summonGroup(group)
- {
- }
-
- bool operator<(TempSummonGroupKey const& rhs) const
- {
- return memcmp(this, &rhs, sizeof(TempSummonGroupKey)) < 0;
- }
-
-private:
- uint32 _summonerEntry; ///< Summoner's entry
- SummonerType _summonerType; ///< Summoner's type, see SummonerType for available types
- uint8 _summonGroup; ///< Summon's group id
-};
-
typedef std::map<uint64, uint64> LinkedRespawnContainer;
typedef UNORDERED_MAP<uint32, CreatureData> CreatureDataContainer;
typedef UNORDERED_MAP<uint32, GameObjectData> GameObjectDataContainer;
@@ -1017,7 +1018,7 @@ class ObjectMgr
TempSummonDataContainer::const_iterator itr = _tempSummonDataStore.find(TempSummonGroupKey(summonerId, summonerType, group));
if (itr != _tempSummonDataStore.end())
return &itr->second;
-
+
return NULL;
}
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 3cdd3d854a1..f3201401c8d 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -152,7 +152,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
}
receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid);
- canReceiveMailFromOtherFaction = AccountMgr::HasPermission(receiverAccountId, RBAC_PERM_TWO_SIDE_INTERACTION_MAIL, realmID);
+ canReceiveMailFromOtherFaction = AccountMgr::HasPermission(receiverAccountId, RBAC_PERM_TWO_SIDE_INTERACTION_MAIL, realmID);
}
// do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 3864acb8f88..3cd937216b8 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -475,13 +475,13 @@ void WorldSession::HandleTogglePvP(WorldPacket& recvData)
if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
{
- if (!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.endTimer != 0)
+ if (!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.EndTimer)
GetPlayer()->UpdatePvP(true, true);
}
else
{
- if (!GetPlayer()->pvpInfo.inHostileArea && GetPlayer()->IsPvP())
- GetPlayer()->pvpInfo.endTimer = time(NULL); // start toggle-off
+ if (!GetPlayer()->pvpInfo.IsHostile && GetPlayer()->IsPvP())
+ GetPlayer()->pvpInfo.EndTimer = time(NULL); // start toggle-off
}
//if (OutdoorPvP* pvp = _player->GetOutdoorPvP())
@@ -1259,7 +1259,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recvData)
std::string charname;
recvData >> charname;
- if (HasPermission(RBAC_PERM_OPCODE_WHOIS))
+ if (!HasPermission(RBAC_PERM_OPCODE_WHOIS))
{
SendNotification(LANG_YOU_NOT_HAVE_PERMISSION);
return;
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 3308c7bee24..5b023fa160c 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -174,7 +174,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->UpdateZone(newzone, newarea);
// honorless target
- if (GetPlayer()->pvpInfo.inHostileArea)
+ if (GetPlayer()->pvpInfo.IsHostile)
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
// in friendly area
@@ -224,7 +224,7 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
if (old_zone != newzone)
{
// honorless target
- if (plMover->pvpInfo.inHostileArea)
+ if (plMover->pvpInfo.IsHostile)
plMover->CastSpell(plMover, 2479, true);
// in friendly area
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 4e5dbb306fa..2724a523667 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -425,10 +425,16 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData)
if (!_player->TakeQuestSourceItem(questId, true))
return; // can't un-equip some items, reject quest cancel
- if (const Quest *quest = sObjectMgr->GetQuestTemplate(questId))
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
if (quest->HasFlag(QUEST_TRINITY_FLAGS_TIMED))
_player->RemoveTimedQuest(questId);
+
+ if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
+ {
+ _player->pvpInfo.IsHostile = _player->pvpInfo.IsInHostileArea || _player->HasPvPForcingQuest();
+ _player->UpdatePvPState();
+ }
}
_player->TakeQuestSourceItem(questId, true); // remove quest src item from player
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 45cb8164775..8f63345925d 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -320,7 +320,6 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
-
if (!spellInfo)
{
sLog->outError(LOG_FILTER_NETWORKIO, "WORLD: unknown spell id %u", spellId);
@@ -328,31 +327,37 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
- if (mover->GetTypeId() == TYPEID_PLAYER)
+ if (spellInfo->IsPassive())
{
- // not have spell in spellbook or spell passive and not casted by client
- if (!mover->ToPlayer()->HasActiveSpell (spellId) || spellInfo->IsPassive())
- {
- //cheater? kick? ban?
- recvPacket.rfinish(); // prevent spam at ignore packet
- return;
- }
+ recvPacket.rfinish(); // prevent spam at ignore packet
+ return;
}
- else
+
+ Unit* caster = mover;
+ if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(spellId))
{
- // not have spell in spellbook or spell passive and not casted by client
- if ((mover->GetTypeId() == TYPEID_UNIT && !mover->ToCreature()->HasSpell(spellId)) || spellInfo->IsPassive())
+ // If the vehicle creature does not have the spell but it allows the passenger to cast own spells
+ // change caster to player and let him cast
+ if (!_player->IsOnVehicle(caster) || spellInfo->CheckVehicle(_player) != SPELL_CAST_OK)
{
- //cheater? kick? ban?
recvPacket.rfinish(); // prevent spam at ignore packet
return;
}
+
+ caster = _player;
+ }
+
+ if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellId))
+ {
+ // not have spell in spellbook
+ recvPacket.rfinish(); // prevent spam at ignore packet
+ return;
}
// Client is resending autoshot cast opcode when other spell is casted during shoot rotation
// Skip it to prevent "interrupt" message
- if (spellInfo->IsAutoRepeatRangedSpell() && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)
- && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo)
+ if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)
+ && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo)
{
recvPacket.rfinish();
return;
@@ -367,7 +372,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
// client provided targets
SpellCastTargets targets;
- targets.Read(recvPacket, mover);
+ targets.Read(recvPacket, caster);
HandleClientCastFlags(recvPacket, castFlags, targets);
// auto-selection buff level base at target level (in spellInfo)
@@ -380,7 +385,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
spellInfo = actualSpellInfo;
}
- Spell* spell = new Spell(mover, spellInfo, TRIGGERED_NONE, 0, false);
+ Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, 0, false);
spell->m_cast_count = castCount; // set count of casts
spell->prepare(&targets);
}
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index b7155e552c7..53334cffd18 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -269,7 +269,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
GetPlayer()->CleanupAfterTaxiFlight();
GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
- if (GetPlayer()->pvpInfo.inHostileArea)
+ if (GetPlayer()->pvpInfo.IsHostile)
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index cc47f053827..3deeb4e04b1 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -435,7 +435,7 @@ class Map : public GridRefManager<NGridType>
void UpdateIteratorBack(Player* player);
TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0);
- void SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list);
+ void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = NULL);
Creature* GetCreature(uint64 guid);
GameObject* GetGameObject(uint64 guid);
DynamicObject* GetDynamicObject(uint64 guid);
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 8bc628b853d..3fefa812489 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -207,6 +207,14 @@ int32 Quest::GetRewOrReqMoney() const
return int32(RewardOrRequiredMoney * sWorld->getRate(RATE_DROP_MONEY));
}
+uint32 Quest::GetRewMoneyMaxLevel() const
+{
+ if (HasFlag(QUEST_FLAGS_NO_MONEY_FROM_XP))
+ return 0;
+
+ return RewardMoneyMaxLevel;
+}
+
bool Quest::IsAutoAccept() const
{
return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? false : (Flags & QUEST_FLAGS_AUTO_ACCEPT);
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 9073c5d1441..a447f4a8f52 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -124,27 +124,27 @@ enum __QuestGiverStatus
enum QuestFlags
{
// Flags used at server and sent to client
- QUEST_FLAGS_NONE = 0x00000000,
- QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
- QUEST_FLAGS_PARTY_ACCEPT = 0x00000002, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
- QUEST_FLAGS_EXPLORATION = 0x00000004, // Not used currently
- QUEST_FLAGS_SHARABLE = 0x00000008, // Can be shared: Player::CanShareQuest()
- //QUEST_FLAGS_NONE2 = 0x00000010, // Not used currently
- QUEST_FLAGS_EPIC = 0x00000020, // Not used currently: Unsure of content
- QUEST_FLAGS_RAID = 0x00000040, // Not used currently
- QUEST_FLAGS_TBC = 0x00000080, // Not used currently: Available if TBC expansion enabled only
- QUEST_FLAGS_DELIVER_MORE = 0x00000100, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs
- QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
- QUEST_FLAGS_AUTO_REWARDED = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
- QUEST_FLAGS_TBC_RACES = 0x00000800, // Not used currently: Blood elf/Draenei starting zone quests
- QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one
- QUEST_FLAGS_REPEATABLE = 0x00002000, // Used on repeatable quests (3.0.0+)
- QUEST_FLAGS_UNAVAILABLE = 0x00004000, // Used on quests that are not generically available
- QUEST_FLAGS_WEEKLY = 0x00008000,
- QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // auto complete
- QUEST_FLAGS_SPECIAL_ITEM = 0x00020000, // has something to do with RequiredItemId and SourceItemId
- QUEST_FLAGS_OBJ_TEXT = 0x00040000, // use Objective text as Complete text
- QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
+ QUEST_FLAGS_NONE = 0x00000000,
+ QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
+ QUEST_FLAGS_PARTY_ACCEPT = 0x00000002, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
+ QUEST_FLAGS_EXPLORATION = 0x00000004, // Not used currently
+ QUEST_FLAGS_SHARABLE = 0x00000008, // Can be shared: Player::CanShareQuest()
+ QUEST_FLAGS_HAS_CONDITION = 0x00000010, // Not used currently
+ QUEST_FLAGS_HIDE_REWARD_POI = 0x00000020, // Not used currently: Unsure of content
+ QUEST_FLAGS_RAID = 0x00000040, // Not used currently
+ QUEST_FLAGS_TBC = 0x00000080, // Not used currently: Available if TBC expansion enabled only
+ QUEST_FLAGS_NO_MONEY_FROM_XP = 0x00000100, // Not used currently: Experience is not converted to gold at max level
+ QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
+ QUEST_FLAGS_TRACKING = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
+ QUEST_FLAGS_DEPRECATE_REPUTATION = 0x00000800, // Not used currently
+ QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one
+ QUEST_FLAGS_FLAGS_PVP = 0x00002000, // Having this quest in log forces PvP flag
+ QUEST_FLAGS_UNAVAILABLE = 0x00004000, // Used on quests that are not generically available
+ QUEST_FLAGS_WEEKLY = 0x00008000,
+ QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // auto complete
+ QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x00020000, // Displays usable item in quest tracker
+ QUEST_FLAGS_OBJ_TEXT = 0x00040000, // use Objective text as Complete text
+ QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
// Trinity flags for set SpecialFlags in DB if required but used only at server
QUEST_TRINITY_FLAGS_REPEATABLE = 0x00100000, // Set by 1 in SpecialFlags from DB
@@ -234,7 +234,7 @@ class Quest
int32 GetRewOrReqMoney() const;
uint32 GetRewHonorAddition() const { return RewardHonor; }
float GetRewHonorMultiplier() const { return RewardHonorMultiplier; }
- uint32 GetRewMoneyMaxLevel() const { return RewardMoneyMaxLevel; } // use in XP calculation at client
+ uint32 GetRewMoneyMaxLevel() const; // use in XP calculation at client
uint32 GetRewSpell() const { return RewardSpell; }
int32 GetRewSpellCast() const { return RewardSpellCast; }
uint32 GetRewMailTemplateId() const { return RewardMailTemplateId; }
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 1e36f342712..8ebb85d8084 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -1175,11 +1175,13 @@ void WorldSession::LoadPermissions()
{
uint32 id = GetAccountId();
std::string name;
- int32 realmId = ConfigMgr::GetIntDefault("RealmID", 0);
AccountMgr::GetName(id, name);
- _RBACData = new RBACData(id, name, realmId);
+ _RBACData = new RBACData(id, name, realmID);
_RBACData->LoadFromDB();
+
+ sLog->outDebug(LOG_FILTER_RBAC, "WorldSession::LoadPermissions [AccountId: %u, Name: %s, realmId: %d]",
+ id, name.c_str(), realmID);
}
RBACData* WorldSession::GetRBACData()
@@ -1189,5 +1191,20 @@ RBACData* WorldSession::GetRBACData()
bool WorldSession::HasPermission(uint32 permission)
{
- return _RBACData->HasPermission(permission);
+ if (!_RBACData)
+ LoadPermissions();
+
+ bool hasPermission = _RBACData->HasPermission(permission);
+ sLog->outDebug(LOG_FILTER_RBAC, "WorldSession::HasPermission [AccountId: %u, Name: %s, realmId: %d]",
+ _RBACData->GetId(), _RBACData->GetName().c_str(), realmID);
+
+ return hasPermission;
+}
+
+void WorldSession::InvalidateRBACData()
+{
+ sLog->outDebug(LOG_FILTER_RBAC, "WorldSession::InvalidateRBACData [AccountId: %u, Name: %s, realmId: %d]",
+ _RBACData->GetId(), _RBACData->GetName().c_str(), realmID);
+ delete _RBACData;
+ _RBACData = NULL;
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 20fa7d9335d..b714cd71e6d 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -220,6 +220,7 @@ class WorldSession
RBACData* GetRBACData();
bool HasPermission(uint32 permissionId);
void LoadPermissions();
+ void InvalidateRBACData(); // Used to force LoadPermissions at next HasPermission check
AccountTypes GetSecurity() const { return _security; }
uint32 GetAccountId() const { return _accountId; }
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index ae1389c5f11..342f0cfbddf 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -823,7 +823,8 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar
if (effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() &&
effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() &&
effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions &&
- effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster))
+ effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) &&
+ CheckScriptEffectImplicitTargets(effIndex, j))
{
effectMask |= 1 << j;
}
@@ -4831,34 +4832,12 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_MOVING;
}
-
- Vehicle* vehicle = m_caster->GetVehicle();
- if (vehicle && !(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE))
+ // Check vehicle flags
+ if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE))
{
- uint16 checkMask = 0;
- for (uint8 effIndex = EFFECT_0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
- {
- SpellEffectInfo const* effInfo = &m_spellInfo->Effects[effIndex];
- if (effInfo->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
- {
- SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(effInfo->MiscValue);
- if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag
- checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED;
- break;
- }
- }
-
- if (m_spellInfo->HasAura(SPELL_AURA_MOUNTED))
- checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL;
-
- if (!checkMask)
- checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK;
-
- // All creatures should be able to cast as passengers freely, restriction and attribute are only for players
- VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(m_caster);
- if (!(m_spellInfo->AttributesEx6 & SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE) && !(m_spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED)
- && (vehicleSeat->m_flags & checkMask) != checkMask && m_caster->GetTypeId() == TYPEID_PLAYER)
- return SPELL_FAILED_DONT_REPORT;
+ SpellCastResult vehicleCheck = m_spellInfo->CheckVehicle(m_caster);
+ if (vehicleCheck != SPELL_CAST_OK)
+ return vehicleCheck;
}
// check spell cast conditions from database
@@ -7153,6 +7132,29 @@ void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffI
}
}
+bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck)
+{
+ // Skip if there are not any script
+ if (!m_loadedScripts.size())
+ return true;
+
+ for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
+ {
+ std::list<SpellScript::ObjectTargetSelectHandler>::iterator targetSelectHookEnd = (*itr)->OnObjectTargetSelect.end(), targetSelectHookItr = (*itr)->OnObjectTargetSelect.begin();
+ for (; targetSelectHookItr != targetSelectHookEnd; ++targetSelectHookItr)
+ if (((*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) ||
+ (!(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)))
+ return false;
+
+ std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator areaTargetSelectHookEnd = (*itr)->OnObjectAreaTargetSelect.end(), areaTargetSelectHookItr = (*itr)->OnObjectAreaTargetSelect.begin();
+ for (; areaTargetSelectHookItr != areaTargetSelectHookEnd; ++areaTargetSelectHookItr)
+ if (((*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) ||
+ (!(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)))
+ return false;
+ }
+ return true;
+}
+
bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const
{
bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 903d4487c31..47ce299c05d 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -632,6 +632,7 @@ class Spell
void CallScriptAfterHitHandlers();
void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex);
void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex);
+ bool CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck);
std::list<SpellScript*> m_loadedScripts;
struct HitTriggerSpell
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9d3ec6630e5..2aa8b6daed8 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5041,6 +5041,12 @@ void Spell::EffectQuestClear(SpellEffIndex effIndex)
// we ignore unequippable quest items in this case, it's still be equipped
player->TakeQuestSourceItem(logQuest, false);
+
+ if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
+ {
+ player->pvpInfo.IsHostile = player->pvpInfo.IsInHostileArea || player->HasPvPForcingQuest();
+ player->UpdatePvPState();
+ }
}
}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 9a9369bad28..aea7689c051 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -23,6 +23,7 @@
#include "ConditionMgr.h"
#include "Player.h"
#include "Battleground.h"
+#include "Vehicle.h"
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
{
@@ -1174,10 +1175,8 @@ bool SpellInfo::IsSingleTarget() const
bool SpellInfo::IsSingleTargetWith(SpellInfo const* spellInfo) const
{
- // TODO - need better check
- // Equal icon and spellfamily
- if (SpellFamilyName == spellInfo->SpellFamilyName &&
- SpellIconID == spellInfo->SpellIconID)
+ // Same spell?
+ if (IsRankOf(spellInfo))
return true;
SpellSpecificType spec = GetSpellSpecific();
@@ -1616,6 +1615,56 @@ SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject c
return SPELL_CAST_OK;
}
+SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
+{
+ // All creatures should be able to cast as passengers freely, restriction and attribute are only for players
+ if (caster->GetTypeId() != TYPEID_PLAYER)
+ return SPELL_CAST_OK;
+
+ Vehicle* vehicle = caster->GetVehicle();
+ if (vehicle)
+ {
+ uint16 checkMask = 0;
+ for (uint8 effIndex = EFFECT_0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ if (Effects[effIndex].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
+ {
+ SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(Effects[effIndex].MiscValue);
+ if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag
+ checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED;
+ break;
+ }
+ }
+
+ if (HasAura(SPELL_AURA_MOUNTED))
+ checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL;
+
+ if (!checkMask)
+ checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK;
+
+ VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(caster);
+ if (!(AttributesEx6 & SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE) && !(Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED)
+ && (vehicleSeat->m_flags & checkMask) != checkMask)
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+
+ // Can only summon uncontrolled minions/guardians when on controlled vehicle
+ if (vehicleSeat->m_flags & (VEHICLE_SEAT_FLAG_CAN_CONTROL | VEHICLE_SEAT_FLAG_UNK2))
+ {
+ for (uint32 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (Effects[i].Effect != SPELL_EFFECT_SUMMON)
+ continue;
+
+ SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(Effects[i].MiscValueB);
+ if (props && props->Category != SUMMON_CATEGORY_WILD)
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+ }
+ }
+ }
+
+ return SPELL_CAST_OK;
+}
+
bool SpellInfo::CheckTargetCreatureType(Unit const* target) const
{
// Curse of Doom & Exorcism: not find another way to fix spell target check :/
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index bbc5b61e282..cc0a0101597 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -420,6 +420,7 @@ public:
SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const;
SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const;
SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const;
+ SpellCastResult CheckVehicle(Unit const* caster) const;
bool CheckTargetCreatureType(Unit const* target) const;
SpellSchoolMask GetSchoolMask() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 312189ffad8..1795c46b342 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -592,21 +592,6 @@ bool SpellMgr::IsSpellRequiringSpell(uint32 spellid, uint32 req_spellid) const
return false;
}
-const SpellsRequiringSpellMap SpellMgr::GetSpellsRequiringSpell()
-{
- return this->mSpellsReqSpell;
-}
-
-uint32 SpellMgr::GetSpellRequired(uint32 spell_id) const
-{
- SpellRequiredMap::const_iterator itr = mSpellReq.find(spell_id);
-
- if (itr == mSpellReq.end())
- return 0;
-
- return itr->second;
-}
-
SpellLearnSkillNode const* SpellMgr::GetSpellLearnSkill(uint32 spell_id) const
{
SpellLearnSkillMap::const_iterator itr = mSpellLearnSkills.find(spell_id);
@@ -777,7 +762,7 @@ SpellProcEventEntry const* SpellMgr::GetSpellProcEvent(uint32 spellId) const
return NULL;
}
-bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellProcEvent, uint32 EventProcFlag, SpellInfo const* procSpell, uint32 procFlags, uint32 procExtra, bool active)
+bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellProcEvent, uint32 EventProcFlag, SpellInfo const* procSpell, uint32 procFlags, uint32 procExtra, bool active) const
{
// No extra req need
uint32 procEvent_procEx = PROC_EX_NONE;
@@ -914,7 +899,7 @@ SpellProcEntry const* SpellMgr::GetSpellProcEntry(uint32 spellId) const
return NULL;
}
-bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo)
+bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const
{
// proc type doesn't match
if (!(eventInfo.GetTypeMask() & procEntry.typeMask))
@@ -1015,7 +1000,7 @@ SkillLineAbilityMapBounds SpellMgr::GetSkillLineAbilityMapBounds(uint32 spell_id
return mSkillLineAbilityMap.equal_range(spell_id);
}
-PetAura const* SpellMgr::GetPetAura(uint32 spell_id, uint8 eff)
+PetAura const* SpellMgr::GetPetAura(uint32 spell_id, uint8 eff) const
{
SpellPetAuraMap::const_iterator itr = mSpellPetAuraMap.find((spell_id<<8) + eff);
if (itr != mSpellPetAuraMap.end())
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 0cdb9601370..dcec7e84132 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -630,8 +630,6 @@ class SpellMgr
SpellRequiredMapBounds GetSpellsRequiredForSpellBounds(uint32 spell_id) const;
SpellsRequiringSpellMapBounds GetSpellsRequiringSpellBounds(uint32 spell_id) const;
bool IsSpellRequiringSpell(uint32 spellid, uint32 req_spellid) const;
- const SpellsRequiringSpellMap GetSpellsRequiringSpell();
- uint32 GetSpellRequired(uint32 spell_id) const;
// Spell learning
SpellLearnSkillNode const* GetSpellLearnSkill(uint32 spell_id) const;
@@ -656,11 +654,11 @@ class SpellMgr
// Spell proc event table
SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const;
- bool IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellProcEvent, uint32 EventProcFlag, SpellInfo const* procSpell, uint32 procFlags, uint32 procExtra, bool active);
+ bool IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellProcEvent, uint32 EventProcFlag, SpellInfo const* procSpell, uint32 procFlags, uint32 procExtra, bool active) const;
// Spell proc table
SpellProcEntry const* GetSpellProcEntry(uint32 spellId) const;
- bool CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo);
+ bool CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
// Spell bonus data table
SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const;
@@ -670,7 +668,7 @@ class SpellMgr
SkillLineAbilityMapBounds GetSkillLineAbilityMapBounds(uint32 spell_id) const;
- PetAura const* GetPetAura(uint32 spell_id, uint8 eff);
+ PetAura const* GetPetAura(uint32 spell_id, uint8 eff) const;
SpellEnchantProcEntry const* GetSpellEnchantProcEvent(uint32 enchId) const;
bool IsArenaAllowedEnchancment(uint32 ench_id) const;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 955f3b7b99f..bcd69ec70ed 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -3122,3 +3122,11 @@ CharacterNameData const* World::GetCharacterNameData(uint32 guid) const
else
return NULL;
}
+
+void World::ReloadRBAC()
+{
+ sLog->outInfo(LOG_FILTER_RBAC, "World::ReloadRBAC()");
+ for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ if (WorldSession* session = itr->second)
+ session->InvalidateRBACData();
+}
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 612078f17bf..154e9972218 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -739,6 +739,9 @@ class World
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
void ResetEventSeasonalQuests(uint16 event_id);
+
+ void ReloadRBAC();
+
protected:
void _UpdateGameTime();
// callback for UpdateRealmCharacters
diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp
index e10cf883518..e0d67b55989 100644
--- a/src/server/scripts/Commands/cs_quest.cpp
+++ b/src/server/scripts/Commands/cs_quest.cpp
@@ -138,6 +138,12 @@ public:
// we ignore unequippable quest items in this case, its' still be equipped
player->TakeQuestSourceItem(logQuest, false);
+
+ if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
+ {
+ player->pvpInfo.IsHostile = player->pvpInfo.IsInHostileArea || player->HasPvPForcingQuest();
+ player->UpdatePvPState();
+ }
}
}
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index b2542d6a668..7aee1139868 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -22,6 +22,7 @@ Comment: All reload related commands
Category: commandscripts
EndScriptData */
+#include "AccountMgr.h"
#include "AchievementMgr.h"
#include "AuctionHouseMgr.h"
#include "Chat.h"
@@ -86,6 +87,7 @@ public:
{ "creature_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesCreatureCommand, "", NULL },
{ "creature_onkill_reputation", SEC_ADMINISTRATOR, true, &HandleReloadOnKillReputationCommand, "", NULL },
{ "creature_questrelation", SEC_ADMINISTRATOR, true, &HandleReloadCreatureQuestRelationsCommand, "", NULL },
+ { "creature_summon_groups", SEC_ADMINISTRATOR, true, &HandleReloadCreatureSummonGroupsCommand, "", NULL },
{ "creature_template", SEC_ADMINISTRATOR, true, &HandleReloadCreatureTemplateCommand, "", NULL },
//{ "db_script_string", SEC_ADMINISTRATOR, true, &HandleReloadDbScriptStringCommand, "", NULL },
{ "disables", SEC_ADMINISTRATOR, true, &HandleReloadDisablesCommand, "", NULL },
@@ -127,6 +129,7 @@ public:
{ "prospecting_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesProspectingCommand, "", NULL },
{ "quest_poi", SEC_ADMINISTRATOR, true, &HandleReloadQuestPOICommand, "", NULL },
{ "quest_template", SEC_ADMINISTRATOR, true, &HandleReloadQuestTemplateCommand, "", NULL },
+ { "rbac", SEC_ADMINISTRATOR, true, &HandleReloadRBACCommand, "", NULL },
{ "reference_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesReferenceCommand, "", NULL },
{ "reserved_name", SEC_ADMINISTRATOR, true, &HandleReloadReservedNameCommand, "", NULL },
{ "reputation_reward_rate", SEC_ADMINISTRATOR, true, &HandleReloadReputationRewardRateCommand, "", NULL },
@@ -195,6 +198,8 @@ public:
HandleReloadTrinityStringCommand(handler, "");
HandleReloadGameTeleCommand(handler, "");
+ HandleReloadCreatureSummonGroupsCommand(handler, "");
+
HandleReloadVehicleAccessoryCommand(handler, "");
HandleReloadVehicleTemplateAccessoryCommand(handler, "");
@@ -397,6 +402,14 @@ public:
return true;
}
+ static bool HandleReloadCreatureSummonGroupsCommand(ChatHandler* handler, const char* /*args*/)
+ {
+ sLog->outInfo(LOG_FILTER_GENERAL, "Reloading creature summon groups...");
+ sObjectMgr->LoadTempSummons();
+ handler->SendGlobalGMSysMessage("DB table `creature_summon_groups` reloaded.");
+ return true;
+ }
+
static bool HandleReloadCreatureTemplateCommand(ChatHandler* handler, const char* args)
{
if (!*args)
@@ -1231,6 +1244,15 @@ public:
handler->SendGlobalGMSysMessage("Vehicle template accessories reloaded.");
return true;
}
+
+ static bool HandleReloadRBACCommand(ChatHandler* handler, const char* /*args*/)
+ {
+ sLog->outInfo(LOG_FILTER_GENERAL, "Reloading RBAC tables...");
+ sAccountMgr->LoadRBAC();
+ sWorld->ReloadRBAC();
+ handler->SendGlobalGMSysMessage("RBAC data reloaded.");
+ return true;
+ }
};
void AddSC_reload_commandscript()
diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp
index a9b41b719f7..d1670171d67 100644
--- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp
@@ -74,32 +74,32 @@ public:
//Shadowflame Timer
if (ShadowFlame_Timer <= diff)
{
- DoCast(me->getVictim(), SPELL_SHADOWFLAME);
+ DoCastVictim(SPELL_SHADOWFLAME);
ShadowFlame_Timer = urand(12000, 15000);
} else ShadowFlame_Timer -= diff;
//Thrash Timer
if (Thrash_Timer <= diff)
{
- DoCast(me->getVictim(), SPELL_THRASH);
+ DoCastVictim(SPELL_THRASH);
Thrash_Timer = urand(10000, 15000);
} else Thrash_Timer -= diff;
//Wing Buffet Timer
if (WingBuffet_Timer <= diff)
{
- DoCast(me->getVictim(), SPELL_WINGBUFFET);
+ DoCastVictim(SPELL_WINGBUFFET);
WingBuffet_Timer = 25000;
} else WingBuffet_Timer -= diff;
//Shadow of Ebonroc Timer
if (ShadowOfEbonroc_Timer <= diff)
{
- DoCast(me->getVictim(), SPELL_SHADOWOFEBONROC);
+ DoCastVictim(SPELL_SHADOWOFEBONROC);
ShadowOfEbonroc_Timer = urand(25000, 350000);
} else ShadowOfEbonroc_Timer -= diff;
- if (me->getVictim()->HasAura(SPELL_SHADOWOFEBONROC))
+ if (me->getVictim() && me->getVictim()->HasAura(SPELL_SHADOWOFEBONROC))
{
if (Heal_Timer <= diff)
{
diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp
index 83fac35b1b6..65ebb46c5dd 100644
--- a/src/server/scripts/World/areatrigger_scripts.cpp
+++ b/src/server/scripts/World/areatrigger_scripts.cpp
@@ -432,10 +432,10 @@ class AreaTrigger_at_area_52_entrance : public AreaTriggerScript
enum FrostgripsHollow
{
QUEST_THE_LONESOME_WATCHER = 12877,
-
+
NPC_STORMFORGED_MONITOR = 29862,
NPC_STORMFORGED_ERADICTOR = 29861,
-
+
TYPE_WAYPOINT = 0,
DATA_START = 0
};
@@ -460,11 +460,11 @@ public:
Creature* stormforgedMonitor = Creature::GetCreature(*player, stormforgedMonitorGUID);
if (stormforgedMonitor)
return false;
-
+
Creature* stormforgedEradictor = Creature::GetCreature(*player, stormforgedEradictorGUID);
if (stormforgedEradictor)
return false;
-
+
if ((stormforgedMonitor = player->SummonCreature(NPC_STORMFORGED_MONITOR, stormforgedMonitorPosition, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000)))
{
stormforgedMonitorGUID = stormforgedMonitor->GetGUID();
@@ -479,7 +479,7 @@ public:
stormforgedEradictorGUID = stormforgedEradictor->GetGUID();
stormforgedEradictor->GetMotionMaster()->MovePath(NPC_STORMFORGED_ERADICTOR * 100, false);
}
-
+
return true;
}
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
index f4e4ce7fe06..44a7749334d 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -170,7 +170,7 @@ enum LocaleConstant
};
const uint8 TOTAL_LOCALES = 9;
-const LocaleConstant DEFAULT_LOCALE = LOCALE_enUS;
+#define DEFAULT_LOCALE LOCALE_enUS
#define MAX_LOCALES 8
#define MAX_ACCOUNT_TUTORIAL_VALUES 8
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index fa02b1d369a..c43cc8fab82 100644
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -222,7 +222,7 @@ class DatabaseWorkerPool
//! Directly executes an SQL query in string format that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
- QueryResult Query(const char* sql, MySQLConnection* conn = NULL)
+ QueryResult Query(const char* sql, T* conn = NULL)
{
if (!conn)
conn = GetFreeConnection();
@@ -241,7 +241,7 @@ class DatabaseWorkerPool
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
- QueryResult PQuery(const char* sql, MySQLConnection* conn, ...)
+ QueryResult PQuery(const char* sql, T* conn, ...)
{
if (!sql)
return QueryResult(NULL);
@@ -380,7 +380,7 @@ class DatabaseWorkerPool
//! were appended to the transaction will be respected during execution.
void DirectCommitTransaction(SQLTransaction& transaction)
{
- MySQLConnection* con = GetFreeConnection();
+ T* con = GetFreeConnection();
if (con->ExecuteTransaction(transaction))
{
con->Unlock(); // OK, operation succesful
@@ -490,17 +490,17 @@ class DatabaseWorkerPool
{
uint8 i = 0;
size_t num_cons = _connectionCount[IDX_SYNCH];
+ T* t = NULL;
//! Block forever until a connection is free
for (;;)
{
- T* t = _connections[IDX_SYNCH][++i % num_cons];
+ t = _connections[IDX_SYNCH][++i % num_cons];
//! Must be matched with t->Unlock() or you will get deadlocks
if (t->LockIfReady())
- return t;
+ break;
}
- //! This will be called when Celine Dion learns to sing
- return NULL;
+ return t;
}
char const* GetDatabaseName() const
diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp
index 1d215e1212e..efb141d1060 100644
--- a/src/server/shared/Logging/Appender.cpp
+++ b/src/server/shared/Logging/Appender.cpp
@@ -216,6 +216,8 @@ char const* Appender::getLogFilterTypeString(LogFilterType type)
return "OPCODE";
case LOG_FILTER_SOAP:
return "SOAP";
+ case LOG_FILTER_RBAC:
+ return "RBAC";
default:
break;
}
diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h
index 08628948b90..e11bc40c42f 100644
--- a/src/server/shared/Logging/Appender.h
+++ b/src/server/shared/Logging/Appender.h
@@ -67,7 +67,8 @@ enum LogFilterType
LOG_FILTER_BATTLEFIELD = 39,
LOG_FILTER_SERVER_LOADING = 40,
LOG_FILTER_OPCODES = 41,
- LOG_FILTER_SOAP = 42
+ LOG_FILTER_SOAP = 42,
+ LOG_FILTER_RBAC = 43
};
const uint8 MaxLogFilter = 43;
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 069c027d139..7c8aff9ce3a 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2789,6 +2789,7 @@ Appenders=Console Server GM DBErrors Char RA Warden Chat
# 40 - Server Loading
# 41 - Opcodes (just id and name sent / received)
# 42 - SOAP
+# 43 - RBAC (Role Based Access Control)
#
# LogLevel
# 0 - (Disabled)