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;
|
m_deathTimer = 0;
|
||||||
setDeathState(DEAD);
|
setDeathState(DEAD);
|
||||||
UpdateObjectVisibility();
|
UpdateObjectVisibility();
|
||||||
|
|
||||||
|
// stop loot rolling before loot clear and for close client dialogs
|
||||||
|
StopGroupLoot();
|
||||||
|
|
||||||
loot.clear();
|
loot.clear();
|
||||||
uint32 respawnDelay = m_respawnDelay;
|
uint32 respawnDelay = m_respawnDelay;
|
||||||
if (AI())
|
if (AI())
|
||||||
|
|
@ -413,19 +417,12 @@ void Creature::Update(uint32 diff)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_deathTimer -= diff;
|
m_deathTimer -= diff;
|
||||||
if (m_groupLootTimer && m_groupLootId)
|
if (m_groupLootId)
|
||||||
{
|
{
|
||||||
if(diff <= m_groupLootTimer)
|
if(diff < m_groupLootTimer)
|
||||||
{
|
|
||||||
m_groupLootTimer -= diff;
|
m_groupLootTimer -= diff;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
StopGroupLoot();
|
||||||
if (Group* group = sObjectMgr.GetGroupById(m_groupLootId))
|
|
||||||
group->EndRoll();
|
|
||||||
m_groupLootTimer = 0;
|
|
||||||
m_groupLootId = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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()
|
void Creature::RegenerateMana()
|
||||||
{
|
{
|
||||||
uint32 curValue = GetPower(POWER_MANA);
|
uint32 curValue = GetPower(POWER_MANA);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
struct SpellEntry;
|
struct SpellEntry;
|
||||||
|
|
||||||
class CreatureAI;
|
class CreatureAI;
|
||||||
|
class Group;
|
||||||
class Quest;
|
class Quest;
|
||||||
class Player;
|
class Player;
|
||||||
class WorldSession;
|
class WorldSession;
|
||||||
|
|
@ -583,8 +584,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
||||||
float GetRespawnRadius() const { return m_respawnradius; }
|
float GetRespawnRadius() const { return m_respawnradius; }
|
||||||
void SetRespawnRadius(float dist) { m_respawnradius = dist; }
|
void SetRespawnRadius(float dist) { m_respawnradius = dist; }
|
||||||
|
|
||||||
uint32 m_groupLootTimer; // (msecs)timer used for group loot
|
void StartGroupLoot(Group* group, uint32 timer);
|
||||||
uint32 m_groupLootId; // used to find group which is looting corpse
|
|
||||||
|
|
||||||
void SendZoneUnderAttackMessage(Player* attacker);
|
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);
|
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
|
||||||
void RelocationNotify();
|
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
|
// vendor items
|
||||||
VendorItemCounts m_vendorItemCounts;
|
VendorItemCounts m_vendorItemCounts;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "LootMgr.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),
|
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_dungeonDifficulty(REGULAR_DIFFICULTY), m_raidDifficulty(REGULAR_DIFFICULTY),
|
||||||
m_bgGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_looterGuid(0), m_lootThreshold(ITEM_QUALITY_UNCOMMON),
|
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;
|
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
item = ObjectMgr::GetItemPrototype(i->itemid);
|
LootItem& lootItem = loot->items[itemSlot];
|
||||||
if (!item)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//roll for over-threshold item if it's one-player loot
|
//roll for over-threshold item if it's one-player loot
|
||||||
if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
|
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
||||||
{
|
StartLootRool(creature,loot,itemSlot,false);
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
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;
|
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
|
||||||
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);
|
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
|
//only roll for one-player items, not for ones everyone can get
|
||||||
if (item->Quality >= uint32(m_lootThreshold) && !i->freeforall)
|
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
||||||
{
|
StartLootRool(creature, loot, itemSlot, true);
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
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;
|
uint32 real_count = 0;
|
||||||
|
|
||||||
WorldPacket data(SMSG_LOOT_MASTER_LIST, 330);
|
WorldPacket data(SMSG_LOOT_MASTER_LIST, 330);
|
||||||
|
|
@ -763,6 +679,54 @@ bool Group::CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& rollI,
|
||||||
return false;
|
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
|
// called when roll timer expires
|
||||||
void Group::EndRoll()
|
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 SendLootRoll(ObjectGuid const& targetGuid, uint8 rollNumber, uint8 rollType, const Roll &r);
|
||||||
void SendLootRollWon(ObjectGuid const& targetGuid, uint8 rollNumber, RollVote rollType, const Roll &r);
|
void SendLootRollWon(ObjectGuid const& targetGuid, uint8 rollNumber, RollVote rollType, const Roll &r);
|
||||||
void SendLootAllPassed(const Roll &r);
|
void SendLootAllPassed(const Roll &r);
|
||||||
void GroupLoot(ObjectGuid const& playerGUID, Loot *loot, Creature *creature);
|
void GroupLoot(Creature *creature, Loot *loot);
|
||||||
void NeedBeforeGreed(ObjectGuid const& playerGUID, Loot *loot, Creature *creature);
|
void NeedBeforeGreed(Creature *creature, Loot *loot);
|
||||||
void MasterLoot(ObjectGuid const& playerGUID, Loot *loot, Creature *creature);
|
void MasterLoot(Creature *creature, Loot *loot);
|
||||||
void CountRollVote(ObjectGuid const& playerGUID, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote choise);
|
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 EndRoll();
|
||||||
|
|
||||||
void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); }
|
void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); }
|
||||||
|
|
|
||||||
|
|
@ -7869,13 +7869,13 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
||||||
{
|
{
|
||||||
case GROUP_LOOT:
|
case GROUP_LOOT:
|
||||||
// GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with quality<threshold, round robin
|
// 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;
|
break;
|
||||||
case NEED_BEFORE_GREED:
|
case NEED_BEFORE_GREED:
|
||||||
group->NeedBeforeGreed(recipient->GetObjectGuid(), loot, creature);
|
group->NeedBeforeGreed(creature, loot);
|
||||||
break;
|
break;
|
||||||
case MASTER_LOOT:
|
case MASTER_LOOT:
|
||||||
group->MasterLoot(recipient->GetObjectGuid(), loot, creature);
|
group->MasterLoot(creature, loot);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "9916"
|
#define REVISION_NR "9917"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue