Core/Loot: Implement round robin for under threshold items in case of master loot

Thanks @Shauren for pointing out
This commit is contained in:
Dehravor committed 2014-03-16 19:12:01 +01:00
1 parent 892d9eac79
commit 6a5c43b0d8
11 files changed
+71 -61

No files matched your search

+1
View File
@@ -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';
@@ -0,0 +1 @@
ALTER TABLE `groups` ADD COLUMN `masterLooterGuid` INT(10) UNSIGNED NOT NULL AFTER `raiddifficulty`;
+2 -2
View File
@@ -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;
+7 -3
View File
@@ -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
+33 -29
View File
@@ -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;
+3
View File
@@ -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;
+2 -2
View File
@@ -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!");
@@ -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();
+7 -21
View File
@@ -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);
group->SendLooter(creature, NULL);
// force update of dynamic flags, otherwise other group's players still not able to loot.
creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS);
}
// 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;
+13 -3
View File
@@ -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);
@@ -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);