Skip to content

Commit

Permalink
Fix missing loot when item of opposite faction is dropped. This may h…
Browse files Browse the repository at this point in the history
…ave an unknow impact in case that i have not tested. So be aware of any loot problem after this.

Thank to @cala and @krullgor for help.

(based on cmangos/mangos-wotlk@47a148e)

Signed-off-by: Xfurry <xfurry@scriptdev2.com>
  • Loading branch information
Cyberium authored and xfurry committed Nov 15, 2015
1 parent 67651fa commit 3d51e9b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 22 deletions.
69 changes: 49 additions & 20 deletions src/game/LootMgr.cpp
Expand Up @@ -61,7 +61,7 @@ class LootTemplate::LootGroup // A set of loot def
bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry
bool HasQuestDropForPlayer(Player const* player) const;
// The same for active quests of the player
void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot
void Process(Loot& loot, Player const* lootOwner) const; // Rolls an item from the group (if any) and adds the item to the loot
float RawTotalChance() const; // Overall chance for the group (without equal chanced items)
float TotalChance() const; // Overall chance for the group

Expand All @@ -72,7 +72,7 @@ class LootTemplate::LootGroup // A set of loot def
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance

LootStoreItem const* Roll() const; // Rolls an item from the group, returns nullptr if all miss their chances
LootStoreItem const* Roll(Loot const& loot, Player const* lootOwner) const; // Rolls an item from the group, returns NULL if all miss their chances
};

// Remove all data and free all memory
Expand Down Expand Up @@ -920,10 +920,10 @@ void Loot::AddItem(uint32 itemid, uint32 count, uint32 randomSuffix, int32 rando
}

// Calls processor of corresponding LootTemplate (which handles everything including references)
bool Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal, bool noEmptyError)
bool Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* lootOwner, bool personal, bool noEmptyError)
{
// Must be provided
if (!loot_owner)
if (!lootOwner)
return false;

LootTemplate const* tab = store.GetLootFor(loot_id);
Expand All @@ -937,7 +937,7 @@ bool Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner,

m_lootItems.reserve(MAX_NR_LOOT_ITEMS);

tab->Process(*this, store, store.IsRatesAllowed()); // Processing is done there, callback via Loot::AddItem()
tab->Process(*this, lootOwner, store, store.IsRatesAllowed()); // Processing is done there, callback via Loot::AddItem()

// Must now check if current looter have right to loot all item or he will lockout that item until he look and release the loot
if (!m_currentLooterGuid.IsEmpty() && m_ownerSet.size() > 1 && m_lootMethod != FREE_FOR_ALL) // only for group that are not free for all
Expand Down Expand Up @@ -2186,25 +2186,54 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem& item)
EqualChanced.push_back(item);
}

// Rolls an item from the group, returns nullptr if all miss their chances
LootStoreItem const* LootTemplate::LootGroup::Roll() const
// Rolls an item from the group, returns NULL if all miss their chances
LootStoreItem const* LootTemplate::LootGroup::Roll(Loot const& loot, Player const* lootOwner) const
{
if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
{
float Roll = rand_chance_f();
float chance = rand_chance_f();

for (uint32 i = 0; i < ExplicitlyChanced.size(); ++i) // check each explicitly chanced entry in the template and modify its chance based on quality.
{
if (ExplicitlyChanced[i].chance >= 100.0f)
return &ExplicitlyChanced[i];
LootStoreItem const& lsi = ExplicitlyChanced[i];
if (lsi.conditionId && !sObjectMgr.IsPlayerMeetToCondition(lsi.conditionId, lootOwner, lootOwner->GetMap(), loot.GetLootTarget(), CONDITION_FROM_REFERING_LOOT))
{
sLog.outDebug("In explicit chance -> This item cannot be added! (%u)", lsi.itemid);
continue;
}

if (lsi.chance >= 100.0f)
return &lsi;

Roll -= ExplicitlyChanced[i].chance;
if (Roll < 0)
return &ExplicitlyChanced[i];
chance -= lsi.chance;
if (chance < 0)
return &lsi;
}
}

if (!EqualChanced.empty()) // If nothing selected yet - an item is taken from equal-chanced part
return &EqualChanced[irand(0, EqualChanced.size() - 1)];
{
std::vector <LootStoreItem const*> lootStoreItemVector; // we'll use new vector to make easy the randomization

// fill the new vector with correct pointer to our item list
for (LootStoreItemList::const_iterator itr = EqualChanced.begin(); itr != EqualChanced.end(); ++itr)
lootStoreItemVector.push_back(&(*itr));

// randomize the new vector
random_shuffle(lootStoreItemVector.begin(), lootStoreItemVector.end());

// as the new vector is randomized we can start from first element and stop at first one that meet the condition
for (std::vector <LootStoreItem const*>::const_iterator itr = lootStoreItemVector.begin(); itr != lootStoreItemVector.end(); ++itr)
{
LootStoreItem const* lsi = *itr;
if (lsi->conditionId && !sObjectMgr.IsPlayerMeetToCondition(lsi->conditionId, lootOwner, lootOwner->GetMap(), loot.GetLootTarget(), CONDITION_FROM_REFERING_LOOT))
{
sLog.outDebug("In equal chance -> This item cannot be added! (%u)", lsi->itemid);
continue;
}
return lsi;
}
}

return nullptr; // Empty drop from the group
}
Expand Down Expand Up @@ -2234,9 +2263,9 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const* player) const
}

// Rolls an item from the group (if any takes its chance) and adds the item to the loot
void LootTemplate::LootGroup::Process(Loot& loot) const
void LootTemplate::LootGroup::Process(Loot& loot, Player const* lootOwner) const
{
LootStoreItem const* item = Roll();
LootStoreItem const* item = Roll(loot, lootOwner);
if (item != nullptr)
loot.AddItem(*item);
}
Expand Down Expand Up @@ -2321,14 +2350,14 @@ void LootTemplate::AddEntry(LootStoreItem& item)
}

// Rolls for every item in the template and adds the rolled items the the loot
void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 groupId) const
void LootTemplate::Process(Loot& loot, Player const* lootOwner, LootStore const& store, bool rate, uint8 groupId) const
{
if (groupId) // Group reference uses own processing of the group
{
if (groupId > Groups.size())
return; // Error message already printed at loading stage

Groups[groupId - 1].Process(loot);
Groups[groupId - 1].Process(loot, lootOwner);
return;
}

Expand All @@ -2350,15 +2379,15 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8
continue;

for (uint32 loop = 0; loop < i->maxcount; ++loop) // Ref multiplicator
Referenced->Process(loot, store, rate, i->group);
Referenced->Process(loot, lootOwner, store, rate, i->group);
}
else // Plain entries (not a reference, not grouped)
loot.AddItem(*i); // Chance is already checked, just add
}

// Now processing groups
for (LootGroups::const_iterator i = Groups.begin() ; i != Groups.end() ; ++i)
i->Process(loot);
i->Process(loot, lootOwner);
}

// True if template includes at least 1 quest drop entry
Expand Down
2 changes: 1 addition & 1 deletion src/game/LootMgr.h
Expand Up @@ -239,7 +239,7 @@ class LootTemplate
// Adds an entry to the group (at loading stage)
void AddEntry(LootStoreItem& item);
// Rolls for every item in the template and adds the rolled items the the loot
void Process(Loot& loot, LootStore const& store, bool rate, uint8 GroupId = 0) const;
void Process(Loot& loot, Player const* lootOwner, LootStore const& store, bool rate, uint8 GroupId = 0) const;

// True if template includes at least 1 quest drop entry
bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const;
Expand Down
11 changes: 10 additions & 1 deletion src/game/ObjectMgr.cpp
Expand Up @@ -7973,7 +7973,16 @@ bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject co
return faction && player->GetReputationMgr().GetRank(faction) >= ReputationRank(m_value2);
}
case CONDITION_TEAM:
return uint32(player->GetTeam()) == m_value1;
switch (conditionSourceType)
{
case CONDITION_FROM_REFERING_LOOT:
if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
return true;
break;
default:
return uint32(player->GetTeam()) == m_value1;
break;
}
case CONDITION_SKILL:
return player->HasSkill(m_value1) && player->GetBaseSkillValue(m_value1) >= m_value2;
case CONDITION_QUESTREWARDED:
Expand Down

0 comments on commit 3d51e9b

Please sign in to comment.