aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp3
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp13
-rw-r--r--src/server/game/Accounts/AccountMgr.h1
-rw-r--r--src/server/game/Accounts/RBAC.h57
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp47
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp52
-rw-r--r--src/server/game/Chat/Chat.cpp5
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp1
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp1
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h16
-rw-r--r--src/server/game/Entities/Object/Object.cpp37
-rw-r--r--src/server/game/Entities/Object/Object.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp15
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp71
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp86
-rw-r--r--src/server/game/Globals/ObjectMgr.h42
-rw-r--r--src/server/game/Guilds/Guild.cpp7
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp4
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp81
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp24
-rw-r--r--src/server/game/Handlers/MailHandler.cpp125
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp49
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp11
-rw-r--r--src/server/game/Maps/Map.h1
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h4
-rw-r--r--src/server/game/Server/WorldSession.cpp1
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Server/WorldSocket.cpp2
-rw-r--r--src/server/game/Spells/Spell.cpp7
-rw-r--r--src/server/game/Spells/SpellEffects.cpp6
-rw-r--r--src/server/game/World/World.cpp43
-rw-r--r--src/server/scripts/Commands/cs_gm.cpp46
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp8
-rw-r--r--src/server/scripts/Commands/cs_rbac.cpp4
-rw-r--r--src/server/scripts/Commands/cs_ticket.cpp12
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp2
-rw-r--r--src/server/scripts/World/areatrigger_scripts.cpp64
-rw-r--r--src/server/worldserver/TCSoap/TCSoap.cpp3
-rw-r--r--src/server/worldserver/TCSoap/TCSoap.h10
41 files changed, 661 insertions, 310 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 7f0d387c2f1..e0e9e68315d 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -146,8 +146,7 @@ void UnitAI::DoCast(uint32 spellId)
float range = spellInfo->GetMaxRange(false);
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
- if (!(spellInfo->Attributes & SPELL_ATTR0_BREAKABLE_BY_DAMAGE)
- && !(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM)
+ if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM)
&& targetSelector(me->getVictim()))
target = me->getVictim();
else
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 596f7f5ceb9..7172efaac0e 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -544,3 +544,16 @@ RBACPermission const* AccountMgr::GetRBACPermission(uint32 permission) const
return NULL;
}
+
+bool AccountMgr::HasPermission(uint32 accountId, uint32 permission, uint32 realmId)
+{
+ if (!accountId)
+ return false;
+
+ RBACData* rbac = new RBACData(accountId, "", realmId);
+ rbac->LoadFromDB();
+ bool hasPermission = rbac->HasPermission(permission);
+ delete rbac;
+
+ return hasPermission;
+}
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index 2c07172723d..28373456994 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -67,6 +67,7 @@ class AccountMgr
static bool IsGMAccount(uint32 gmlevel);
static bool IsAdminAccount(uint32 gmlevel);
static bool IsConsoleAccount(uint32 gmlevel);
+ static bool HasPermission(uint32 accountId, uint32 permission, uint32 realmId);
void UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId);
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index f6e494e7b70..0bd193d3841 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -48,16 +48,53 @@
enum RBACPermissions
{
- RBAC_PERM_INSTANT_LOGOUT = 1,
- RBAC_PERM_SKIP_QUEUE,
- RBAC_PERM_JOIN_NORMAL_BG,
- RBAC_PERM_JOIN_RANDOM_BG,
- RBAC_PERM_JOIN_ARENAS,
- RBAC_PERM_JOIN_DUNGEON_FINDER,
- RBAC_PERM_PLAYER_COMMANDS,
- RBAC_PERM_MODERATOR_COMMANDS,
- RBAC_PERM_GAMEMASTER_COMMANDS,
- RBAC_PERM_ADMINISTRATOR_COMMANDS,
+ RBAC_PERM_INSTANT_LOGOUT = 1,
+ RBAC_PERM_SKIP_QUEUE = 2,
+ RBAC_PERM_JOIN_NORMAL_BG = 3,
+ RBAC_PERM_JOIN_RANDOM_BG = 4,
+ RBAC_PERM_JOIN_ARENAS = 5,
+ RBAC_PERM_JOIN_DUNGEON_FINDER = 6,
+ RBAC_PERM_PLAYER_COMMANDS = 7,
+ RBAC_PERM_MODERATOR_COMMANDS = 8,
+ RBAC_PERM_GAMEMASTER_COMMANDS = 9,
+ RBAC_PERM_ADMINISTRATOR_COMMANDS = 10,
+ RBAC_PERM_LOG_GM_TRADE = 11,
+ // Free = 12
+ RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13,
+ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14,
+ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15,
+ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK = 16,
+ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME = 17,
+ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER = 18,
+ RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ = 19,
+ RBAC_PERM_SKIP_CHECK_DISABLE_MAP = 20,
+ RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED = 21,
+ RBAC_PERM_SKIP_CHECK_CHAT_SPAM = 22,
+ RBAC_PERM_SKIP_CHECK_OVERSPEED_PING = 23,
+ RBAC_PERM_TWO_SIDE_CHARACTER_CREATION = 24,
+ RBAC_PERM_TWO_SIDE_INTERACTION_CHAT = 25,
+ RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL = 26,
+ RBAC_PERM_TWO_SIDE_INTERACTION_MAIL = 27,
+ RBAC_PERM_TWO_SIDE_WHO_LIST = 28,
+ RBAC_PERM_TWO_SIDE_ADD_FRIEND = 29,
+ RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY = 30,
+ RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS = 31,
+ RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET = 32,
+ RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR = 33,
+ RBAC_PERM_COMMANDS_APPEAR_IN_GM_LIST = 34,
+ RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS = 35,
+ RBAC_PERM_CAN_FILTER_WHISPERS = 36,
+ RBAC_PERM_CHAT_USE_STAFF_BADGE = 37,
+ RBAC_PERM_RESURRECT_WITH_FULL_HPS = 38,
+ RBAC_PERM_RESTORE_SAVED_GM_STATE = 39,
+ RBAC_PERM_ALLOW_GM_FRIEND = 40,
+ RBAC_PERM_USE_START_GM_LEVEL = 41,
+ RBAC_PERM_OPCODE_WORLD_TELEPORT = 42,
+ RBAC_PERM_OPCODE_WHOIS = 43,
+ RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE = 44,
+ RBAC_PERM_SILENTLY_JOIN_CHANNEL = 45,
+ RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR = 46,
+ RBAC_PERM_CHECK_FOR_LOWER_SECURITY = 47,
RBAC_PERM_MAX
};
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 67bc094797f..906ce520bd1 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -93,46 +93,45 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
if (!pItem)
return;
- uint32 bidder_accId = 0;
- uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
- Player* bidder = ObjectAccessor::FindPlayer(bidder_guid);
+ uint32 bidderAccId = 0;
+ uint64 bidderGuid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
+ Player* bidder = ObjectAccessor::FindPlayer(bidderGuid);
// data for gm.log
if (sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
- uint32 bidder_security = 0;
- std::string bidder_name;
+ std::string bidderName;
+ bool logGmTrade = false;
+
if (bidder)
{
- bidder_accId = bidder->GetSession()->GetAccountId();
- bidder_security = bidder->GetSession()->GetSecurity();
- bidder_name = bidder->GetName();
+ bidderAccId = bidder->GetSession()->GetAccountId();
+ bidderName = bidder->GetName();
+ logGmTrade = bidder->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE);
}
else
{
- bidder_accId = sObjectMgr->GetPlayerAccountIdByGUID(bidder_guid);
- bidder_security = AccountMgr::GetSecurity(bidder_accId, realmID);
+ bidderAccId = sObjectMgr->GetPlayerAccountIdByGUID(bidderGuid);
+ logGmTrade = AccountMgr::HasPermission(bidderAccId, RBAC_PERM_LOG_GM_TRADE, realmID);
- if (!AccountMgr::IsPlayerAccount(bidder_security)) // not do redundant DB requests
- {
- if (!sObjectMgr->GetPlayerNameByGUID(bidder_guid, bidder_name))
- bidder_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
- }
+ if (logGmTrade && !sObjectMgr->GetPlayerNameByGUID(bidderGuid, bidderName))
+ bidderName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
}
- if (!AccountMgr::IsPlayerAccount(bidder_security))
+
+ if (logGmTrade)
{
- std::string owner_name;
- if (!sObjectMgr->GetPlayerNameByGUID(auction->owner, owner_name))
- owner_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
+ std::string ownerName;
+ if (!sObjectMgr->GetPlayerNameByGUID(auction->owner, ownerName))
+ ownerName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
- uint32 owner_accid = sObjectMgr->GetPlayerAccountIdByGUID(auction->owner);
+ uint32 ownerAccId = sObjectMgr->GetPlayerAccountIdByGUID(auction->owner);
- sLog->outCommand(bidder_accId, "GM %s (Account: %u) won item in auction: %s (Entry: %u Count: %u) and pay money: %u. Original owner %s (Account: %u)",
- bidder_name.c_str(), bidder_accId, pItem->GetTemplate()->Name1.c_str(), pItem->GetEntry(), pItem->GetCount(), auction->bid, owner_name.c_str(), owner_accid);
+ sLog->outCommand(bidderAccId, "GM %s (Account: %u) won item in auction: %s (Entry: %u Count: %u) and pay money: %u. Original owner %s (Account: %u)",
+ bidderName.c_str(), bidderAccId, pItem->GetTemplate()->Name1.c_str(), pItem->GetEntry(), pItem->GetCount(), auction->bid, ownerName.c_str(), ownerAccId);
}
}
// receiver exist
- if (bidder || bidder_accId)
+ if (bidder || bidderAccId)
{
// set owner to bidder (to prevent delete item with sender char deleting)
// owner in `data` will set at mail receive and item extracting
@@ -143,7 +142,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
if (bidder)
{
- bidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->itemEntry);
+ bidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, bidderGuid, 0, 0, auction->itemEntry);
// FIXME: for offline player need also
bidder->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS, 1);
}
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 9e7a63c9093..5f6bc8b7865 100644
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -180,7 +180,7 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
if (HasFlag(CHANNEL_FLAG_LFG) &&
sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL) &&
- AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) &&
+ AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) && //FIXME: Move to RBAC
player->GetGroup())
{
WorldPacket data;
@@ -191,8 +191,8 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
player->JoinedChannel(this);
- if (_announce && (!AccountMgr::IsGMAccount(player->GetSession()->GetSecurity()) ||
- !sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL)))
+ if (_announce && (!sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL) ||
+ !player->GetSession()->HasPermission(RBAC_PERM_SILENTLY_JOIN_CHANNEL)))
{
WorldPacket data;
MakeJoined(&data, guid);
@@ -252,8 +252,9 @@ void Channel::LeaveChannel(Player* player, bool send)
bool changeowner = playersStore[guid].IsOwner();
playersStore.erase(guid);
- if (_announce && (!AccountMgr::IsGMAccount(player->GetSession()->GetSecurity()) ||
- !sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL)))
+
+ if (_announce && (!sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL) ||
+ !player->GetSession()->HasPermission(RBAC_PERM_SILENTLY_JOIN_CHANNEL)))
{
WorldPacket data;
MakeLeft(&data, guid);
@@ -279,7 +280,6 @@ void Channel::LeaveChannel(Player* player, bool send)
void Channel::KickOrBan(Player const* player, std::string const& badname, bool ban)
{
- AccountTypes sec = player->GetSession()->GetSecurity();
uint64 good = player->GetGUID();
if (!IsOn(good))
@@ -290,7 +290,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b
return;
}
- if (!playersStore[good].IsModerator() && !AccountMgr::IsGMAccount(sec))
+ if (!playersStore[good].IsModerator() && !player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR))
{
WorldPacket data;
MakeNotModerator(&data);
@@ -310,7 +310,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b
bool changeowner = _ownerGUID == victim;
- if (!AccountMgr::IsGMAccount(sec) && changeowner && good != _ownerGUID)
+ if (!player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && changeowner && good != _ownerGUID)
{
WorldPacket data;
MakeNotOwner(&data);
@@ -318,7 +318,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b
return;
}
- bool notify = !(AccountMgr::IsGMAccount(sec) && sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL));
+ bool notify = !sWorld->getBoolConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL) || !player->GetSession()->HasPermission(RBAC_PERM_SILENTLY_JOIN_CHANNEL);
if (ban && !IsBanned(victim))
{
@@ -363,7 +363,7 @@ void Channel::UnBan(Player const* player, std::string const& badname)
return;
}
- if (!playersStore[good].IsModerator() && !AccountMgr::IsGMAccount(sec))
+ if (!playersStore[good].IsModerator() && !player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR))
{
WorldPacket data;
MakeNotModerator(&data);
@@ -404,7 +404,7 @@ void Channel::Password(Player const* player, std::string const& pass)
return;
}
- if (!playersStore[guid].IsModerator() && !AccountMgr::IsGMAccount(player->GetSession()->GetSecurity()))
+ if (!playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR))
{
WorldPacket data;
MakeNotModerator(&data);
@@ -424,7 +424,6 @@ void Channel::Password(Player const* player, std::string const& pass)
void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bool set)
{
uint64 guid = player->GetGUID();
- uint32 sec = player->GetSession()->GetSecurity();
if (!IsOn(guid))
{
@@ -434,7 +433,7 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo
return;
}
- if (!playersStore[guid].IsModerator() && !AccountMgr::IsGMAccount(sec))
+ if (!playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR))
{
WorldPacket data;
MakeNotModerator(&data);
@@ -449,10 +448,11 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo
uint64 victim = newp ? newp->GetGUID() : 0;
if (!victim || !IsOn(victim) ||
+ (player->GetTeam() != newp->GetTeam() && (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL) ||
+ !player->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL) ||
+ !newp->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL))))
// allow make moderator from another team only if both is GMs
// at this moment this only way to show channel post for GM from another team
- ((!AccountMgr::IsGMAccount(sec) || !AccountMgr::IsGMAccount(newp->GetSession()->GetSecurity())) &&
- player->GetTeam() != newp->GetTeam() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)))
{
WorldPacket data;
MakePlayerNotFound(&data, p2n);
@@ -477,7 +477,6 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo
void Channel::SetOwner(Player const* player, std::string const& newname)
{
uint64 guid = player->GetGUID();
- uint32 sec = player->GetSession()->GetSecurity();
if (!IsOn(guid))
{
@@ -487,7 +486,7 @@ void Channel::SetOwner(Player const* player, std::string const& newname)
return;
}
- if (!AccountMgr::IsGMAccount(sec) && guid != _ownerGUID)
+ if (!player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && guid != _ownerGUID)
{
WorldPacket data;
MakeNotOwner(&data);
@@ -553,7 +552,9 @@ void Channel::List(Player const* player)
// PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
- if (member && (!AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) || member->GetSession()->GetSecurity() <= AccountTypes(gmLevelInWhoList)) &&
+ if (member &&
+ (player->GetSession()->HasPermission(RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) ||
+ member->GetSession()->GetSecurity() <= AccountTypes(gmLevelInWhoList)) &&
member->IsVisibleGloballyFor(player))
{
data << uint64(i->first);
@@ -570,7 +571,6 @@ void Channel::List(Player const* player)
void Channel::Announce(Player const* player)
{
uint64 guid = player->GetGUID();
- uint32 sec = player->GetSession()->GetSecurity();
if (!IsOn(guid))
{
@@ -580,7 +580,7 @@ void Channel::Announce(Player const* player)
return;
}
- if (!playersStore[guid].IsModerator() && !AccountMgr::IsGMAccount(sec))
+ if (!playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR))
{
WorldPacket data;
MakeNotModerator(&data);
@@ -605,6 +605,11 @@ void Channel::Say(uint64 guid, std::string const& what, uint32 lang)
if (what.empty())
return;
+ uint8 chatTag = 0;
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ chatTag = player->GetChatTag();
+
+ // TODO: Add proper RBAC check
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL))
lang = LANG_UNIVERSAL;
@@ -633,8 +638,7 @@ void Channel::Say(uint64 guid, std::string const& what, uint32 lang)
data << uint64(guid);
data << uint32(what.size() + 1);
data << what;
- Player* player = ObjectAccessor::FindPlayer(guid);
- data << uint8(player ? player->GetChatTag() : 0);
+ data << uint8(chatTag);
SendToAll(&data, !playersStore[guid].IsModerator() ? guid : false);
}
@@ -668,7 +672,9 @@ void Channel::Invite(Player const* player, std::string const& newname)
return;
}
- if (newp->GetTeam() != player->GetTeam() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL))
+ if (newp->GetTeam() != player->GetTeam() && (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL) ||
+ !player->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL) ||
+ !newp->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL)))
{
WorldPacket data;
MakeInviteWrongFaction(&data);
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 12a98126dbf..62a148eae03 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -175,7 +175,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac
return false;
// ignore only for non-players for non strong checks (when allow apply command at least to same sec level)
- if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !strong && !sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY))
+ if (m_session->HasPermission(RBAC_PERM_CHECK_FOR_LOWER_SECURITY) && !strong && !sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY))
return false;
if (target)
@@ -361,6 +361,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, co
// table[i].Name == "" is special case: send original command to handler
if ((table[i].Handler)(this, table[i].Name[0] != '\0' ? text : oldtext))
{
+ // FIXME: When Command system is moved to RBAC this check must be changed
if (!AccountMgr::IsPlayerAccount(table[i].SecurityLevel))
{
// chat case
@@ -476,7 +477,7 @@ bool ChatHandler::ParseCommands(char const* text)
if (!ExecuteCommandInTable(getCommandTable(), text, fullcmd))
{
- if (m_session && AccountMgr::IsPlayerAccount(m_session->GetSecurity()))
+ if (m_session && !m_session->HasPermission(RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR))
return false;
SendSysMessage(LANG_NO_CMD);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index bc1fd27e093..01d675a35c1 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -431,6 +431,7 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
default:
break;
}
+ break;
case CONDITION_TYPE_MASK:
if (ConditionValue1 & TYPEMASK_UNIT)
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 9bb65b63557..ce18c227656 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -29,6 +29,7 @@
#include "LFGQueue.h"
#include "Group.h"
#include "Player.h"
+#include "RBAC.h"
#include "GroupMgr.h"
#include "GameEventMgr.h"
#include "WorldSession.h"
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index a96d9ab33d0..dc3347c5b4f 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -21,6 +21,22 @@
#include "Creature.h"
+enum SummonerType
+{
+ SUMMONER_TYPE_CREATURE = 0,
+ SUMMONER_TYPE_GAMEOBJECT = 1,
+ SUMMONER_TYPE_MAP = 2
+};
+
+/// Stores data for temp summons
+struct TempSummonData
+{
+ uint32 entry; ///< Entry of summoned creature
+ Position pos; ///< Position, where should be creature spawned
+ TempSummonType type; ///< Summon type, see TempSummonType for available types
+ uint32 time; ///< Despawn time, usable only with certain temp summon types
+};
+
class TempSummon : public Creature
{
public:
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index cb497d11d4f..1851847f408 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2463,6 +2463,24 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
return summon;
}
+/**
+* Summons group of creatures.
+*
+* @param group Id of group to summon.
+* @param list List to store pointers to summoned creatures.
+*/
+
+void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>& list)
+{
+ std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetId(), SUMMONER_TYPE_MAP, group);
+ if (!data)
+ return;
+
+ 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);
+}
+
void WorldObject::SetZoneScript()
{
if (Map* map = FindMap())
@@ -2542,6 +2560,25 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3
return summon;
}
+/**
+* Summons group of creatures. Should be called only by instances of Creature and GameObject classes.
+*
+* @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)
+{
+ ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!");
+
+ std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group);
+ if (!data)
+ return;
+
+ 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);
+}
+
Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive) const
{
Creature* creature = NULL;
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 8b61b6ec2c8..0f34c5df4b9 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -872,6 +872,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);
Creature* FindNearestCreature(uint32 entry, float range, bool alive = true) const;
GameObject* FindNearestGameObject(uint32 entry, float range) const;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index d72b906e6a5..e207c2535d0 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -671,7 +671,7 @@ Player::Player(WorldSession* session): Unit(true), phaseMgr(this)
//m_pad = 0;
// players always accept
- if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()))
+ if (!GetSession()->HasPermission(RBAC_PERM_CAN_FILTER_WHISPERS))
SetAcceptWhispers(true);
m_curSelection = 0;
@@ -1013,7 +1013,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
- if (!AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()))
+ if (m_session->HasPermission(RBAC_PERM_USE_START_GM_LEVEL))
{
uint32 gm_level = sWorld->getIntConfig(CONFIG_START_GM_LEVEL);
if (gm_level > start_level)
@@ -2072,7 +2072,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
return false;
}
- if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, mapid, this))
+ if (!GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_DISABLE_MAP) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, mapid, this))
{
sLog->outError(LOG_FILTER_MAPS, "Player (GUID: %u, name: %s) tried to enter a forbidden map %u", GetGUIDLow(), GetName().c_str(), mapid);
SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED);
@@ -3176,7 +3176,7 @@ void Player::InitTalentForLevel()
// if used more that have then reset
if (GetUsedTalentCount() > talentPointsForLevel)
{
- if (!AccountMgr::IsAdminAccount(GetSession()->GetSecurity()))
+ if (!GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED))
ResetTalents(true);
else
SetFreeTalentPoints(0);
@@ -16808,7 +16808,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// check name limitations
if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS ||
- (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && sObjectMgr->IsReservedName(m_name)))
+ (!GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) &&
+ sObjectMgr->IsReservedName(m_name)))
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_RENAME));
@@ -17366,7 +17367,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
outDebugValues();
// GM state
- if (!AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()))
+ if (GetSession()->HasPermission(RBAC_PERM_RESTORE_SAVED_GM_STATE))
{
switch (sWorld->getIntConfig(CONFIG_GM_LOGIN_STATE))
{
@@ -19871,7 +19872,7 @@ void Player::outDebugValues() const
void Player::UpdateSpeakTime()
{
// ignore chat spam protection for GMs in any mode
- if (!AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()))
+ if (!GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_CHAT_SPAM))
return;
time_t current = time (NULL);
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index db91fb90936..ec8e6672508 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -217,34 +217,38 @@ void SocialMgr::GetFriendInfo(Player* player, uint32 friendGUID, FriendInfo &fri
friendInfo.Level = 0;
friendInfo.Class = 0;
- Player* pFriend = ObjectAccessor::FindPlayer(friendGUID);
- if (!pFriend)
+ Player* target = ObjectAccessor::FindPlayer(friendGUID);
+ if (!target)
return;
- uint32 team = player->GetTeam();
- AccountTypes security = player->GetSession()->GetSecurity();
- bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
- AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
-
PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID);
if (itr != player->GetSocial()->m_playerSocialMap.end())
friendInfo.Note = itr->second.Note;
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
- if (pFriend &&
- (!AccountMgr::IsPlayerAccount(security) ||
- ((pFriend->GetTeam() == team || allowTwoSideWhoList) && (pFriend->GetSession()->GetSecurity() <= gmLevelInWhoList))) &&
- pFriend->IsVisibleGloballyFor(player))
+
+ if (!player->GetSession()->HasPermission(RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) &&
+ target->GetSession()->GetSecurity() > AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)))
+ return;
+
+ // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
+ if (target->GetTeam() != player->GetTeam() &&
+ !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST) && !player->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_WHO_LIST))
+ return;
+
+ if (target->IsVisibleGloballyFor(player))
{
- friendInfo.Status = FRIEND_STATUS_ONLINE;
- if (pFriend->isAFK())
- friendInfo.Status = FRIEND_STATUS_AFK;
- if (pFriend->isDND())
+ if (target->isDND())
friendInfo.Status = FRIEND_STATUS_DND;
- friendInfo.Area = pFriend->GetZoneId();
- friendInfo.Level = pFriend->getLevel();
- friendInfo.Class = pFriend->getClass();
+ else if (target->isAFK())
+ friendInfo.Status = FRIEND_STATUS_AFK;
+ else
+ friendInfo.Status = FRIEND_STATUS_ONLINE;
+
+ friendInfo.Area = target->GetZoneId();
+ friendInfo.Level = target->getLevel();
+ friendInfo.Class = target->getClass();
}
}
@@ -296,28 +300,29 @@ void SocialMgr::BroadcastToFriendListers(Player* player, WorldPacket* packet)
if (!player)
return;
- uint32 team = player->GetTeam();
- AccountTypes security = player->GetSession()->GetSecurity();
- uint32 guid = player->GetGUIDLow();
- AccountTypes gmLevelInWhoList = AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
- bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
-
for (SocialMap::const_iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
{
- PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(guid);
+ PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(player->GetGUID());
if (itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
{
- Player* pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
+ Player* target = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
+ if (!target || !target->IsInWorld())
+ continue;
+
+ if (!target->GetSession()->HasPermission(RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) &&
+ player->GetSession()->GetSecurity() > AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST)))
+ continue;
+
+ // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
+ if (target->GetTeam() != player->GetTeam() &&
+ !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST) &&
+ !target->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_WHO_LIST))
+ continue;
// PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
// MODERATOR, GAME MASTER, ADMINISTRATOR can see all
- if (pFriend && pFriend->IsInWorld() &&
- (!AccountMgr::IsPlayerAccount(pFriend->GetSession()->GetSecurity()) ||
- ((pFriend->GetTeam() == team || allowTwoSideWhoList) && security <= gmLevelInWhoList)) &&
- player->IsVisibleGloballyFor(pFriend))
- {
- pFriend->GetSession()->SendPacket(packet);
- }
+ if (player->IsVisibleGloballyFor(target))
+ target->GetSession()->SendPacket(packet);
}
}
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 040cd6a19f8..50b88f3dd27 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -524,7 +524,7 @@ bool Unit::HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura) const
AuraEffectList const& auras = GetAuraEffectsByType(type);
for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
if ((!excludeAura || excludeAura != (*itr)->GetSpellInfo()->Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction
- ((*itr)->GetSpellInfo()->Attributes & SPELL_ATTR0_BREAKABLE_BY_DAMAGE || (*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
+ ((*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
return true;
return false;
}
@@ -10013,7 +10013,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
// ..taken
AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
- if ((*i)->GetMiscValue() & GetMeleeDamageSchoolMask())
+ if ((*i)->GetMiscValue() & attacker->GetMeleeDamageSchoolMask())
TakenFlatBenefit += (*i)->GetAmount();
if (attType != RANGED_ATTACK)
@@ -10025,7 +10025,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
float TakenTotalMod = 1.0f;
// ..taken
- TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, GetMeleeDamageSchoolMask());
+ TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, attacker->GetMeleeDamageSchoolMask());
// .. taken pct (special attacks)
if (spellProto)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index f9a0ca80f90..c2fd3494c79 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -398,6 +398,7 @@ enum TriggerCastFlags
TRIGGERED_IGNORE_CASTER_AURAS = 0x00010000, //! Will ignore caster aura restrictions or requirements
TRIGGERED_DISALLOW_PROC_EVENTS = 0x00020000, //! Disallows proc events from triggered spell (default)
TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions
+ TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements
TRIGGERED_FULL_MASK = 0xFFFFFFFF
};
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 399087d1c0a..265b981639f 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1446,6 +1446,92 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow)
return true;
}
+void ObjectMgr::LoadTempSummons()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 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");
+
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 temp summons. DB table `creature_summon_groups` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 summonerId = fields[0].GetUInt32();
+ SummonerType summonerType = SummonerType(fields[1].GetUInt8());
+ uint8 group = fields[2].GetUInt8();
+
+ switch (summonerType)
+ {
+ case SUMMONER_TYPE_CREATURE:
+ if (!GetCreatureTemplate(summonerId))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has summoner with non existing entry %u for creature summoner type, skipped.", summonerId);
+ continue;
+ }
+ break;
+ case SUMMONER_TYPE_GAMEOBJECT:
+ if (!GetGameObjectTemplate(summonerId))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has summoner with non existing entry %u for gameobject summoner type, skipped.", summonerId);
+ continue;
+ }
+ break;
+ case SUMMONER_TYPE_MAP:
+ if (!sMapStore.LookupEntry(summonerId))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has summoner with non existing entry %u for map summoner type, skipped.", summonerId);
+ continue;
+ }
+ break;
+ default:
+ sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has unhandled summoner type %u for summoner %u, skipped.", summonerType, summonerId);
+ continue;
+ }
+
+ TempSummonData data;
+ data.entry = fields[3].GetUInt32();
+
+ if (!GetCreatureTemplate(data.entry))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has creature in group [Summoner ID: %u, Summoner Type: %u, Group ID: %u] with non existing creature entry %u, skipped.", summonerId, summonerType, group, data.entry);
+ continue;
+ }
+
+ float posX = fields[4].GetFloat();
+ float posY = fields[5].GetFloat();
+ float posZ = fields[6].GetFloat();
+ float orientation = fields[7].GetFloat();
+
+ data.pos.Relocate(posX, posY, posZ, orientation);
+
+ data.type = TempSummonType(fields[8].GetUInt8());
+
+ if (data.type > TEMPSUMMON_MANUAL_DESPAWN)
+ {
+ sLog->outError(LOG_FILTER_SQL, "Table `creature_summon_groups` has unhandled temp summon type %u in group [Summoner ID: %u, Summoner Type: %u, Group ID: %u] for creature entry %u, skipped.", data.type, summonerId, summonerType, group, data.entry);
+ continue;
+ }
+
+ data.time = fields[9].GetUInt32();
+
+ TempSummonGroupKey key(summonerId, summonerType, group);
+ _tempSummonDataStore[key].push_back(data);
+
+ ++count;
+
+ } while (result->NextRow());
+
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u temp summons in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadCreatures()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index d0963a224b7..9502bb343e0 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -25,6 +25,7 @@
#include "Creature.h"
#include "DynamicObject.h"
#include "GameObject.h"
+#include "TemporarySummon.h"
#include "Corpse.h"
#include "QuestDef.h"
#include "ItemPrototype.h"
@@ -416,9 +417,29 @@ 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;
+typedef std::map<TempSummonGroupKey, std::vector<TempSummonData> > TempSummonDataContainer;
typedef UNORDERED_MAP<uint32, CreatureLocale> CreatureLocaleContainer;
typedef UNORDERED_MAP<uint32, GameObjectLocale> GameObjectLocaleContainer;
typedef UNORDERED_MAP<uint32, ItemLocale> ItemLocaleContainer;
@@ -872,6 +893,7 @@ class ObjectMgr
void LoadCreatureTemplates();
void LoadCreatureTemplateAddons();
void CheckCreatureTemplate(CreatureTemplate const* cInfo);
+ void LoadTempSummons();
void LoadCreatures();
void LoadLinkedRespawn();
bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid);
@@ -984,6 +1006,24 @@ class ObjectMgr
return _mapObjectGuidsStore[MAKE_PAIR32(mapid, spawnMode)][cell_id];
}
+ /**
+ * Gets temp summon data for all creatures of specified group.
+ *
+ * @param summonerId Summoner's entry.
+ * @param summonerType Summoner's type, see SummonerType for available types.
+ * @param group Id of required group.
+ *
+ * @return null if group was not found, otherwise reference to the creature group data
+ */
+ std::vector<TempSummonData> const* GetSummonGroup(uint32 summonerId, SummonerType summonerType, uint8 group) const
+ {
+ TempSummonDataContainer::const_iterator itr = _tempSummonDataStore.find(TempSummonGroupKey(summonerId, summonerType, group));
+ if (itr != _tempSummonDataStore.end())
+ return &itr->second;
+
+ return NULL;
+ }
+
CreatureData const* GetCreatureData(uint32 guid) const
{
CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid);
@@ -1313,6 +1353,8 @@ class ObjectMgr
GameObjectDataContainer _gameObjectDataStore;
GameObjectLocaleContainer _gameObjectLocaleStore;
GameObjectTemplateContainer _gameObjectTemplateStore;
+ /// Stores temp summon data grouped by summoner's entry, summoner's type and group id
+ TempSummonDataContainer _tempSummonDataStore;
ItemTemplateContainer _itemTemplateStore;
ItemLocaleContainer _itemLocaleStore;
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index b112888d1b3..705bdfd8589 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1019,12 +1019,15 @@ void Guild::BankMoveItemData::LogBankEvent(SQLTransaction& trans, MoveItemData*
void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const
{
MoveItemData::LogAction(pFrom);
- if (!pFrom->IsBank() && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE) && !AccountMgr::IsPlayerAccount(m_pPlayer->GetSession()->GetSecurity())) // TODO: move to scripts
+ if (!pFrom->IsBank() && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE) &&
+ m_pPlayer->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE))
+ {
sLog->outCommand(m_pPlayer->GetSession()->GetAccountId(),
"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)",
m_pPlayer->GetName().c_str(), m_pPlayer->GetSession()->GetAccountId(),
pFrom->GetItem()->GetTemplate()->Name1.c_str(), pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(),
m_pGuild->GetId());
+ }
}
Item* Guild::BankMoveItemData::_StoreItem(SQLTransaction& trans, BankTab* pTab, Item* pItem, ItemPosCount& pos, bool clone) const
@@ -2009,7 +2012,7 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint64 amount, bool
std::string aux = ByteArrayToHexStr(reinterpret_cast<uint8*>(&amount), 8, true);
_BroadcastEvent(GE_BANK_MONEY_CHANGED, 0, aux.c_str());
- if (!AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (player->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(player->GetSession()->GetAccountId(),
"GM %s (Account: %u) deposit money (Amount: " UI64FMTD ") to guild bank (Guild ID %u)",
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index 17551df2181..59a1bcf6c33 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -269,7 +269,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
// Required stack size of auction matches to current item stack size, just move item to auctionhouse
if (itemsCount == 1 && item->GetCount() == count[i])
{
- if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount());
@@ -318,7 +318,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData)
return;
}
- if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
GetPlayerName().c_str(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount());
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 5dfba797448..a647a9098e0 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -299,7 +299,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases
- if (AccountMgr::IsPlayerAccount(GetSecurity()))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK))
{
if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED))
{
@@ -308,13 +308,17 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
uint32 team = Player::TeamForRace(race_);
switch (team)
{
- case ALLIANCE: disabled = mask & (1 << 0); break;
- case HORDE: disabled = mask & (1 << 1); break;
+ case ALLIANCE:
+ disabled = mask & (1 << 0);
+ break;
+ case HORDE:
+ disabled = mask & (1 << 1);
+ break;
}
if (disabled)
{
- data << (uint8)CHAR_CREATE_DISABLED;
+ data << uint8(CHAR_CREATE_DISABLED);
SendPacket(&data);
return;
}
@@ -324,7 +328,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_);
if (!classEntry)
{
- data << (uint8)CHAR_CREATE_FAILED;
+ data << uint8(CHAR_CREATE_FAILED);
SendPacket(&data);
sLog->outError(LOG_FILTER_NETWORKIO, "Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", class_, GetAccountId());
return;
@@ -333,7 +337,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_);
if (!raceEntry)
{
- data << (uint8)CHAR_CREATE_FAILED;
+ data << uint8(CHAR_CREATE_FAILED);
SendPacket(&data);
sLog->outError(LOG_FILTER_NETWORKIO, "Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", race_, GetAccountId());
return;
@@ -342,7 +346,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion race without Expansion account
if (raceEntry->expansion > Expansion())
{
- data << (uint8)CHAR_CREATE_EXPANSION;
+ data << uint8(CHAR_CREATE_EXPANSION);
sLog->outError(LOG_FILTER_NETWORKIO, "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, race_);
SendPacket(&data);
return;
@@ -351,13 +355,13 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion class without Expansion account
if (classEntry->expansion > Expansion())
{
- data << (uint8)CHAR_CREATE_EXPANSION_CLASS;
+ data << uint8(CHAR_CREATE_EXPANSION_CLASS);
sLog->outError(LOG_FILTER_NETWORKIO, "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, class_);
SendPacket(&data);
return;
}
- if (AccountMgr::IsPlayerAccount(GetSecurity()))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (race_ - 1)) & raceMaskDisabled)
@@ -366,7 +370,10 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
SendPacket(&data);
return;
}
+ }
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK))
+ {
uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
if ((1 << (class_ - 1)) & classMaskDisabled)
{
@@ -379,7 +386,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating with invalid name
if (!normalizePlayerName(name))
{
- data << (uint8)CHAR_NAME_NO_NAME;
+ data << uint8(CHAR_NAME_NO_NAME);
SendPacket(&data);
sLog->outError(LOG_FILTER_NETWORKIO, "Account:[%d] but tried to Create character with empty [name] ", GetAccountId());
return;
@@ -394,29 +401,32 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
return;
}
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(name))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(name))
{
- data << (uint8)CHAR_NAME_RESERVED;
+ data << uint8(CHAR_NAME_RESERVED);
SendPacket(&data);
return;
}
- // speedup check for heroic class disabled case
- uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
- if (heroic_free_slots == 0 && AccountMgr::IsPlayerAccount(GetSecurity()) && class_ == CLASS_DEATH_KNIGHT)
+ if (class_ == CLASS_DEATH_KNIGHT && !HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER))
{
- data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
- SendPacket(&data);
- return;
- }
+ // speedup check for heroic class disabled case
+ uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
+ if (heroic_free_slots == 0)
+ {
+ data << uint8(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
+ SendPacket(&data);
+ return;
+ }
- // speedup check for heroic class disabled case
- uint32 req_level_for_heroic = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
- {
- data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
- SendPacket(&data);
- return;
+ // speedup check for heroic class disabled case
+ uint32 req_level_for_heroic = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
+ if (req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
+ {
+ data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT);
+ SendPacket(&data);
+ return;
+ }
}
delete _charCreateCallback.GetParam(); // Delete existing if any, to make the callback chain reset to stage 0
@@ -507,7 +517,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
}
}
- bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
+ bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || HasPermission(RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
_charCreateCallback.FreeResult();
@@ -531,8 +541,9 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
bool haveSameRace = false;
uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
bool hasHeroicReqLevel = (heroicReqLevel == 0);
- bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
+ bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || HasPermission(RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
+ bool checkHeroicReqs = createInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER);
if (result)
{
@@ -542,7 +553,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
Field* field = result->Fetch();
uint8 accRace = field[1].GetUInt8();
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT)
+ if (checkHeroicReqs)
{
uint8 accClass = field[2].GetUInt8();
if (accClass == CLASS_DEATH_KNIGHT)
@@ -601,7 +612,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (!haveSameRace)
haveSameRace = createInfo->Race == accRace;
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT)
+ if (checkHeroicReqs)
{
uint8 acc_class = field[2].GetUInt8();
if (acc_class == CLASS_DEATH_KNIGHT)
@@ -630,7 +641,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
}
}
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT && !hasHeroicReqLevel)
+ if (checkHeroicReqs && !hasHeroicReqLevel)
{
WorldPacket data(SMSG_CHAR_CREATE, 1);
data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT);
@@ -1211,7 +1222,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
}
// check name limitations
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << uint8(CHAR_NAME_RESERVED);
@@ -1531,7 +1542,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
}
// check name limitations
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
{
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
data << uint8(CHAR_NAME_RESERVED);
@@ -1777,7 +1788,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
return;
}
- if (AccountMgr::IsPlayerAccount(GetSecurity()))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
if ((1 << (race - 1)) & raceMaskDisabled)
@@ -1808,7 +1819,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
}
// check name limitations
- if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newname))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newname))
{
WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1);
data << uint8(CHAR_NAME_RESERVED);
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index eef049fdb66..40547463323 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -327,20 +327,22 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
Player* receiver = sObjectAccessor->FindPlayerByName(to);
- bool senderIsPlayer = AccountMgr::IsPlayerAccount(GetSecurity());
- bool receiverIsPlayer = AccountMgr::IsPlayerAccount(receiver ? receiver->GetSession()->GetSecurity() : SEC_PLAYER);
- if (!receiver || (senderIsPlayer && !receiverIsPlayer && !receiver->isAcceptWhispers() && !receiver->IsInWhisperWhiteList(sender->GetGUID())))
+ if (!receiver || (!HasPermission(RBAC_PERM_CAN_FILTER_WHISPERS) &&
+ receiver->GetSession()->HasPermission(RBAC_PERM_CAN_FILTER_WHISPERS) &&
+ !receiver->isAcceptWhispers() && !receiver->IsInWhisperWhiteList(sender->GetGUID())))
{
SendPlayerNotFoundNotice(to);
return;
}
- if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && senderIsPlayer && receiverIsPlayer)
- if (GetPlayer()->GetTeam() != receiver->GetTeam())
- {
- SendWrongFactionNotice();
- return;
- }
+ if (GetPlayer()->GetTeam() != receiver->GetTeam() &&
+ (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) ||
+ !HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHAT) ||
+ !receiver->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_CHAT)))
+ {
+ SendWrongFactionNotice();
+ return;
+ }
if (GetPlayer()->HasAura(1852) && !receiver->isGameMaster())
{
@@ -349,7 +351,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
}
// If player is a Gamemaster and doesn't accept whisper, we auto-whitelist every player that the Gamemaster is talking to
- if (!senderIsPlayer && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID()))
+ if (HasPermission(RBAC_PERM_CAN_FILTER_WHISPERS) && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID()))
sender->AddWhisperWhiteList(receiver->GetGUID());
GetPlayer()->Whisper(msg, lang, receiver->GetGUID());
@@ -452,7 +454,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
} break;
case CHAT_MSG_CHANNEL:
{
- if (AccountMgr::IsPlayerAccount(GetSecurity()))
+ if (!HasPermission(RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ))
{
if (_player->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ))
{
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 48f11c596d2..b1f42f92a6d 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -33,7 +33,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
{
ObjectGuid mailbox;
uint64 money, COD;
- std::string receiver, subject, body;
+ std::string receiverName, subject, body;
uint32 bodyLength, subjectLength, receiverLength;
uint32 unk1, unk2;
@@ -46,7 +46,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
uint8 items_count = recvData.ReadBits(5); // attached items count
- if (items_count > MAX_MAIL_ITEMS) // client limit
+ if (items_count > MAX_MAIL_ITEMS) // client limit
{
GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS);
recvData.rfinish(); // set to end to avoid warnings spam
@@ -99,7 +99,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
recvData.ReadByteSeq(mailbox[5]);
subject = recvData.ReadString(subjectLength);
- receiver = recvData.ReadString(receiverLength);
+ receiverName = recvData.ReadString(receiverLength);
recvData.ReadByteSeq(mailbox[2]);
recvData.ReadByteSeq(mailbox[0]);
@@ -113,7 +113,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
- if (receiver.empty())
+ if (receiverName.empty())
return;
Player* player = _player;
@@ -124,21 +124,26 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
- uint64 rc = 0;
- if (normalizePlayerName(receiver))
- rc = sObjectMgr->GetPlayerGUIDByName(receiver);
+ uint64 receiverGuid = 0;
+ if (normalizePlayerName(receiverName))
+ receiverGuid = sObjectMgr->GetPlayerGUIDByName(receiverName);
- if (!rc)
+ if (!receiverGuid)
{
- sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
- player->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2);
+ sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s "
+ "and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
+ player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(),
+ items_count, money, COD, unk1, unk2);
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND);
return;
}
- sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2);
+ sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s "
+ "includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
+ player->GetGUIDLow(), receiverName.c_str(), GUID_LOPART(receiverGuid), subject.c_str(),
+ body.c_str(), items_count, money, COD, unk1, unk2);
- if (player->GetGUID() == rc)
+ if (player->GetGUID() == receiverGuid)
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF);
return;
@@ -154,58 +159,62 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
- Player* receive = ObjectAccessor::FindPlayer(rc);
+ Player* receiver = ObjectAccessor::FindPlayer(receiverGuid);
- uint32 rc_team = 0;
- uint8 mails_count = 0; //do not allow to send to one player more than 100 mails
- uint8 receiveLevel = 0;
+ uint32 receiverTeam = 0;
+ uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails
+ uint8 receiverLevel = 0;
+ uint32 receiverAccountId = 0;
+ bool canReceiveMailFromOtherFaction = false;
- if (receive)
+ if (receiver)
{
- rc_team = receive->GetTeam();
- mails_count = receive->GetMailSize();
- receiveLevel = receive->getLevel();
+ receiverTeam = receiver->GetTeam();
+ mailsCount = receiver->GetMailSize();
+ receiverLevel = receiver->getLevel();
+ receiverAccountId = receiver->GetSession()->GetAccountId();
+ canReceiveMailFromOtherFaction = receiver->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_MAIL);
}
else
{
- rc_team = sObjectMgr->GetPlayerTeamByGUID(rc);
+ receiverTeam = sObjectMgr->GetPlayerTeamByGUID(receiverGuid);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT);
-
- stmt->setUInt32(0, GUID_LOPART(rc));
+ stmt->setUInt32(0, GUID_LOPART(receiverGuid));
PreparedQueryResult result = CharacterDatabase.Query(stmt);
-
if (result)
{
Field* fields = result->Fetch();
- mails_count = fields[0].GetUInt64();
+ mailsCount = fields[0].GetUInt64();
}
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL);
-
- stmt->setUInt32(0, GUID_LOPART(rc));
+ stmt->setUInt32(0, GUID_LOPART(receiverGuid));
result = CharacterDatabase.Query(stmt);
-
if (result)
{
Field* fields = result->Fetch();
- receiveLevel = fields[0].GetUInt8();
+ receiverLevel = fields[0].GetUInt8();
}
+
+ receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid);
+ 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..
- if (mails_count > 100)
+
+ // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
+ if (mailsCount > 100)
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED);
return;
}
+
// test the receiver's Faction... or all items are account bound
bool accountBound = items_count ? true : false;
for (uint8 i = 0; i < items_count; ++i)
{
- Item* item = player->GetItemByGuid(itemGUIDs[i]);
- if (item)
+ if (Item* item = player->GetItemByGuid(itemGUIDs[i]))
{
ItemTemplate const* itemProto = item->GetTemplate();
if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT))
@@ -216,22 +225,21 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
}
}
- if (!accountBound && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeam() != rc_team && AccountMgr::IsPlayerAccount(GetSecurity()))
+ if (!accountBound && player->GetTeam() != receiverTeam && // Sender and reciver are from different faction
+ (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) || // Config not enabled
+ !HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_MAIL) || // Sender cant mail interact with the other faction
+ !canReceiveMailFromOtherFaction)) // Receiver cant mail interact with the other faction
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM);
return;
}
- if (receiveLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ))
+ if (receiverLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ))
{
SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ));
return;
}
- uint32 rc_account = receive
- ? receive->GetSession()->GetAccountId()
- : sObjectMgr->GetPlayerAccountIdByGUID(rc);
-
Item* items[MAX_MAIL_ITEMS];
for (uint8 i = 0; i < items_count; ++i)
@@ -257,7 +265,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
- if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != rc_account)
+ if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId)
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT);
return;
@@ -297,35 +305,38 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
if (items_count > 0 || money > 0)
{
+ bool log = sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE) && HasPermission(RBAC_PERM_LOG_GM_TRADE);
if (items_count > 0)
{
for (uint8 i = 0; i < items_count; ++i)
{
Item* item = items[i];
- if (!AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (log)
{
- sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)",
- GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account);
+ sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) "
+ "to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(),
+ item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(),
+ receiverName.c_str(), receiverAccountId);
}
item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable
player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true);
item->DeleteFromInventoryDB(trans); // deletes item from character's inventory
- item->SetOwnerGUID(rc);
+ item->SetOwnerGUID(receiverGuid);
item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone
draft.AddItem(item);
}
// if item send to character at another account, then apply item delivery delay
- needItemDelay = player->GetSession()->GetAccountId() != rc_account;
+ needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId;
}
- if (money > 0 && !AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (log && money > 0)
{
sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: " UI64FMTD " to player: %s (Account: %u)",
- GetPlayerName().c_str(), GetAccountId(), money, receiver.c_str(), rc_account);
+ GetPlayerName().c_str(), GetAccountId(), money, receiverName.c_str(), receiverAccountId);
}
}
@@ -336,7 +347,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
draft
.AddMoney(money)
.AddCOD(COD)
- .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
+ .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
player->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
@@ -492,17 +503,17 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail
{
uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER);
- Player* receive = ObjectAccessor::FindPlayer(sender_guid);
+ Player* receiver = ObjectAccessor::FindPlayer(sender_guid);
uint32 sender_accId = 0;
- if (!AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
std::string sender_name;
- if (receive)
+ if (receiver)
{
- sender_accId = receive->GetSession()->GetAccountId();
- sender_name = receive->GetName();
+ sender_accId = receiver->GetSession()->GetAccountId();
+ sender_name = receiver->GetName();
}
else
{
@@ -512,18 +523,18 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name))
sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN);
}
- sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: " UI64FMTD " to player: %s (Account: %u)",
+ sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: " UI64FMTD " to player: %s (Account: %u)",
GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId);
}
- else if (!receive)
+ else if (!receiver)
sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid);
// check player existence
- if (receive || sender_accId)
+ if (receiver || sender_accId)
{
MailDraft(m->subject, "")
.AddMoney(m->COD)
- .SendMailTo(trans, MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT);
+ .SendMailTo(trans, MailReceiver(receiver, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT);
}
player->ModifyMoney(-int32(m->COD));
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index a2768319150..808e86e15c7 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -241,7 +241,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
level_max = STRONG_MAX_LEVEL;
uint32 team = _player->GetTeam();
- uint32 security = GetSecurity();
+
bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST);
uint32 displaycount = 0;
@@ -254,42 +254,40 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
HashMapHolder<Player>::MapType const& m = sObjectAccessor->GetPlayers();
for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
{
- if (AccountMgr::IsPlayerAccount(security))
- {
- // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
- if (itr->second->GetTeam() != team && !allowTwoSideWhoList)
- continue;
+ Player* target = itr->second;
+ // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
+ if (target->GetTeam() != team && !allowTwoSideWhoList && !HasPermission(RBAC_PERM_TWO_SIDE_WHO_LIST))
+ continue;
- // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST
- if ((itr->second->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList)))
- continue;
- }
+ // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST
+ if (!HasPermission(RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList))
+ continue;
- //do not process players which are not in world
- if (!(itr->second->IsInWorld()))
+ // do not process players which are not in world
+ if (!target->IsInWorld())
continue;
// check if target is globally visible for player
- if (!(itr->second->IsVisibleGloballyFor(_player)))
+ if (!target->IsVisibleGloballyFor(_player))
continue;
// check if target's level is in level range
- uint8 lvl = itr->second->getLevel();
+ uint8 lvl = target->getLevel();
if (lvl < level_min || lvl > level_max)
continue;
// check if class matches classmask
- uint32 class_ = itr->second->getClass();
+ uint8 class_ = target->getClass();
if (!(classmask & (1 << class_)))
continue;
// check if race matches racemask
- uint32 race = itr->second->getRace();
+ uint32 race = target->getRace();
if (!(racemask & (1 << race)))
continue;
- uint32 pzoneid = itr->second->GetZoneId();
- uint8 gender = itr->second->getGender();
+ uint32 pzoneid = target->GetZoneId();
+ uint8 gender = target->getGender();
bool z_show = true;
for (uint32 i = 0; i < zones_count; ++i)
@@ -305,7 +303,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
if (!z_show)
continue;
- std::string pname = itr->second->GetName();
+ std::string pname = target->GetName();
std::wstring wpname;
if (!Utf8toWStr(pname, wpname))
continue;
@@ -314,7 +312,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos))
continue;
- std::string gname = sGuildMgr->GetGuildNameById(itr->second->GetGuildId());
+ std::string gname = sGuildMgr->GetGuildNameById(target->GetGuildId());
std::wstring wgname;
if (!Utf8toWStr(gname, wgname))
continue;
@@ -324,7 +322,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
continue;
std::string aname;
- if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId()))
+ if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid))
aname = areaEntry->area_name[GetSessionDbcLocale()];
bool s_show = true;
@@ -574,13 +572,14 @@ void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std
team = Player::TeamForRace(fields[1].GetUInt8());
friendAccountId = fields[2].GetUInt32();
- if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID)))
+ if (HasPermission(RBAC_PERM_ALLOW_GM_FRIEND) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND) ||
+ AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID)))
{
if (friendGuid)
{
if (friendGuid == GetPlayer()->GetGUID())
friendResult = FRIEND_SELF;
- else if (GetPlayer()->GetTeam() != team && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && AccountMgr::IsPlayerAccount(GetSecurity()))
+ else if (GetPlayer()->GetTeam() != team && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && !HasPermission(RBAC_PERM_TWO_SIDE_ADD_FRIEND))
friendResult = FRIEND_ENEMY;
else if (GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid)))
friendResult = FRIEND_ALREADY;
@@ -1310,7 +1309,7 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recvData)
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_WORLD_TELEPORT: Player = %s, Time = %u, map = %u, x = %f, y = %f, z = %f, o = %f",
GetPlayer()->GetName().c_str(), time, mapid, PositionX, PositionY, PositionZ, Orientation);
- if (AccountMgr::IsAdminAccount(GetSecurity()))
+ if (HasPermission(RBAC_PERM_OPCODE_WORLD_TELEPORT))
GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation);
else
SendNotification(LANG_YOU_NOT_HAVE_PERMISSION);
@@ -1322,7 +1321,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recvData)
std::string charname;
recvData >> charname;
- if (!AccountMgr::IsAdminAccount(GetSecurity()))
+ if (HasPermission(RBAC_PERM_OPCODE_WHOIS))
{
SendNotification(LANG_YOU_NOT_HAVE_PERMISSION);
return;
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index b25f0a301a9..49bc70dcde3 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -213,7 +213,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
{
// logging
sLog->outDebug(LOG_FILTER_NETWORKIO, "partner storing: %u", myItems[i]->GetGUIDLow());
- if (!AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
_player->GetName().c_str(), _player->GetSession()->GetAccountId(),
@@ -231,7 +231,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
{
// logging
sLog->outDebug(LOG_FILTER_NETWORKIO, "player storing: %u", hisItems[i]->GetGUIDLow());
- if (!AccountMgr::IsPlayerAccount(trader->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
trader->GetName().c_str(), trader->GetSession()->GetAccountId(),
@@ -534,16 +534,17 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
moveItems(myItems, hisItems);
// logging money
- if (sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
- if (!AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()) && my_trade->GetMoney() > 0)
+ if (my_trade->GetMoney() > 0)
{
sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: " UI64FMTD ") to player: %s (Account: %u)",
_player->GetName().c_str(), _player->GetSession()->GetAccountId(),
my_trade->GetMoney(),
trader->GetName().c_str(), trader->GetSession()->GetAccountId());
}
- if (!AccountMgr::IsPlayerAccount(trader->GetSession()->GetSecurity()) && his_trade->GetMoney() > 0)
+
+ if (his_trade->GetMoney() > 0)
{
sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: " UI64FMTD ") to player: %s (Account: %u)",
trader->GetName().c_str(), trader->GetSession()->GetAccountId(),
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index cbc17901d02..d3f7ac7bbf1 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -435,6 +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);
Creature* GetCreature(uint64 guid);
GameObject* GetGameObject(uint64 guid);
DynamicObject* GetDynamicObject(uint64 guid);
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 514a59894b0..035e658bd69 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -307,7 +307,7 @@ enum SpellAttr0
SPELL_ATTR0_CASTABLE_WHILE_SITTING = 0x08000000, // 27 castable while sitting
SPELL_ATTR0_CANT_USED_IN_COMBAT = 0x10000000, // 28 Cannot be used in combat
SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY = 0x20000000, // 29 unaffected by invulnerability (hmm possible not...)
- SPELL_ATTR0_BREAKABLE_BY_DAMAGE = 0x40000000, // 30
+ SPELL_ATTR0_HEARTBEAT_RESIST_CHECK = 0x40000000, // 30 random chance the effect will end TODO: implement core support
SPELL_ATTR0_CANT_CANCEL = 0x80000000 // 31 positive aura can't be canceled
};
@@ -499,7 +499,7 @@ enum SpellAttr6
SPELL_ATTR6_UNK3 = 0x00000008, // 3
SPELL_ATTR6_UNK4 = 0x00000010, // 4
SPELL_ATTR6_UNK5 = 0x00000020, // 5
- SPELL_ATTR6_UNK6 = 0x00000040, // 6
+ SPELL_ATTR6_PRINT_SPELLNAME = 0x00000040, // 6 when activated, spell name is shown at the center of the screen: <Spell name> (client-side attribute)
SPELL_ATTR6_UNK7 = 0x00000080, // 7
SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED = 0x00000100, // 8
SPELL_ATTR6_UNK9 = 0x00000200, // 9
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 1819b829404..dd186c498a9 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -25,6 +25,7 @@
#include "Config.h"
#include "Common.h"
#include "DatabaseEnv.h"
+#include "AccountMgr.h"
#include "Log.h"
#include "Opcodes.h"
#include "WorldPacket.h"
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 96b766fdf74..24917b368fc 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -24,7 +24,6 @@
#define __WORLDSESSION_H
#include "Common.h"
-#include "AccountMgr.h"
#include "SharedDefines.h"
#include "AddonMgr.h"
#include "DatabaseEnv.h"
@@ -41,6 +40,7 @@ class LoginQueryHolder;
class Object;
class Player;
class Quest;
+class RBACData;
class SpellCastTargets;
class Unit;
class Warden;
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 7c263a62b19..f6b43c79199 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -1046,7 +1046,7 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
{
ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
- if (m_Session && AccountMgr::IsPlayerAccount(m_Session->GetSecurity()))
+ if (m_Session && !m_Session->HasPermission(RBAC_PERM_SKIP_CHECK_OVERSPEED_PING))
{
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSocket::HandlePing: %s kicked for over-speed pings (address: %s)",
m_Session->GetPlayerInfo().c_str(), GetRemoteAddress().c_str());
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 4c465df7c35..57b316a3141 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -6015,8 +6015,9 @@ SpellCastResult Spell::CheckItems()
// if not item target then required item must be equipped
else
{
- if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_caster->ToPlayer()->HasItemFitToSpellRequirements(m_spellInfo))
- return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
+ if (!(_triggeredCastFlags & TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT))
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_caster->ToPlayer()->HasItemFitToSpellRequirements(m_spellInfo))
+ return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
}
// check spell focus object
@@ -6340,7 +6341,7 @@ SpellCastResult Spell::CheckItems()
}
// check weapon presence in slots for main/offhand weapons
- if (m_spellInfo->EquippedItemClass >=0)
+ if (!(_triggeredCastFlags & TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT) && m_spellInfo->EquippedItemClass >=0)
{
// main hand weapon required
if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_MAIN_HAND)
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 86d8f55c0ae..fc2da0d199c 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2593,7 +2593,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
if (!item_owner)
return;
- if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (item_owner != p_caster && p_caster->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
@@ -2658,7 +2658,7 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex)
if (!item_owner)
return;
- if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (item_owner != p_caster && p_caster->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
@@ -2740,7 +2740,7 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex)
if (!item_owner)
return;
- if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
+ if (item_owner != p_caster && p_caster->GetSession()->HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
{
sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 1a7f4b8c2a9..93c336c811c 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1257,7 +1257,7 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowOverwrite", true);
m_bool_configs[CONFIG_UI_QUESTLEVELS_IN_DIALOGS] = ConfigMgr::GetBoolDefault("UI.ShowQuestLevelsInDialogs", false);
- // call ScriptMgr if we're reloading the configuration
+ // Wintergrasp battlefield
m_bool_configs[CONFIG_WINTERGRASP_ENABLE] = ConfigMgr::GetBoolDefault("Wintergrasp.Enable", false);
m_int_configs[CONFIG_WINTERGRASP_PLR_MAX] = ConfigMgr::GetIntDefault("Wintergrasp.PlayerMax", 100);
m_int_configs[CONFIG_WINTERGRASP_PLR_MIN] = ConfigMgr::GetIntDefault("Wintergrasp.PlayerMin", 0);
@@ -1266,6 +1266,7 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_WINTERGRASP_NOBATTLETIME] = ConfigMgr::GetIntDefault("Wintergrasp.NoBattleTimer", 150);
m_int_configs[CONFIG_WINTERGRASP_RESTART_AFTER_CRASH] = ConfigMgr::GetIntDefault("Wintergrasp.CrashRestartTimer", 10);
+ // call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
}
@@ -1472,6 +1473,9 @@ void World::SetInitialWorldSettings()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature Data...");
sObjectMgr->LoadCreatures();
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Temporary Summon Data...");
+ sObjectMgr->LoadTempSummons(); // must be after LoadCreatureTemplates() and LoadGameObjectTemplates()
+
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading pet levelup spells...");
sSpellMgr->LoadPetLevelupSpellMap();
@@ -2181,18 +2185,21 @@ void World::SendGlobalMessage(WorldPacket* packet, WorldSession* self, uint32 te
/// Send a packet to all GMs (except self if mentioned)
void World::SendGlobalGMMessage(WorldPacket* packet, WorldSession* self, uint32 team)
{
- SessionMap::iterator itr;
- for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
{
- if (itr->second &&
- itr->second->GetPlayer() &&
- itr->second->GetPlayer()->IsInWorld() &&
- itr->second != self &&
- !AccountMgr::IsPlayerAccount(itr->second->GetSecurity()) &&
- (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
- {
- itr->second->SendPacket(packet);
- }
+ // check if session and can receive global GM Messages and its not self
+ WorldSession* session = itr->second;
+ if (!session || session == self || !session->HasPermission(RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE))
+ continue;
+
+ // Player should be in world
+ Player* player = session->GetPlayer();
+ if (!player || !player->IsInWorld())
+ continue;
+
+ // Send only to same team, if team is given
+ if (!team || player->GetTeam() == team)
+ session->SendPacket(packet);
}
}
@@ -2280,15 +2287,19 @@ void World::SendGMText(int32 string_id, ...)
Trinity::WorldWorldTextBuilder wt_builder(string_id, &ap);
Trinity::LocalizedPacketListDo<Trinity::WorldWorldTextBuilder> wt_do(wt_builder);
- for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
{
- if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld())
+ // Session should have permissions to receive global gm messages
+ WorldSession* session = itr->second;
+ if (!session || !session->HasPermission(RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE))
continue;
- if (AccountMgr::IsPlayerAccount(itr->second->GetSecurity()))
+ // Player should be in world
+ Player* player = session->GetPlayer();
+ if (!player || !player->IsInWorld())
continue;
- wt_do(itr->second->GetPlayer());
+ wt_do(player);
}
va_end(ap);
diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp
index c2939666452..a99957a07c0 100644
--- a/src/server/scripts/Commands/cs_gm.cpp
+++ b/src/server/scripts/Commands/cs_gm.cpp
@@ -59,30 +59,32 @@ public:
// Enables or disables hiding of the staff badge
static bool HandleGMChatCommand(ChatHandler* handler, char const* args)
{
- if (!*args)
+ if (WorldSession* session = handler->GetSession())
{
- WorldSession* session = handler->GetSession();
- if (!AccountMgr::IsPlayerAccount(session->GetSecurity()) && session->GetPlayer()->isGMChat())
- session->SendNotification(LANG_GM_CHAT_ON);
- else
- session->SendNotification(LANG_GM_CHAT_OFF);
- return true;
- }
+ if (!*args)
+ {
+ if (session->HasPermission(RBAC_PERM_CHAT_USE_STAFF_BADGE) && session->GetPlayer()->isGMChat())
+ session->SendNotification(LANG_GM_CHAT_ON);
+ else
+ session->SendNotification(LANG_GM_CHAT_OFF);
+ return true;
+ }
- std::string param = (char*)args;
+ std::string param = (char*)args;
- if (param == "on")
- {
- handler->GetSession()->GetPlayer()->SetGMChat(true);
- handler->GetSession()->SendNotification(LANG_GM_CHAT_ON);
- return true;
- }
+ if (param == "on")
+ {
+ session->GetPlayer()->SetGMChat(true);
+ session->SendNotification(LANG_GM_CHAT_ON);
+ return true;
+ }
- if (param == "off")
- {
- handler->GetSession()->GetPlayer()->SetGMChat(false);
- handler->GetSession()->SendNotification(LANG_GM_CHAT_OFF);
- return true;
+ if (param == "off")
+ {
+ session->GetPlayer()->SetGMChat(false);
+ session->SendNotification(LANG_GM_CHAT_OFF);
+ return true;
+ }
}
handler->SendSysMessage(LANG_USE_BOL);
@@ -123,7 +125,9 @@ public:
for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
{
AccountTypes itrSec = itr->second->GetSession()->GetSecurity();
- if ((itr->second->isGameMaster() || (!AccountMgr::IsPlayerAccount(itrSec) && itrSec <= AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_GM_LIST)))) &&
+ if ((itr->second->isGameMaster() ||
+ (itr->second->GetSession()->HasPermission(RBAC_PERM_COMMANDS_APPEAR_IN_GM_LIST) &&
+ itrSec <= AccountTypes(sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_GM_LIST)))) &&
(!handler->GetSession() || itr->second->IsVisibleGloballyFor(handler->GetSession()->GetPlayer())))
{
if (first)
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 3acfe9c14ba..e695a171255 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -677,7 +677,7 @@ public:
if (target)
{
- target->ResurrectPlayer(!AccountMgr::IsPlayerAccount(target->GetSession()->GetSecurity()) ? 1.0f : 0.5f);
+ target->ResurrectPlayer(target->GetSession()->HasPermission(RBAC_PERM_RESURRECT_WITH_FULL_HPS) ? 1.0f : 0.5f);
target->SpawnCorpseBones();
target->SaveToDB();
}
@@ -880,7 +880,7 @@ public:
Player* player = handler->GetSession()->GetPlayer();
// save GM account without delay and output message
- if (!AccountMgr::IsPlayerAccount(handler->GetSession()->GetSecurity()))
+ if (handler->GetSession()->HasPermission(RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY))
{
if (Player* target = handler->getSelectedPlayer())
target->SaveToDB();
@@ -937,8 +937,8 @@ public:
static bool HandleUnstuckCommand(ChatHandler* handler, char const* args)
{
- //No args required for players
- if (handler->GetSession() && AccountMgr::IsPlayerAccount(handler->GetSession()->GetSecurity()))
+ // No args required for players
+ if (handler->GetSession() && !handler->GetSession()->HasPermission(RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS))
{
// 7355: "Stuck"
if (Player* player = handler->GetSession()->GetPlayer())
diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp
index 092aabb0045..604218c2e68 100644
--- a/src/server/scripts/Commands/cs_rbac.cpp
+++ b/src/server/scripts/Commands/cs_rbac.cpp
@@ -22,7 +22,7 @@ Comment: All role based access control related commands (including account relat
Category: commandscripts
EndScriptData */
-#include "RBAC.h"
+#include "AccountMgr.h"
#include "Config.h"
#include "Chat.h"
#include "Language.h"
@@ -188,7 +188,7 @@ public:
if (!rdata)
{
- data->rbac = new RBACData(accountId, accountName, ConfigMgr::GetIntDefault("RealmID", 0));
+ data->rbac = new RBACData(accountId, accountName, realmID);
data->rbac->LoadFromDB();
data->needDelete = true;
}
diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp
index aee01f47581..958eb1709d5 100644
--- a/src/server/scripts/Commands/cs_ticket.cpp
+++ b/src/server/scripts/Commands/cs_ticket.cpp
@@ -95,18 +95,16 @@ public:
return true;
}
- // Get target information
- uint64 targetGuid = sObjectMgr->GetPlayerGUIDByName(target.c_str());
- uint64 targetAccountId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid);
- uint32 targetGmLevel = AccountMgr::GetSecurity(targetAccountId, realmID);
-
+ uint32 accountId = AccountMgr::GetId(target);
// Target must exist and have administrative rights
- if (!targetGuid || AccountMgr::IsPlayerAccount(targetGmLevel))
+ if (!AccountMgr::HasPermission(accountId, RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realmID))
{
handler->SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A);
return true;
}
+ uint64 targetGuid = sObjectMgr->GetPlayerGUIDByName(target);
+
// If already assigned, leave
if (ticket->IsAssignedTo(targetGuid))
{
@@ -125,7 +123,7 @@ public:
// Assign ticket
SQLTransaction trans = SQLTransaction(NULL);
- ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(targetGmLevel));
+ ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realmID)));
ticket->SaveToDB(trans);
sTicketMgr->UpdateLastChange();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index 593d9586156..db4ab2f32d2 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -954,7 +954,7 @@ class instance_icecrown_citadel : public InstanceMapScript
bool CheckRequiredBosses(uint32 bossId, Player const* player = NULL) const
{
- if (player && AccountMgr::IsGMAccount(player->GetSession()->GetSecurity()))
+ if (player && player->GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES))
return true;
switch (bossId)
diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp
index c031c4a3b4d..83fac35b1b6 100644
--- a/src/server/scripts/World/areatrigger_scripts.cpp
+++ b/src/server/scripts/World/areatrigger_scripts.cpp
@@ -425,6 +425,69 @@ class AreaTrigger_at_area_52_entrance : public AreaTriggerScript
std::map<uint32, time_t> _triggerTimes;
};
+/*######
+ ## at_frostgrips_hollow
+ ######*/
+
+enum FrostgripsHollow
+{
+ QUEST_THE_LONESOME_WATCHER = 12877,
+
+ NPC_STORMFORGED_MONITOR = 29862,
+ NPC_STORMFORGED_ERADICTOR = 29861,
+
+ TYPE_WAYPOINT = 0,
+ DATA_START = 0
+};
+
+Position const stormforgedMonitorPosition = {6963.95f, 45.65f, 818.71f, 4.948f};
+Position const stormforgedEradictorPosition = {6983.18f, 7.15f, 806.33f, 2.228f};
+
+class AreaTrigger_at_frostgrips_hollow : public AreaTriggerScript
+{
+public:
+ AreaTrigger_at_frostgrips_hollow() : AreaTriggerScript("at_frostgrips_hollow")
+ {
+ stormforgedMonitorGUID = 0;
+ stormforgedEradictorGUID = 0;
+ }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /* trigger */)
+ {
+ if (player->GetQuestStatus(QUEST_THE_LONESOME_WATCHER) != QUEST_STATUS_INCOMPLETE)
+ return false;
+
+ 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();
+ stormforgedMonitor->SetWalk(false);
+ /// The npc would search an alternative way to get to the last waypoint without this unit state.
+ stormforgedMonitor->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
+ stormforgedMonitor->GetMotionMaster()->MovePath(NPC_STORMFORGED_MONITOR * 100, false);
+ }
+
+ if ((stormforgedEradictor = player->SummonCreature(NPC_STORMFORGED_ERADICTOR, stormforgedEradictorPosition, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000)))
+ {
+ stormforgedEradictorGUID = stormforgedEradictor->GetGUID();
+ stormforgedEradictor->GetMotionMaster()->MovePath(NPC_STORMFORGED_ERADICTOR * 100, false);
+ }
+
+ return true;
+ }
+
+private:
+ uint64 stormforgedMonitorGUID;
+ uint64 stormforgedEradictorGUID;
+};
+
void AddSC_areatrigger_scripts()
{
new AreaTrigger_at_coilfang_waterfall();
@@ -436,4 +499,5 @@ void AddSC_areatrigger_scripts()
new AreaTrigger_at_nats_landing();
new AreaTrigger_at_brewfest();
new AreaTrigger_at_area_52_entrance();
+ new AreaTrigger_at_frostgrips_hollow();
}
diff --git a/src/server/worldserver/TCSoap/TCSoap.cpp b/src/server/worldserver/TCSoap/TCSoap.cpp
index 7d460da4f83..dd82c6ce0c7 100644
--- a/src/server/worldserver/TCSoap/TCSoap.cpp
+++ b/src/server/worldserver/TCSoap/TCSoap.cpp
@@ -18,6 +18,9 @@
#include "TCSoap.h"
#include "soapH.h"
#include "soapStub.h"
+#include "World.h"
+#include "AccountMgr.h"
+#include "Log.h"
void TCSoapRunnable::run()
{
diff --git a/src/server/worldserver/TCSoap/TCSoap.h b/src/server/worldserver/TCSoap/TCSoap.h
index ccdc7b1f89f..b786ee94e81 100644
--- a/src/server/worldserver/TCSoap/TCSoap.h
+++ b/src/server/worldserver/TCSoap/TCSoap.h
@@ -18,17 +18,11 @@
#ifndef _TCSOAP_H
#define _TCSOAP_H
-#include "Common.h"
-#include "World.h"
-#include "AccountMgr.h"
-#include "Log.h"
-
-#include "soapH.h"
-#include "soapStub.h"
-#include "stdsoap2.h"
+#include "Define.h"
#include <ace/Semaphore.h>
#include <ace/Task.h>
+#include <Threading.h>
class TCSoapRunnable: public ACE_Based::Runnable
{