diff options
Diffstat (limited to 'src')
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 { |