aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDehravor <dehravor@gmail.com>2014-03-16 19:12:01 +0100
committerDehravor <dehravor@gmail.com>2014-03-16 19:12:01 +0100
commit6a5c43b0d819fc43a3d46aa63fa7576a11e5761c (patch)
tree7d0a26d1ff26e68906c62d3545e6c9687d99cd96
parent892d9eac79e94796e3b22e5be368063d59b20efc (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.sql1
-rw-r--r--sql/updates/characters/2014_03_16_00_characters_groups.sql1
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp4
-rw-r--r--src/server/game/Entities/Player/Player.cpp10
-rw-r--r--src/server/game/Groups/Group.cpp62
-rw-r--r--src/server/game/Groups/Group.h3
-rw-r--r--src/server/game/Groups/GroupMgr.cpp4
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp1
-rw-r--r--src/server/game/Handlers/LootHandler.cpp30
-rw-r--r--src/server/game/Loot/LootMgr.cpp16
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp2
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);