diff options
author | Dehravor <dehravor@gmail.com> | 2014-03-16 19:12:01 +0100 |
---|---|---|
committer | Dehravor <dehravor@gmail.com> | 2014-03-16 19:12:01 +0100 |
commit | 6a5c43b0d819fc43a3d46aa63fa7576a11e5761c (patch) | |
tree | 7d0a26d1ff26e68906c62d3545e6c9687d99cd96 | |
parent | 892d9eac79e94796e3b22e5be368063d59b20efc (diff) |
Core/Loot: Implement round robin for under threshold items in case of master loot
Thanks @Shauren for pointing out
-rw-r--r-- | sql/base/characters_database.sql | 1 | ||||
-rw-r--r-- | sql/updates/characters/2014_03_16_00_characters_groups.sql | 1 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGMgr.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Groups/Group.cpp | 62 | ||||
-rw-r--r-- | src/server/game/Groups/Group.h | 3 | ||||
-rw-r--r-- | src/server/game/Groups/GroupMgr.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Handlers/GroupHandler.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/LootHandler.cpp | 30 | ||||
-rw-r--r-- | src/server/game/Loot/LootMgr.cpp | 16 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 2 |
11 files changed, 72 insertions, 62 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 86d08ca954b..c7e1372e9a1 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -1632,6 +1632,7 @@ CREATE TABLE `groups` ( `groupType` tinyint(3) unsigned NOT NULL, `difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0', `raiddifficulty` tinyint(3) unsigned NOT NULL DEFAULT '0', + `masterLooterGuid` int(10) unsigned NOT NULL, PRIMARY KEY (`guid`), KEY `leaderGuid` (`leaderGuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Groups'; diff --git a/sql/updates/characters/2014_03_16_00_characters_groups.sql b/sql/updates/characters/2014_03_16_00_characters_groups.sql new file mode 100644 index 00000000000..bec5963c23c --- /dev/null +++ b/sql/updates/characters/2014_03_16_00_characters_groups.sql @@ -0,0 +1 @@ +ALTER TABLE `groups` ADD COLUMN `masterLooterGuid` INT(10) UNSIGNED NOT NULL AFTER `raiddifficulty`; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 822ae904ef1..d9df2057b54 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -60,8 +60,8 @@ void LFGMgr::_LoadFromDB(Field* fields, uint64 guid) SetLeader(guid, MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER)); - uint32 dungeon = fields[16].GetUInt32(); - uint8 state = fields[17].GetUInt8(); + uint32 dungeon = fields[17].GetUInt32(); + uint8 state = fields[18].GetUInt8(); if (!dungeon || !state) return; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e78392e917f..2f7b37a2254 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8835,7 +8835,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) switch (group->GetLootMethod()) { case MASTER_LOOT: - permission = group->GetLooterGuid() == GetGUID() ? MASTER_PERMISSION : RESTRICTED_PERMISSION; + permission = group->GetMasterLooterGuid() == GetGUID() ? MASTER_PERMISSION : RESTRICTED_PERMISSION; break; case FREE_FOR_ALL: permission = ALL_PERMISSION; @@ -9013,7 +9013,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) switch (group->GetLootMethod()) { case MASTER_LOOT: - permission = group->GetLooterGuid() == GetGUID() ? MASTER_PERMISSION : RESTRICTED_PERMISSION; + permission = group->GetMasterLooterGuid() == GetGUID() ? MASTER_PERMISSION : RESTRICTED_PERMISSION; break; case FREE_FOR_ALL: permission = ALL_PERMISSION; @@ -17794,7 +17794,6 @@ bool Player::isAllowedToLoot(const Creature* creature) switch (thisGroup->GetLootMethod()) { case FREE_FOR_ALL: - case MASTER_LOOT: return true; case ROUND_ROBIN: // may only loot if the player is the loot roundrobin player @@ -17803,6 +17802,11 @@ bool Player::isAllowedToLoot(const Creature* creature) return true; return loot->hasItemFor(this); + case MASTER_LOOT: + // may loot if the player is the master looter + if (thisGroup->GetMasterLooterGuid() == GetGUID()) + return true; + // fall-through case GROUP_LOOT: case NEED_BEFORE_GREED: // may only loot if the player is the loot roundrobin player diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index abc4b19f3f2..699a67b5340 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -56,7 +56,7 @@ Loot* Roll::getLoot() Group::Group() : m_leaderGuid(0), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL), m_dungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL), m_raidDifficulty(RAID_DIFFICULTY_10MAN_NORMAL), m_bgGroup(NULL), m_bfGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(0), -m_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0) +m_masterLooterGuid(0), m_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0) { for (uint8 i = 0; i < TARGETICONCOUNT; ++i) m_targetIcons[i] = 0; @@ -112,6 +112,7 @@ bool Group::Create(Player* leader) m_lootThreshold = ITEM_QUALITY_UNCOMMON; m_looterGuid = leaderGuid; + m_masterLooterGuid = 0; m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL; m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; @@ -146,6 +147,7 @@ bool Group::Create(Player* leader) stmt->setUInt8(index++, uint8(m_groupType)); stmt->setUInt32(index++, uint8(m_dungeonDifficulty)); stmt->setUInt32(index++, uint8(m_raidDifficulty)); + stmt->setUInt32(index++, GUID_LOPART(m_masterLooterGuid)); CharacterDatabase.Execute(stmt); @@ -162,7 +164,7 @@ bool Group::Create(Player* leader) void Group::LoadGroupFromDB(Field* fields) { - m_dbStoreId = fields[15].GetUInt32(); + m_dbStoreId = fields[16].GetUInt32(); m_guid = MAKE_NEW_GUID(sGroupMgr->GenerateGroupId(), 0, HIGHGUID_GROUP); m_leaderGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); @@ -193,6 +195,8 @@ void Group::LoadGroupFromDB(Field* fields) else m_raidDifficulty = Difficulty(r_diff); + m_masterLooterGuid = MAKE_NEW_GUID(fields[15].GetUInt32(), 0, HIGHGUID_PLAYER); + if (m_groupType & GROUPTYPE_LFG) sLFGMgr->_LoadFromDB(fields, GetGUID()); } @@ -891,24 +895,15 @@ void Group::SendLooter(Creature* creature, Player* groupLooter) WorldPacket data(SMSG_LOOT_LIST, (8+8)); data << uint64(creature->GetGUID()); - if (groupLooter) - { - if (GetLootMethod() == MASTER_LOOT) - { - data.append(groupLooter->GetPackGUID()); - data << uint8(0); - } - else - { - data << uint8(0); - data.append(groupLooter->GetPackGUID()); - } - } + if (GetLootMethod() == MASTER_LOOT) + data.appendPackGUID(GetMasterLooterGuid()); else - { data << uint8(0); + + if (groupLooter) + data.append(groupLooter->GetPackGUID()); + else data << uint8(0); - } BroadcastPacket(&data, false); } @@ -1550,7 +1545,12 @@ void Group::SendUpdateToPlayer(uint64 playerGUID, MemberSlot* slot) if (GetMembersCount() - 1) { data << uint8(m_lootMethod); // loot method - data << uint64(m_looterGuid); // looter guid + + if (m_lootMethod == MASTER_LOOT) + data << uint64(m_masterLooterGuid); // master looter guid + else + data << uint64(m_looterGuid); // looter guid + data << uint8(m_lootThreshold); // loot threshold data << uint8(m_dungeonDifficulty); // Dungeon Difficulty data << uint8(m_raidDifficulty); // Raid Difficulty @@ -1706,7 +1706,7 @@ void Group::ChangeMembersGroup(uint64 guid, uint8 group) // Retrieve the next Round-Roubin player for the group // -// No update done if loot method is Master or FFA. +// No update done if loot method is FFA. // // If the RR player is not yet set for the group, the first group member becomes the round-robin player. // If the RR player is set, the next player in group becomes the round-robin player. @@ -1717,16 +1717,10 @@ void Group::ChangeMembersGroup(uint64 guid, uint8 group) // if not, he loses his turn. void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed) { - switch (GetLootMethod()) - { - case MASTER_LOOT: - case FREE_FOR_ALL: - return; - default: - // round robin style looting applies for all low - // quality items in each loot method except free for all and master loot - break; - } + // round robin style looting applies for all low + // quality items in each loot method except free for all + if (GetLootMethod() == FREE_FOR_ALL) + return; uint64 oldLooterGUID = GetLooterGuid(); member_citerator guid_itr = _getMemberCSlot(oldLooterGUID); @@ -2150,6 +2144,11 @@ void Group::SetLooterGuid(uint64 guid) m_looterGuid = guid; } +void Group::SetMasterLooterGuid(uint64 guid) +{ + m_masterLooterGuid = guid; +} + void Group::SetLootThreshold(ItemQualities threshold) { m_lootThreshold = threshold; @@ -2225,6 +2224,11 @@ uint64 Group::GetLooterGuid() const return m_looterGuid; } +uint64 Group::GetMasterLooterGuid() const +{ + return m_masterLooterGuid; +} + ItemQualities Group::GetLootThreshold() const { return m_lootThreshold; diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 6336a1bb30c..64122b0cb4d 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -195,6 +195,7 @@ class Group void ChangeLeader(uint64 guid); void SetLootMethod(LootMethod method); void SetLooterGuid(uint64 guid); + void SetMasterLooterGuid(uint64 guid); void UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed = false); void SetLootThreshold(ItemQualities threshold); void Disband(bool hideDestroy=false); @@ -213,6 +214,7 @@ class Group const char * GetLeaderName() const; LootMethod GetLootMethod() const; uint64 GetLooterGuid() const; + uint64 GetMasterLooterGuid() const; ItemQualities GetLootThreshold() const; uint32 GetDbStoreId() const { return m_dbStoreId; }; @@ -332,6 +334,7 @@ class Group LootMethod m_lootMethod; ItemQualities m_lootThreshold; uint64 m_looterGuid; + uint64 m_masterLooterGuid; Rolls RollId; BoundInstancesMap m_boundInstances[MAX_DIFFICULTY]; uint8* m_subGroupsCounts; diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp index 20e6a0671a5..39735f5dce3 100644 --- a/src/server/game/Groups/GroupMgr.cpp +++ b/src/server/game/Groups/GroupMgr.cpp @@ -123,8 +123,8 @@ void GroupMgr::LoadGroups() // 0 1 2 3 4 5 6 7 8 9 QueryResult result = CharacterDatabase.Query("SELECT g.leaderGuid, g.lootMethod, g.looterGuid, g.lootThreshold, g.icon1, g.icon2, g.icon3, g.icon4, g.icon5, g.icon6" - // 10 11 12 13 14 15 16 17 - ", g.icon7, g.icon8, g.groupType, g.difficulty, g.raiddifficulty, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC"); + // 10 11 12 13 14 15 16 17 18 + ", g.icon7, g.icon8, g.groupType, g.difficulty, g.raiddifficulty, g.masterLooterGuid, g.guid, lfg.dungeon, lfg.state FROM groups g LEFT JOIN lfg_data lfg ON lfg.guid = g.guid ORDER BY g.guid ASC"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 group definitions. DB table `groups` is empty!"); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index fd7d0602265..7e8f662df4c 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -438,6 +438,7 @@ void WorldSession::HandleLootMethodOpcode(WorldPacket& recvData) // everything's fine, do it group->SetLootMethod((LootMethod)lootMethod); + group->SetMasterLooterGuid(lootMaster); group->SetLooterGuid(lootMaster); group->SetLootThreshold((ItemQualities)lootThreshold); group->SendUpdate(); diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index d1b60ed07fa..f92c6e08e31 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -297,17 +297,7 @@ void WorldSession::DoLootRelease(uint64 lguid) // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) - { - if (Group* group = player->GetGroup()) - { - if (group->GetLootMethod() != MASTER_LOOT) - { - loot->roundRobinPlayer = 0; - } - } - else - loot->roundRobinPlayer = 0; - } + loot->roundRobinPlayer = 0; } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG @@ -376,19 +366,15 @@ void WorldSession::DoLootRelease(uint64 lguid) // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { + loot->roundRobinPlayer = 0; + if (Group* group = player->GetGroup()) { - if (group->GetLootMethod() != MASTER_LOOT) - { - loot->roundRobinPlayer = 0; - group->SendLooter(creature, NULL); - - // force update of dynamic flags, otherwise other group's players still not able to loot. - creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); - } + group->SendLooter(creature, NULL); + + // force update of dynamic flags, otherwise other group's players still not able to loot. + creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } - else - loot->roundRobinPlayer = 0; } } } @@ -404,7 +390,7 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData) recvData >> lootguid >> slotid >> target_playerguid; - if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID() || _player->GetGroup()->GetLootMethod() != MASTER_LOOT) + if (!_player->GetGroup() || _player->GetGroup()->GetMasterLooterGuid() != _player->GetGUID() || _player->GetGroup()->GetLootMethod() != MASTER_LOOT) { _player->SendLootRelease(GetPlayer()->GetLootGUID()); return; diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 79056bcd750..cbb7036538c 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -555,7 +555,7 @@ QuestItemList* Loot::FillQuestLoot(Player* player) { LootItem &item = quest_items[i]; - if (!item.is_looted && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT )))) + if (!item.is_looted && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT)))) { ql->push_back(QuestItem(i)); @@ -589,7 +589,7 @@ QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player, bool pres for (uint8 i = 0; i < items.size(); ++i) { LootItem &item = items[i]; - if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT )))) + if (!item.is_looted && !item.freeforall && (item.AllowedForPlayer(player) || (item.follow_loot_rules && player->GetGroup() && ((player->GetGroup()->GetLootMethod() == MASTER_LOOT && player->GetGroup()->GetMasterLooterGuid() == player->GetGUID()) || player->GetGroup()->GetLootMethod() != MASTER_LOOT)))) { if (presentAtLooting) item.AddAllowedLooter(player); @@ -959,7 +959,17 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer)) { - uint8 slot_type = l.items[i].is_blocked ? LOOT_SLOT_TYPE_LOCKED : LOOT_SLOT_TYPE_ALLOW_LOOT; + uint8 slot_type; + + if (l.items[i].is_blocked) + slot_type = LOOT_SLOT_TYPE_LOCKED; + else + { + if (l.roundRobinPlayer == 0 || lv.viewer->GetGUID() == l.roundRobinPlayer) + slot_type = LOOT_SLOT_TYPE_ALLOW_LOOT; + else + continue; // item shall not be displayed + } b << uint8(i) << l.items[i]; b << uint8(slot_type); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index b6590317b8c..24e61e7399a 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -376,7 +376,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_PETITION_NAME, "UPDATE petition SET name = ? WHERE petitionguid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_PETITION_SIGNATURE, "INSERT INTO petition_sign (ownerguid, petitionguid, playerguid, player_account) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_ACCOUNT_ONLINE, "UPDATE characters SET online = 0 WHERE account = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_INS_GROUP, "INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_GROUP, "INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, masterLooterGuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_GROUP_MEMBER, "INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GROUP_MEMBER, "DELETE FROM group_member WHERE memberGuid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GROUP_INSTANCE_PERM_BINDING, "DELETE FROM group_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC); |