From 96d50bf55a2fa05946bce61a226371183e2fda20 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 17 May 2010 05:24:30 +0400 Subject: [PATCH] [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. --- src/game/Creature.cpp | 36 +++++--- src/game/Creature.h | 8 +- src/game/Group.cpp | 180 ++++++++++++++++----------------------- src/game/Group.h | 7 +- src/game/Player.cpp | 6 +- src/shared/revision_nr.h | 2 +- 6 files changed, 112 insertions(+), 127 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 774f2454d..83601d13c 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -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 (m_groupLootId) { - if(diff <= m_groupLootTimer) - { + 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); diff --git a/src/game/Creature.h b/src/game/Creature.h index d8f74fbdf..cac8ff93b 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -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; diff --git a/src/game/Group.cpp b/src/game/Group.cpp index 1433a0237..97c0143d2 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -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::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::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() { diff --git a/src/game/Group.h b/src/game/Group.h index 94041dc21..63bdea8b0 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -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); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f8c56e499..eae1779e6 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -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 qualityGroupLoot(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; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6e5f88bc4..8c3bb9db9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9916" + #define REVISION_NR "9917" #endif // __REVISION_NR_H__