mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 10:37:03 +00:00
[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:
parent
0b7f090a37
commit
96d50bf55a
6 changed files with 112 additions and 127 deletions
|
|
@ -168,6 +168,10 @@ void Creature::RemoveCorpse()
|
|||
m_deathTimer = 0;
|
||||
setDeathState(DEAD);
|
||||
UpdateObjectVisibility();
|
||||
|
||||
// stop loot rolling before loot clear and for close client dialogs
|
||||
StopGroupLoot();
|
||||
|
||||
loot.clear();
|
||||
uint32 respawnDelay = m_respawnDelay;
|
||||
if (AI())
|
||||
|
|
@ -413,19 +417,12 @@ void Creature::Update(uint32 diff)
|
|||
else
|
||||
{
|
||||
m_deathTimer -= diff;
|
||||
if (m_groupLootTimer && m_groupLootId)
|
||||
{
|
||||
if(diff <= m_groupLootTimer)
|
||||
if (m_groupLootId)
|
||||
{
|
||||
if(diff < m_groupLootTimer)
|
||||
m_groupLootTimer -= diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Group* group = sObjectMgr.GetGroupById(m_groupLootId))
|
||||
group->EndRoll();
|
||||
m_groupLootTimer = 0;
|
||||
m_groupLootId = 0;
|
||||
}
|
||||
StopGroupLoot();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -504,6 +501,25 @@ void Creature::Update(uint32 diff)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Creature::StartGroupLoot( Group* group, uint32 timer )
|
||||
{
|
||||
m_groupLootId = group->GetId();
|
||||
m_groupLootTimer = timer;
|
||||
}
|
||||
|
||||
void Creature::StopGroupLoot()
|
||||
{
|
||||
if (!m_groupLootId)
|
||||
return;
|
||||
|
||||
if (Group* group = sObjectMgr.GetGroupById(m_groupLootId))
|
||||
group->EndRoll();
|
||||
|
||||
m_groupLootTimer = 0;
|
||||
m_groupLootId = 0;
|
||||
}
|
||||
|
||||
void Creature::RegenerateMana()
|
||||
{
|
||||
uint32 curValue = GetPower(POWER_MANA);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
struct SpellEntry;
|
||||
|
||||
class CreatureAI;
|
||||
class Group;
|
||||
class Quest;
|
||||
class Player;
|
||||
class WorldSession;
|
||||
|
|
@ -583,8 +584,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
float GetRespawnRadius() const { return m_respawnradius; }
|
||||
void SetRespawnRadius(float dist) { m_respawnradius = dist; }
|
||||
|
||||
uint32 m_groupLootTimer; // (msecs)timer used for group loot
|
||||
uint32 m_groupLootId; // used to find group which is looting corpse
|
||||
void StartGroupLoot(Group* group, uint32 timer);
|
||||
|
||||
void SendZoneUnderAttackMessage(Player* attacker);
|
||||
|
||||
|
|
@ -628,6 +628,10 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
|
||||
void RelocationNotify();
|
||||
|
||||
uint32 m_groupLootTimer; // (msecs)timer used for group loot
|
||||
uint32 m_groupLootId; // used to find group which is looting corpse
|
||||
void StopGroupLoot();
|
||||
|
||||
// vendor items
|
||||
VendorItemCounts m_vendorItemCounts;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
||||
StartLootRool(creature,loot,itemSlot,false);
|
||||
else
|
||||
lootItem.is_underthreshold = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//a vector is filled with only near party members
|
||||
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
void Group::NeedBeforeGreed(Creature *creature, Loot *loot)
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
if(!member || !member->GetSession())
|
||||
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
else
|
||||
i->is_underthreshold = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Group::NeedBeforeGreed(ObjectGuid const& playerGUID, Loot *loot, Creature *creature)
|
||||
{
|
||||
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)
|
||||
{
|
||||
item = ObjectMgr::GetItemPrototype(i->itemid);
|
||||
|
||||
//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;
|
||||
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
||||
StartLootRool(creature, loot, itemSlot, true);
|
||||
else
|
||||
lootItem.is_underthreshold = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Group::MasterLoot(Creature *creature, Loot* /*loot*/)
|
||||
{
|
||||
group->SendLootStartRoll(60000, creature->GetMapId(), *r);
|
||||
loot->items[itemSlot].is_blocked = true;
|
||||
}
|
||||
|
||||
RollId.push_back(r);
|
||||
}
|
||||
else // no looters??
|
||||
delete r;
|
||||
}
|
||||
else
|
||||
i->is_underthreshold = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Group::MasterLoot(ObjectGuid const& playerGUID, Loot* /*loot*/, Creature *creature)
|
||||
{
|
||||
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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -331,10 +331,11 @@ class MANGOS_DLL_SPEC Group
|
|||
void SendLootRoll(ObjectGuid const& targetGuid, uint8 rollNumber, uint8 rollType, const Roll &r);
|
||||
void SendLootRollWon(ObjectGuid const& targetGuid, uint8 rollNumber, RollVote rollType, const Roll &r);
|
||||
void SendLootAllPassed(const Roll &r);
|
||||
void GroupLoot(ObjectGuid const& playerGUID, Loot *loot, Creature *creature);
|
||||
void NeedBeforeGreed(ObjectGuid const& playerGUID, Loot *loot, Creature *creature);
|
||||
void MasterLoot(ObjectGuid const& playerGUID, Loot *loot, Creature *creature);
|
||||
void GroupLoot(Creature *creature, Loot *loot);
|
||||
void NeedBeforeGreed(Creature *creature, Loot *loot);
|
||||
void MasterLoot(Creature *creature, Loot *loot);
|
||||
void CountRollVote(ObjectGuid const& playerGUID, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote choise);
|
||||
void StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool skipIfCanNotUse);
|
||||
void EndRoll();
|
||||
|
||||
void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); }
|
||||
|
|
|
|||
|
|
@ -7869,13 +7869,13 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
{
|
||||
case GROUP_LOOT:
|
||||
// GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with quality<threshold, round robin
|
||||
group->GroupLoot(recipient->GetObjectGuid(), loot, creature);
|
||||
group->GroupLoot(creature, loot);
|
||||
break;
|
||||
case NEED_BEFORE_GREED:
|
||||
group->NeedBeforeGreed(recipient->GetObjectGuid(), loot, creature);
|
||||
group->NeedBeforeGreed(creature, loot);
|
||||
break;
|
||||
case MASTER_LOOT:
|
||||
group->MasterLoot(recipient->GetObjectGuid(), loot, creature);
|
||||
group->MasterLoot(creature, loot);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "9916"
|
||||
#define REVISION_NR "9917"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue