[9917] Fixes in loot roll timer work and related cleanups.

* Changes include (in fact as part cleanup) fix got NeedBeforeGreed locked item after expire roll timer
  suggested by somedruid@mangos.lighthouseapp.com.
* Added cancel rolling at creatuer corpse remove.
* For NeedBeforeGreed and GroupLoot sued common code for prepare item roll.
This commit is contained in:
VladimirMangos 2010-05-17 05:24:30 +04:00
parent 0b7f090a37
commit 96d50bf55a
6 changed files with 112 additions and 127 deletions

View file

@ -34,6 +34,8 @@
#include "Util.h"
#include "LootMgr.h"
#define LOOT_ROLL_TIMEOUT (1*MINUTE*IN_MILLISECONDS)
Group::Group() : m_Id(0), m_leaderGuid(0), m_mainTank(0), m_mainAssistant(0), m_groupType(GROUPTYPE_NORMAL),
m_dungeonDifficulty(REGULAR_DIFFICULTY), m_raidDifficulty(REGULAR_DIFFICULTY),
m_bgGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_looterGuid(0), m_lootThreshold(ITEM_QUALITY_UNCOMMON),
@ -538,134 +540,48 @@ void Group::SendLootAllPassed(Roll const& r)
}
}
void Group::GroupLoot(ObjectGuid const& playerGUID, Loot *loot, Creature *creature)
void Group::GroupLoot(Creature *creature, Loot *loot)
{
std::vector<LootItem>::iterator i;
ItemPrototype const *item;
uint8 itemSlot = 0;
Player *player = sObjectMgr.GetPlayer(playerGUID);
Group *group = player->GetGroup();
for (i = loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot)
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
{
item = ObjectMgr::GetItemPrototype(i->itemid);
if (!item)
LootItem& lootItem = loot->items[itemSlot];
ItemPrototype const *itemProto = ObjectMgr::GetItemPrototype(lootItem.itemid);
if (!itemProto)
{
//DEBUG_LOG("Group::GroupLoot: missing item prototype for item with id: %d", i->itemid);
DEBUG_LOG("Group::GroupLoot: missing item prototype for item with id: %d", lootItem.itemid);
continue;
}
//roll for over-threshold item if it's one-player loot
if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
{
Roll* r = new Roll(creature->GetGUID(), *i);
//a vector is filled with only near party members
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *member = itr->getSource();
if(!member || !member->GetSession())
continue;
if ( i->AllowedForPlayer(member) )
{
if (member->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
{
r->playerVote[member->GetGUID()] = ROLL_NOT_EMITED_YET;
++r->totalPlayersRolling;
}
}
}
if (r->totalPlayersRolling > 0) // has looters
{
r->setLoot(loot);
r->itemSlot = itemSlot;
if (r->totalPlayersRolling == 1) // single looter
r->playerVote.begin()->second = ROLL_NEED;
else
{
group->SendLootStartRoll(60000, creature->GetMapId(), *r);
loot->items[itemSlot].is_blocked = true;
creature->m_groupLootTimer = 60000;
creature->m_groupLootId = GetId();
}
RollId.push_back(r);
}
else // no looters??
delete r;
}
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
StartLootRool(creature,loot,itemSlot,false);
else
i->is_underthreshold = 1;
lootItem.is_underthreshold = 1;
}
}
void Group::NeedBeforeGreed(ObjectGuid const& playerGUID, Loot *loot, Creature *creature)
void Group::NeedBeforeGreed(Creature *creature, Loot *loot)
{
ItemPrototype const *item;
Player *player = sObjectMgr.GetPlayer(playerGUID);
Group *group = player->GetGroup();
uint8 itemSlot = 0;
for(std::vector<LootItem>::iterator i = loot->items.begin(); i != loot->items.end(); ++i, ++itemSlot)
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
{
item = ObjectMgr::GetItemPrototype(i->itemid);
LootItem& lootItem = loot->items[itemSlot];
ItemPrototype const *itemProto = ObjectMgr::GetItemPrototype(lootItem.itemid);
if (!itemProto)
{
DEBUG_LOG("Group::NeedBeforeGreed: missing item prototype for item with id: %d", lootItem.itemid);
continue;
}
//only roll for one-player items, not for ones everyone can get
if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
{
Roll* r = new Roll(creature->GetGUID(), *i);
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *playerToRoll = itr->getSource();
if(!playerToRoll || !playerToRoll->GetSession())
continue;
if (playerToRoll->CanUseItem(item) && i->AllowedForPlayer(playerToRoll) )
{
if (playerToRoll->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
{
r->playerVote[playerToRoll->GetGUID()] = ROLL_NOT_EMITED_YET;
++r->totalPlayersRolling;
}
}
}
if (r->totalPlayersRolling > 0) // has looters
{
r->setLoot(loot);
r->itemSlot = itemSlot;
if (r->totalPlayersRolling == 1) // single looter
r->playerVote.begin()->second = ROLL_NEED;
else
{
group->SendLootStartRoll(60000, creature->GetMapId(), *r);
loot->items[itemSlot].is_blocked = true;
}
RollId.push_back(r);
}
else // no looters??
delete r;
}
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
StartLootRool(creature, loot, itemSlot, true);
else
i->is_underthreshold = 1;
lootItem.is_underthreshold = 1;
}
}
void Group::MasterLoot(ObjectGuid const& playerGUID, Loot* /*loot*/, Creature *creature)
void Group::MasterLoot(Creature *creature, Loot* /*loot*/)
{
Player *player = sObjectMgr.GetPlayer(playerGUID);
if(!player)
return;
DEBUG_LOG("Group::MasterLoot (SMSG_LOOT_MASTER_LIST, 330) player = [%s].", player->GetName());
uint32 real_count = 0;
WorldPacket data(SMSG_LOOT_MASTER_LIST, 330);
@ -763,6 +679,54 @@ bool Group::CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& rollI,
return false;
}
void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool skipIfCanNotUse)
{
if (itemSlot >= loot->items.size())
return;
LootItem const& lootItem = loot->items[itemSlot];
ItemPrototype const* item = ObjectMgr::GetItemPrototype(lootItem.itemid);
Roll* r = new Roll(lootTarget->GetGUID(), lootItem);
//a vector is filled with only near party members
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *playerToRoll = itr->getSource();
if(!playerToRoll || !playerToRoll->GetSession())
continue;
if ((!skipIfCanNotUse || playerToRoll->CanUseItem(item)) && lootItem.AllowedForPlayer(playerToRoll) )
{
if (playerToRoll->IsWithinDist(lootTarget, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
{
r->playerVote[playerToRoll->GetGUID()] = ROLL_NOT_EMITED_YET;
++r->totalPlayersRolling;
}
}
}
if (r->totalPlayersRolling > 0) // has looters
{
r->setLoot(loot);
r->itemSlot = itemSlot;
if (r->totalPlayersRolling == 1) // single looter
r->playerVote.begin()->second = ROLL_NEED;
else
{
SendLootStartRoll(LOOT_ROLL_TIMEOUT, lootTarget->GetMapId(), *r);
loot->items[itemSlot].is_blocked = true;
lootTarget->StartGroupLoot(this,LOOT_ROLL_TIMEOUT);
}
RollId.push_back(r);
}
else // no looters??
delete r;
}
// called when roll timer expires
void Group::EndRoll()
{