Core/Loot: Implement round robin for under threshold items in case of master loot
Thanks @Shauren for pointing out
This commit is contained in:
1 parent
892d9eac79
commit
6a5c43b0d8
11 files changed
+71
-61
No files matched your search
@@ -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`;
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user