From 238b57f93e87cad335db40578732035839e25193 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 18 Jul 2010 03:15:00 +0400 Subject: [PATCH] [10216] Re-implement ROLL_VOTE_DISENCHANT disable case Also implement NEED_BEFORE_GREED disabling ROLL_VOTE_MASK_NEED instead skip item as expected in recent client changes. Thanks to TOM_RUS for help in understanding proper way work. Hmm, maybe i still do wrong something... ^^ Also count disenchnt roll as greed in ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED --- src/game/Group.cpp | 108 +++++++++++++++++++++++++------------- src/game/Group.h | 17 ++++-- src/game/GroupHandler.cpp | 1 + src/shared/revision_nr.h | 2 +- 4 files changed, 87 insertions(+), 41 deletions(-) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index b38cf9f64..856a084e7 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -36,6 +36,44 @@ #define LOOT_ROLL_TIMEOUT (1*MINUTE*IN_MILLISECONDS) +//=================================================== +//============== Roll =============================== +//=================================================== + +void Roll::targetObjectBuildLink() +{ + // called from link() + getTarget()->addLootValidatorRef(this); +} + +void Roll::CalculateCommonVoteMask(uint32 max_enchanting_skill) +{ + m_commonVoteMask = ROLL_VOTE_MASK_ALL; + + ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(itemid); + + if (itemProto->Flags2 & ITEM_FLAGS2_NEED_ROLL_DISABLED) + m_commonVoteMask = RollVoteMask(m_commonVoteMask & ~ROLL_VOTE_MASK_NEED); + + if (!itemProto->DisenchantID || uint32(itemProto->RequiredDisenchantSkill) > max_enchanting_skill) + m_commonVoteMask = RollVoteMask(m_commonVoteMask & ~ROLL_VOTE_MASK_DISENCHANT); +} + +RollVoteMask Roll::GetVoteMaskFor(Player* player) const +{ + ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(itemid); + + // In NEED_BEFORE_GREED need disabled for non-usable item for player + if (m_method != NEED_BEFORE_GREED || player->CanUseItem(itemProto) == EQUIP_ERR_OK) + return m_commonVoteMask; + else + return RollVoteMask(m_commonVoteMask & ~ROLL_VOTE_MASK_NEED); +} + +//=================================================== +//============== Group ============================== +//=================================================== + 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), @@ -451,8 +489,6 @@ void Group::Disband(bool hideDestroy) void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r) { - ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(r.itemid); - WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4+1)); data << r.lootedTargetGUID; // creature guid what we're looting data << uint32(mapid); // 3.3.3 mapid @@ -476,8 +512,8 @@ void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r) continue; // dependent from player - RollVoteMask voteMask = GetVoteMaskFor(pProto, p); - data.put(voteMaskPos,uint8(voteMask)); + RollVoteMask mask = r.GetVoteMaskFor(p); + data.put(voteMaskPos,uint8(mask)); p->GetSession()->SendPacket( &data ); } @@ -552,6 +588,8 @@ void Group::SendLootAllPassed(Roll const& r) void Group::GroupLoot(Creature *creature, Loot *loot) { + uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING); + for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot) { LootItem& lootItem = loot->items[itemSlot]; @@ -564,7 +602,7 @@ void Group::GroupLoot(Creature *creature, Loot *loot) //roll for over-threshold item if it's one-player loot if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall) - StartLootRool(creature,loot,itemSlot,false); + StartLootRool(creature, GROUP_LOOT, loot, itemSlot, maxEnchantingSkill); else lootItem.is_underthreshold = 1; } @@ -572,6 +610,8 @@ void Group::GroupLoot(Creature *creature, Loot *loot) void Group::NeedBeforeGreed(Creature *creature, Loot *loot) { + uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING); + for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot) { LootItem& lootItem = loot->items[itemSlot]; @@ -584,7 +624,7 @@ void Group::NeedBeforeGreed(Creature *creature, Loot *loot) //only roll for one-player items, not for ones everyone can get if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall) - StartLootRool(creature, loot, itemSlot, true); + StartLootRool(creature, NEED_BEFORE_GREED, loot, itemSlot, maxEnchantingSkill); else lootItem.is_underthreshold = 1; } @@ -629,19 +669,6 @@ void Group::MasterLoot(Creature *creature, Loot* loot) } } -RollVoteMask Group::GetVoteMaskFor( ItemPrototype const* itemProto, Player* player ) -{ - RollVoteMask mask = ROLL_VOTE_MASK_ALL; - - if (itemProto->Flags2 & ITEM_FLAGS2_NEED_ROLL_DISABLED) - mask = RollVoteMask(mask & ~ROLL_VOTE_MASK_NEED); - - if (!itemProto->DisenchantID || uint32(itemProto->RequiredDisenchantSkill) > player->GetSkillValue(SKILL_ENCHANTING)) - mask = RollVoteMask(mask & ~ROLL_VOTE_MASK_DISENCHANT); - - return mask; -} - bool Group::CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote vote) { Rolls::iterator rollI = RollId.begin(); @@ -653,8 +680,7 @@ bool Group::CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 return false; // possible cheating - ItemPrototype const* pProto = ObjectMgr::GetItemPrototype((*rollI)->itemid); - RollVoteMask voteMask = GetVoteMaskFor(pProto, player); + RollVoteMask voteMask = (*rollI)->GetVoteMaskFor(player); if ((voteMask & (1 << vote)) == 0) return false; @@ -718,7 +744,7 @@ bool Group::CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& rollI, return false; } -void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool skipIfCanNotUse) +void Group::StartLootRool(Creature* lootTarget, LootMethod method, Loot* loot, uint8 itemSlot, uint32 maxEnchantingSkill) { if (itemSlot >= loot->items.size()) return; @@ -727,7 +753,7 @@ void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool ItemPrototype const* item = ObjectMgr::GetItemPrototype(lootItem.itemid); - Roll* r = new Roll(lootTarget->GetGUID(), lootItem); + Roll* r = new Roll(lootTarget->GetGUID(), method, lootItem); //a vector is filled with only near party members for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) @@ -736,7 +762,7 @@ void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool if(!playerToRoll || !playerToRoll->GetSession()) continue; - if ((!skipIfCanNotUse || playerToRoll->CanUseItem(item)==EQUIP_ERR_OK) && lootItem.AllowedForPlayer(playerToRoll) ) + if (lootItem.AllowedForPlayer(playerToRoll)) { if (playerToRoll->IsWithinDist(lootTarget, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) { @@ -746,15 +772,17 @@ void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool } } - if (r->totalPlayersRolling > 0) // has looters + if (r->totalPlayersRolling > 0) // has looters { r->setLoot(loot); r->itemSlot = itemSlot; - if (r->totalPlayersRolling == 1) // single looter + if (r->totalPlayersRolling == 1) // single looter r->playerVote.begin()->second = ROLL_NEED; else { + r->CalculateCommonVoteMask(maxEnchantingSkill); // dependent from item and possible skill + SendLootStartRoll(LOOT_ROLL_TIMEOUT, lootTarget->GetMapId(), *r); loot->items[itemSlot].is_blocked = true; lootTarget->StartGroupLoot(this,LOOT_ROLL_TIMEOUT); @@ -1433,6 +1461,24 @@ void Group::ChangeMembersGroup(Player *player, uint8 group) } } +uint32 Group::GetMaxSkillValueForGroup( SkillType skill ) +{ + uint32 maxvalue = 0; + + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if (!member) + continue; + + uint32 value = member->GetSkillValue(skill); + if (maxvalue < value) + maxvalue = value; + } + + return maxvalue; +} + void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) { switch (GetLootMethod()) @@ -1565,16 +1611,6 @@ GroupJoinBattlegroundResult Group::CanJoinBattleGroundQueue(BattleGround const* return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID()); } -//=================================================== -//============== Roll =============================== -//=================================================== - -void Roll::targetObjectBuildLink() -{ - // called from link() - getTarget()->addLootValidatorRef(this); -} - void Group::SetDungeonDifficulty(Difficulty difficulty) { m_dungeonDifficulty = difficulty; diff --git a/src/game/Group.h b/src/game/Group.h index 3f2c10ec7..85efa1ccb 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -137,14 +137,18 @@ static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 2, 2, 2, 1 class Roll : public LootValidatorRef { public: - Roll(ObjectGuid _lootedTragetGuid, LootItem const& li) + Roll(ObjectGuid _lootedTragetGuid, LootMethod method, LootItem const& li) : lootedTargetGUID(_lootedTragetGuid), itemid(li.itemid), itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix), - itemCount(li.count), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0) {} + itemCount(li.count), totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0), + m_method(method), m_commonVoteMask(ROLL_VOTE_MASK_ALL) {} ~Roll() { } void setLoot(Loot *pLoot) { link(pLoot, this); } Loot *getLoot() { return getTarget(); } void targetObjectBuildLink(); + void CalculateCommonVoteMask(uint32 max_enchanting_skill); + RollVoteMask GetVoteMaskFor(Player* player) const; + ObjectGuid lootedTargetGUID; uint32 itemid; int32 itemRandomPropId; @@ -157,6 +161,10 @@ class Roll : public LootValidatorRef uint8 totalGreed; uint8 totalPass; uint8 itemSlot; + + private: + LootMethod m_method; + RollVoteMask m_commonVoteMask; }; struct InstanceGroupBind @@ -356,7 +364,7 @@ class MANGOS_DLL_SPEC Group void NeedBeforeGreed(Creature *creature, Loot *loot); void MasterLoot(Creature *creature, Loot *loot); bool CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote vote); - void StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool skipIfCanNotUse); + void StartLootRool(Creature* lootTarget, LootMethod method, Loot* loot, uint8 itemSlot, uint32 maxEnchantingSkill); void EndRoll(); void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); } @@ -427,9 +435,10 @@ class MANGOS_DLL_SPEC Group --m_subGroupsCounts[subgroup]; } + uint32 GetMaxSkillValueForGroup(SkillType skill); + void CountTheRoll(Rolls::iterator& roll); // iterator update to next, in CountRollVote if true bool CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& roll, RollVote vote); - static RollVoteMask GetVoteMaskFor(ItemPrototype const* itemProto, Player* player); GroupFlagMask GetFlags(MemberSlot const& slot) const { diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 98476fa24..c432d4ad1 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -402,6 +402,7 @@ void WorldSession::HandleLootRoll( WorldPacket &recv_data ) GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); break; case ROLL_GREED: + case ROLL_DISENCHANT: GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); break; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5199f1666..cb6014333 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 "10215" + #define REVISION_NR "10216" #endif // __REVISION_NR_H__