diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index fc762f35c03..005503c1613 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -508,7 +508,7 @@ CREATE TABLE `rbac_default_permissions` ( LOCK TABLES `rbac_default_permissions` WRITE; /*!40000 ALTER TABLE `rbac_default_permissions` DISABLE KEYS */; -INSERT INTO `rbac_default_permissions` VALUES (0,195),(1,194),(2,193),(3,192); +INSERT INTO `rbac_default_permissions` VALUES (3,192),(2,193),(1,194),(0,195); /*!40000 ALTER TABLE `rbac_default_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -661,4 +661,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2014-10-18 23:33:11 +-- Dump completed on 2014-11-11 0:38:41 diff --git a/sql/updates/auth/2014_11_10_00_auth.sql b/sql/updates/auth/2014_11_10_00_auth.sql new file mode 100644 index 00000000000..088c5cc71b5 --- /dev/null +++ b/sql/updates/auth/2014_11_10_00_auth.sql @@ -0,0 +1,7 @@ +DELETE FROM rbac_permissions WHERE id = 797; +INSERT INTO rbac_permissions (`id`, `name`) VALUES +(797, 'Command: pvpstats'); + +DELETE FROM rbac_linked_permissions WHERE `linkedId` = 797; +INSERT INTO rbac_linked_permissions (`id`, `linkedId`) VALUES +(199, 797); diff --git a/sql/updates/auth/2014_11_10_01_auth.sql b/sql/updates/auth/2014_11_10_01_auth.sql new file mode 100644 index 00000000000..0f89140ecf4 --- /dev/null +++ b/sql/updates/auth/2014_11_10_01_auth.sql @@ -0,0 +1,9 @@ +/* add rbac permissions to new commands */ +DELETE FROM `rbac_permissions` WHERE `id`=798; +INSERT INTO `rbac_permissions` (`id`,`name`) VALUES +(798, 'Command: .mod xp'); + +DELETE FROM `rbac_linked_permissions` WHERE `id`=798; +INSERT INTO `rbac_linked_permissions` (`id`,`linkedId`) VALUES +/* add mod xp to gms */ +(194, 798); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 0505c2cbab3..374e7c7f162 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -700,6 +700,8 @@ enum RBACPermissions RBAC_PERM_COMMAND_GUILD_INFO = 794, RBAC_PERM_COMMAND_INSTANCE_SET_BOSS_STATE = 795, RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE = 796, + RBAC_PERM_COMMAND_PVPSTATS = 797, + RBAC_PERM_COMMAND_MODIFY_XP = 798, // custom permissions 1000+ RBAC_PERM_MAX diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index c44aa4e9724..674f718009f 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -33,6 +33,7 @@ #include "GroupMgr.h" #include "GameEventMgr.h" #include "WorldSession.h" +#include "InstanceSaveMgr.h" namespace lfg { @@ -481,7 +482,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const dungeons = GetDungeonsByRandom(rDungeonId); // if we have lockmap then there are no compatible dungeons - GetCompatibleDungeons(dungeons, players, joinData.lockmap); + GetCompatibleDungeons(dungeons, players, joinData.lockmap, isContinue); if (dungeons.empty()) joinData.result = grp ? LFG_JOIN_INTERNAL_ERROR : LFG_JOIN_NOT_MEET_REQS; } @@ -746,20 +747,48 @@ void LFGMgr::UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid /* = ObjectGuid:: @param[in] players Set of players to check their dungeon restrictions @param[out] lockMap Map of players Lock status info of given dungeons (Empty if dungeons is not empty) */ -void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap) +void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue) { lockMap.clear(); + + std::map lockedDungeons; + for (GuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) { ObjectGuid guid = (*it); LfgLockMap const& cachedLockMap = GetLockedDungeons(guid); + Player* player = ObjectAccessor::FindPlayer(guid); for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2) { uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId); if (itDungeon != dungeons.end()) { - dungeons.erase(itDungeon); + bool eraseDungeon = true; + + // Don't remove the dungeon if team members are trying to continue a locked instance + if (it2->second == LFG_LOCKSTATUS_RAID_LOCKED && isContinue) + { + LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId); + ASSERT(dungeon); + ASSERT(player); + if (InstancePlayerBind* playerBind = player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) + { + if (InstanceSave* playerSave = playerBind->save) + { + uint32 dungeonInstanceId = playerSave->GetInstanceId(); + auto itLockedDungeon = lockedDungeons.find(dungeonId); + if (itLockedDungeon == lockedDungeons.end() || itLockedDungeon->second == dungeonInstanceId) + eraseDungeon = false; + + lockedDungeons[dungeonId] = dungeonInstanceId; + } + } + } + + if (eraseDungeon) + dungeons.erase(itDungeon); + lockMap[guid][dungeonId] = it2->second; } } diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index f1af7886473..f754145617a 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -436,7 +436,7 @@ class LFGMgr void DecreaseKicksLeft(ObjectGuid guid); void SetState(ObjectGuid guid, LfgState state); void RemovePlayerData(ObjectGuid guid); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue); void _SaveToDB(ObjectGuid guid, uint32 db_guid); LFGDungeonData const* GetLFGDungeon(uint32 id); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 889f82c8a51..9520ab6aaea 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -20582,7 +20582,7 @@ void Player::SendAutoRepeatCancel(Unit* target) { WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, target->GetPackGUID().size()); data << target->GetPackGUID(); // may be it's target guid - GetSession()->SendPacket(&data); + SendMessageToSet(&data, false); } void Player::SendExplorationExperience(uint32 Area, uint32 Experience) diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index c199697ebbd..77fc2c97f04 100644 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -115,7 +115,9 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData) { uint32 dungeon; recvData >> dungeon; - newDungeons.insert((dungeon & 0x00FFFFFF)); // remove the type from the dungeon entry + dungeon &= 0x00FFFFFF; // remove the type from the dungeon entry + if (dungeon) + newDungeons.insert(dungeon); } TC_LOG_DEBUG("lfg", "CMSG_LFG_JOIN %s roles: %u, Dungeons: %u, Comment: %s", diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 9b2863b00b7..f824da78fa0 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -110,7 +110,9 @@ enum TrinityStrings LANG_RBAC_PERM_DENIED = 77, LANG_RBAC_PERM_REVOKED = 78, LANG_RBAC_PERM_REVOKED_NOT_IN_LIST = 79, - // Free 80 - 95 + LANG_PVPSTATS = 80, + LANG_PVPSTATS_DISABLED = 81, + // Free 82 - 95 LANG_GUILD_RENAME_ALREADY_EXISTS = 96, diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 7efa5134384..1427bb34520 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1194,8 +1194,6 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_MAX_WHO] = sConfigMgr->GetIntDefault("MaxWhoListReturns", 49); m_bool_configs[CONFIG_START_ALL_SPELLS] = sConfigMgr->GetBoolDefault("PlayerStart.AllSpells", false); - if (m_bool_configs[CONFIG_START_ALL_SPELLS]) - TC_LOG_WARN("server.loading", "PlayerStart.AllSpells enabled - may not function as intended!"); m_int_configs[CONFIG_HONOR_AFTER_DUEL] = sConfigMgr->GetIntDefault("HonorPointsAfterDuel", 0); m_bool_configs[CONFIG_START_ALL_EXPLORED] = sConfigMgr->GetBoolDefault("PlayerStart.MapsExplored", false); m_bool_configs[CONFIG_START_ALL_REP] = sConfigMgr->GetBoolDefault("PlayerStart.AllReputation", false); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 292bd78bfdb..b561e3b2abc 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -78,6 +78,7 @@ public: { "pinfo", rbac::RBAC_PERM_COMMAND_PINFO, true, &HandlePInfoCommand, "", NULL }, { "playall", rbac::RBAC_PERM_COMMAND_PLAYALL, false, &HandlePlayAllCommand, "", NULL }, { "possess", rbac::RBAC_PERM_COMMAND_POSSESS, false, &HandlePossessCommand, "", NULL }, + { "pvpstats", rbac::RBAC_PERM_COMMAND_PVPSTATS, true, &HandlePvPstatsCommand, "", NULL }, { "recall", rbac::RBAC_PERM_COMMAND_RECALL, false, &HandleRecallCommand, "", NULL }, { "repairitems", rbac::RBAC_PERM_COMMAND_REPAIRITEMS, true, &HandleRepairitemsCommand, "", NULL }, { "respawn", rbac::RBAC_PERM_COMMAND_RESPAWN, false, &HandleRespawnCommand, "", NULL }, @@ -100,6 +101,35 @@ public: return commandTable; } + static bool HandlePvPstatsCommand(ChatHandler * handler, char const* /*args*/) + { + if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE)) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PVPSTATS_FACTIONS_OVERALL); + PreparedQueryResult result = CharacterDatabase.Query(stmt); + + if (result) + { + Field* fields = result->Fetch(); + uint32 horde_victories = fields[1].GetUInt32(); + + if (!(result->NextRow())) + return false; + + fields = result->Fetch(); + uint32 alliance_victories = fields[1].GetUInt32(); + + handler->PSendSysMessage(LANG_PVPSTATS, alliance_victories, horde_victories); + } + else + return false; + } + else + handler->PSendSysMessage(LANG_PVPSTATS_DISABLED); + + return true; + } + static bool HandleDevCommand(ChatHandler* handler, char const* args) { if (!*args) diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index db091fcde5d..1e7db4f014b 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -71,6 +71,7 @@ public: { "spell", rbac::RBAC_PERM_COMMAND_MODIFY_SPELL, false, &HandleModifySpellCommand, "", NULL }, { "standstate", rbac::RBAC_PERM_COMMAND_MODIFY_STANDSTATE, false, &HandleModifyStandStateCommand, "", NULL }, { "talentpoints", rbac::RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS, false, &HandleModifyTalentCommand, "", NULL }, + { "xp", rbac::RBAC_PERM_COMMAND_MODIFY_XP, false, &HandleModifyXPCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = @@ -1402,6 +1403,37 @@ public: return true; } + + // mod xp command + static bool HandleModifyXPCommand(ChatHandler *handler, const char* args) + { + if (!*args) + return false; + + int32 xp = atoi((char*)args); + + if (xp < 1) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + Player* target = handler->getSelectedPlayerOrSelf(); + if (!target) + { + handler->SendSysMessage(LANG_NO_CHAR_SELECTED); + handler->SetSentErrorMessage(true); + return false; + } + + if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) + return false; + + // we can run the command + target->GiveXP(xp, nullptr); + return true; + } }; void AddSC_modify_commandscript() diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 5f3b22c3377..56fddea6c4d 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -638,6 +638,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_PVPSTATS_MAXID, "SELECT MAX(id) FROM pvpstats_battlegrounds", CONNECTION_SYNCH); PrepareStatement(CHAR_INS_PVPSTATS_BATTLEGROUND, "INSERT INTO pvpstats_battlegrounds (id, winner_faction, bracket_id, type, date) VALUES (?, ?, ?, ?, NOW())", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_PVPSTATS_PLAYER, "INSERT INTO pvpstats_players (battleground_id, character_guid, score_killing_blows, score_deaths, score_honorable_kills, score_bonus_honor, score_damage_done, score_healing_done, attr_1, attr_2, attr_3, attr_4, attr_5) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_PVPSTATS_FACTIONS_OVERALL, "SELECT winner_faction, COUNT(*) AS count FROM pvpstats_battlegrounds WHERE DATEDIFF(NOW(), date) < 7 GROUP BY winner_faction ORDER BY winner_faction ASC", CONNECTION_SYNCH); // QuestTracker PrepareStatement(CHAR_INS_QUEST_TRACK, "INSERT INTO quest_tracker (id, character_guid, quest_accept_time, core_hash, core_revision) VALUES (?, ?, NOW(), ?, ?)", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 49a1762ce1c..b840903d3b7 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -566,6 +566,7 @@ enum CharacterDatabaseStatements CHAR_SEL_PVPSTATS_MAXID, CHAR_INS_PVPSTATS_BATTLEGROUND, CHAR_INS_PVPSTATS_PLAYER, + CHAR_SEL_PVPSTATS_FACTIONS_OVERALL, CHAR_INS_QUEST_TRACK, CHAR_UPD_QUEST_TRACK_GM_COMPLETE, diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 79c26092605..74a526e2e59 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2448,7 +2448,7 @@ PlayerStart.AllReputation = 0 # Description: If enabled, players will start with all their class spells (not talents). # You must populate playercreateinfo_spell_custom table with the spells you # want, or this will not work! The table has data for all classes / races up -# to TBC expansion. +# to WoTLK expansion. # Default: 0 - (Disabled) # 1 - (Enabled)