mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[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
This commit is contained in:
parent
4ef23face4
commit
238b57f93e
4 changed files with 87 additions and 41 deletions
|
|
@ -36,6 +36,44 @@
|
||||||
|
|
||||||
#define LOOT_ROLL_TIMEOUT (1*MINUTE*IN_MILLISECONDS)
|
#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),
|
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),
|
||||||
|
|
@ -451,8 +489,6 @@ void Group::Disband(bool hideDestroy)
|
||||||
|
|
||||||
void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r)
|
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));
|
WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4+1));
|
||||||
data << r.lootedTargetGUID; // creature guid what we're looting
|
data << r.lootedTargetGUID; // creature guid what we're looting
|
||||||
data << uint32(mapid); // 3.3.3 mapid
|
data << uint32(mapid); // 3.3.3 mapid
|
||||||
|
|
@ -476,8 +512,8 @@ void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// dependent from player
|
// dependent from player
|
||||||
RollVoteMask voteMask = GetVoteMaskFor(pProto, p);
|
RollVoteMask mask = r.GetVoteMaskFor(p);
|
||||||
data.put<uint8>(voteMaskPos,uint8(voteMask));
|
data.put<uint8>(voteMaskPos,uint8(mask));
|
||||||
|
|
||||||
p->GetSession()->SendPacket( &data );
|
p->GetSession()->SendPacket( &data );
|
||||||
}
|
}
|
||||||
|
|
@ -552,6 +588,8 @@ void Group::SendLootAllPassed(Roll const& r)
|
||||||
|
|
||||||
void Group::GroupLoot(Creature *creature, Loot *loot)
|
void Group::GroupLoot(Creature *creature, Loot *loot)
|
||||||
{
|
{
|
||||||
|
uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING);
|
||||||
|
|
||||||
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
|
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
|
||||||
{
|
{
|
||||||
LootItem& lootItem = loot->items[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
|
//roll for over-threshold item if it's one-player loot
|
||||||
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
||||||
StartLootRool(creature,loot,itemSlot,false);
|
StartLootRool(creature, GROUP_LOOT, loot, itemSlot, maxEnchantingSkill);
|
||||||
else
|
else
|
||||||
lootItem.is_underthreshold = 1;
|
lootItem.is_underthreshold = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -572,6 +610,8 @@ void Group::GroupLoot(Creature *creature, Loot *loot)
|
||||||
|
|
||||||
void Group::NeedBeforeGreed(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)
|
for(uint8 itemSlot = 0; itemSlot < loot->items.size(); ++itemSlot)
|
||||||
{
|
{
|
||||||
LootItem& lootItem = loot->items[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
|
//only roll for one-player items, not for ones everyone can get
|
||||||
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
|
||||||
StartLootRool(creature, loot, itemSlot, true);
|
StartLootRool(creature, NEED_BEFORE_GREED, loot, itemSlot, maxEnchantingSkill);
|
||||||
else
|
else
|
||||||
lootItem.is_underthreshold = 1;
|
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)
|
bool Group::CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote vote)
|
||||||
{
|
{
|
||||||
Rolls::iterator rollI = RollId.begin();
|
Rolls::iterator rollI = RollId.begin();
|
||||||
|
|
@ -653,8 +680,7 @@ bool Group::CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// possible cheating
|
// possible cheating
|
||||||
ItemPrototype const* pProto = ObjectMgr::GetItemPrototype((*rollI)->itemid);
|
RollVoteMask voteMask = (*rollI)->GetVoteMaskFor(player);
|
||||||
RollVoteMask voteMask = GetVoteMaskFor(pProto, player);
|
|
||||||
if ((voteMask & (1 << vote)) == 0)
|
if ((voteMask & (1 << vote)) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -718,7 +744,7 @@ bool Group::CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& rollI,
|
||||||
return false;
|
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())
|
if (itemSlot >= loot->items.size())
|
||||||
return;
|
return;
|
||||||
|
|
@ -727,7 +753,7 @@ void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool
|
||||||
|
|
||||||
ItemPrototype const* item = ObjectMgr::GetItemPrototype(lootItem.itemid);
|
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
|
//a vector is filled with only near party members
|
||||||
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
|
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())
|
if(!playerToRoll || !playerToRoll->GetSession())
|
||||||
continue;
|
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))
|
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->setLoot(loot);
|
||||||
r->itemSlot = itemSlot;
|
r->itemSlot = itemSlot;
|
||||||
|
|
||||||
if (r->totalPlayersRolling == 1) // single looter
|
if (r->totalPlayersRolling == 1) // single looter
|
||||||
r->playerVote.begin()->second = ROLL_NEED;
|
r->playerVote.begin()->second = ROLL_NEED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
r->CalculateCommonVoteMask(maxEnchantingSkill); // dependent from item and possible skill
|
||||||
|
|
||||||
SendLootStartRoll(LOOT_ROLL_TIMEOUT, lootTarget->GetMapId(), *r);
|
SendLootStartRoll(LOOT_ROLL_TIMEOUT, lootTarget->GetMapId(), *r);
|
||||||
loot->items[itemSlot].is_blocked = true;
|
loot->items[itemSlot].is_blocked = true;
|
||||||
lootTarget->StartGroupLoot(this,LOOT_ROLL_TIMEOUT);
|
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 )
|
void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
|
||||||
{
|
{
|
||||||
switch (GetLootMethod())
|
switch (GetLootMethod())
|
||||||
|
|
@ -1565,16 +1611,6 @@ GroupJoinBattlegroundResult Group::CanJoinBattleGroundQueue(BattleGround const*
|
||||||
return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID());
|
return GroupJoinBattlegroundResult(bgOrTemplate->GetTypeID());
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================
|
|
||||||
//============== Roll ===============================
|
|
||||||
//===================================================
|
|
||||||
|
|
||||||
void Roll::targetObjectBuildLink()
|
|
||||||
{
|
|
||||||
// called from link()
|
|
||||||
getTarget()->addLootValidatorRef(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Group::SetDungeonDifficulty(Difficulty difficulty)
|
void Group::SetDungeonDifficulty(Difficulty difficulty)
|
||||||
{
|
{
|
||||||
m_dungeonDifficulty = difficulty;
|
m_dungeonDifficulty = difficulty;
|
||||||
|
|
|
||||||
|
|
@ -137,14 +137,18 @@ static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT] = { 0, 2, 2, 2, 1
|
||||||
class Roll : public LootValidatorRef
|
class Roll : public LootValidatorRef
|
||||||
{
|
{
|
||||||
public:
|
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),
|
: 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() { }
|
~Roll() { }
|
||||||
void setLoot(Loot *pLoot) { link(pLoot, this); }
|
void setLoot(Loot *pLoot) { link(pLoot, this); }
|
||||||
Loot *getLoot() { return getTarget(); }
|
Loot *getLoot() { return getTarget(); }
|
||||||
void targetObjectBuildLink();
|
void targetObjectBuildLink();
|
||||||
|
|
||||||
|
void CalculateCommonVoteMask(uint32 max_enchanting_skill);
|
||||||
|
RollVoteMask GetVoteMaskFor(Player* player) const;
|
||||||
|
|
||||||
ObjectGuid lootedTargetGUID;
|
ObjectGuid lootedTargetGUID;
|
||||||
uint32 itemid;
|
uint32 itemid;
|
||||||
int32 itemRandomPropId;
|
int32 itemRandomPropId;
|
||||||
|
|
@ -157,6 +161,10 @@ class Roll : public LootValidatorRef
|
||||||
uint8 totalGreed;
|
uint8 totalGreed;
|
||||||
uint8 totalPass;
|
uint8 totalPass;
|
||||||
uint8 itemSlot;
|
uint8 itemSlot;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LootMethod m_method;
|
||||||
|
RollVoteMask m_commonVoteMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InstanceGroupBind
|
struct InstanceGroupBind
|
||||||
|
|
@ -356,7 +364,7 @@ class MANGOS_DLL_SPEC Group
|
||||||
void NeedBeforeGreed(Creature *creature, Loot *loot);
|
void NeedBeforeGreed(Creature *creature, Loot *loot);
|
||||||
void MasterLoot(Creature *creature, Loot *loot);
|
void MasterLoot(Creature *creature, Loot *loot);
|
||||||
bool CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote vote);
|
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 EndRoll();
|
||||||
|
|
||||||
void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); }
|
void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); }
|
||||||
|
|
@ -427,9 +435,10 @@ class MANGOS_DLL_SPEC Group
|
||||||
--m_subGroupsCounts[subgroup];
|
--m_subGroupsCounts[subgroup];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 GetMaxSkillValueForGroup(SkillType skill);
|
||||||
|
|
||||||
void CountTheRoll(Rolls::iterator& roll); // iterator update to next, in CountRollVote if true
|
void CountTheRoll(Rolls::iterator& roll); // iterator update to next, in CountRollVote if true
|
||||||
bool CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& roll, RollVote vote);
|
bool CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& roll, RollVote vote);
|
||||||
static RollVoteMask GetVoteMaskFor(ItemPrototype const* itemProto, Player* player);
|
|
||||||
|
|
||||||
GroupFlagMask GetFlags(MemberSlot const& slot) const
|
GroupFlagMask GetFlags(MemberSlot const& slot) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,7 @@ void WorldSession::HandleLootRoll( WorldPacket &recv_data )
|
||||||
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1);
|
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1);
|
||||||
break;
|
break;
|
||||||
case ROLL_GREED:
|
case ROLL_GREED:
|
||||||
|
case ROLL_DISENCHANT:
|
||||||
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1);
|
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1);
|
||||||
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 "10215"
|
#define REVISION_NR "10216"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue