feat(Core/Loot): Add Rate.Drop.Item.GroupAmount to increase loot generated from loot groups (#16220)
* Adds the `Rate.Drop.Item.GroupAmount` setting to the world config. Causes top-level loot groups to drop multiple items. Does not affect references. * Don't multiply a group if a quest item gets selected. Avoids strange situations like Arcanist Doan having three hearts. * Resolve syntax error. * Fix whitespace * Fix code style issue
This commit is contained in:
@@ -2267,7 +2267,20 @@ Rate.Drop.Item.Artifact = 1
|
|||||||
Rate.Drop.Item.Referenced = 1
|
Rate.Drop.Item.Referenced = 1
|
||||||
Rate.Drop.Money = 1
|
Rate.Drop.Money = 1
|
||||||
|
|
||||||
# RewardBonusMoney
|
# Rate.Drop.Item.ReferencedAmount
|
||||||
|
# Description: Multiplier for referenced loot amount. Makes many raid bosses (and others) drop additional loot.
|
||||||
|
# Default: 1
|
||||||
|
|
||||||
|
Rate.Drop.Item.ReferencedAmount = 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rate.Drop.Item.GroupAmount
|
||||||
|
# Description: Multiplier for grouped items. Makes many dungeon bosses (and others) drop additional loot.
|
||||||
|
# Default: 1
|
||||||
|
|
||||||
|
Rate.Drop.Item.GroupAmount = 1
|
||||||
|
|
||||||
|
# Rate.RewardBonusMoney
|
||||||
# Description: Allows to further tweak the amount of extra money rewarded by quests when the player
|
# Description: Allows to further tweak the amount of extra money rewarded by quests when the player
|
||||||
# is at MaxPlayerLevel (this amount is specified in quest_template.RewardBonusMoney).
|
# is at MaxPlayerLevel (this amount is specified in quest_template.RewardBonusMoney).
|
||||||
# NOTE: the final amount will also affected by Rate.Drop.Money
|
# NOTE: the final amount will also affected by Rate.Drop.Money
|
||||||
@@ -2331,13 +2344,6 @@ Rate.BuyValue.Item.Legendary = 1
|
|||||||
Rate.BuyValue.Item.Artifact = 1
|
Rate.BuyValue.Item.Artifact = 1
|
||||||
Rate.BuyValue.Item.Heirloom = 1
|
Rate.BuyValue.Item.Heirloom = 1
|
||||||
|
|
||||||
#
|
|
||||||
# Rate.Drop.Item.ReferencedAmount
|
|
||||||
# Description: Multiplier for referenced loot amount.
|
|
||||||
# Default: 1
|
|
||||||
|
|
||||||
Rate.Drop.Item.ReferencedAmount = 1
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Rate.XP.Kill
|
# Rate.XP.Kill
|
||||||
# Rate.XP.Quest
|
# Rate.XP.Quest
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public:
|
|||||||
bool HasQuestDrop(LootTemplateMap const& store) const; // True if group includes at least 1 quest drop entry
|
bool HasQuestDrop(LootTemplateMap const& store) const; // True if group includes at least 1 quest drop entry
|
||||||
bool HasQuestDropForPlayer(Player const* player, LootTemplateMap const& store) const;
|
bool HasQuestDropForPlayer(Player const* player, LootTemplateMap const& store) const;
|
||||||
// The same for active quests of the player
|
// The same for active quests of the player
|
||||||
void Process(Loot& loot, Player const* player, LootStore const& lootstore, uint16 lootMode) const; // Rolls an item from the group (if any) and adds the item to the loot
|
void Process(Loot& loot, Player const* player, LootStore const& lootstore, uint16 lootMode, uint16 nonRefIterationsLeft) 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 RawTotalChance() const; // Overall chance for the group (without equal chanced items)
|
||||||
float TotalChance() const; // Overall chance for the group
|
float TotalChance() const; // Overall chance for the group
|
||||||
|
|
||||||
@@ -570,7 +570,8 @@ bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bo
|
|||||||
items.reserve(MAX_NR_LOOT_ITEMS);
|
items.reserve(MAX_NR_LOOT_ITEMS);
|
||||||
quest_items.reserve(MAX_NR_QUEST_ITEMS);
|
quest_items.reserve(MAX_NR_QUEST_ITEMS);
|
||||||
|
|
||||||
tab->Process(*this, store, lootMode, lootOwner); // Processing is done there, callback via Loot::AddItem()
|
// Initial group is 0, top level set to True
|
||||||
|
tab->Process(*this, store, lootMode, lootOwner, 0, true); // Processing is done there, callback via Loot::AddItem()
|
||||||
|
|
||||||
sScriptMgr->OnAfterLootTemplateProcess(this, tab, store, lootOwner, personal, noEmptyError, lootMode);
|
sScriptMgr->OnAfterLootTemplateProcess(this, tab, store, lootOwner, personal, noEmptyError, lootMode);
|
||||||
|
|
||||||
@@ -1413,7 +1414,7 @@ void LootTemplate::LootGroup::CopyConditions(ConditionList /*conditions*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
|
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
|
||||||
void LootTemplate::LootGroup::Process(Loot& loot, Player const* player, LootStore const& store, uint16 lootMode) const
|
void LootTemplate::LootGroup::Process(Loot& loot, Player const* player, LootStore const& store, uint16 lootMode, uint16 nonRefIterationsLeft) const
|
||||||
{
|
{
|
||||||
if (LootStoreItem const* item = Roll(loot, player, store, lootMode))
|
if (LootStoreItem const* item = Roll(loot, player, store, lootMode))
|
||||||
{
|
{
|
||||||
@@ -1426,7 +1427,9 @@ void LootTemplate::LootGroup::Process(Loot& loot, Player const* player, LootStor
|
|||||||
uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
|
uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
|
||||||
sScriptMgr->OnAfterRefCount(player, loot, rate, lootMode, const_cast<LootStoreItem*>(item), maxcount, store);
|
sScriptMgr->OnAfterRefCount(player, loot, rate, lootMode, const_cast<LootStoreItem*>(item), maxcount, store);
|
||||||
for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
|
for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
|
||||||
Referenced->Process(loot, store, lootMode, player, item->groupid);
|
// This reference needs to be processed further, but it is marked isTopLevel=false so that any groups inside
|
||||||
|
// the reference are not multiplied by Rate.Drop.Item.GroupAmount
|
||||||
|
Referenced->Process(loot, store, lootMode, player, item->groupid, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1434,6 +1437,14 @@ void LootTemplate::LootGroup::Process(Loot& loot, Player const* player, LootStor
|
|||||||
// Plain entries (not a reference, not grouped)
|
// Plain entries (not a reference, not grouped)
|
||||||
sScriptMgr->OnBeforeDropAddItem(player, loot, rate, lootMode, const_cast<LootStoreItem*>(item), store);
|
sScriptMgr->OnBeforeDropAddItem(player, loot, rate, lootMode, const_cast<LootStoreItem*>(item), store);
|
||||||
loot.AddItem(*item); // Chance is already checked, just add
|
loot.AddItem(*item); // Chance is already checked, just add
|
||||||
|
|
||||||
|
// If we still have non-ref runs to do for this group AND this item wasn't a reference,
|
||||||
|
// recursively call this function to produce more items for this group.
|
||||||
|
// However, if this is a quest item we shouldn't multiply this group.
|
||||||
|
if (nonRefIterationsLeft > 1 && !item->needs_quest)
|
||||||
|
{
|
||||||
|
this->Process(loot, player, store, lootMode, nonRefIterationsLeft-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1665,7 +1676,7 @@ bool LootTemplate::CopyConditions(LootItem* li, uint32 conditionLootId) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rolls for every item in the template and adds the rolled items the the loot
|
// Rolls for every item in the template and adds the rolled items the the loot
|
||||||
void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId) const
|
void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId, bool isTopLevel) const
|
||||||
{
|
{
|
||||||
bool rate = store.IsRatesAllowed();
|
bool rate = store.IsRatesAllowed();
|
||||||
|
|
||||||
@@ -1677,7 +1688,15 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode,
|
|||||||
if (!Groups[groupId - 1])
|
if (!Groups[groupId - 1])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Groups[groupId - 1]->Process(loot, player, store, lootMode);
|
// Rate.Drop.Item.GroupAmount is only in effect for the top loot template level
|
||||||
|
if (isTopLevel)
|
||||||
|
{
|
||||||
|
Groups[groupId - 1]->Process(loot, player, store, lootMode, sWorld->getRate(RATE_DROP_ITEM_GROUP_AMOUNT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Groups[groupId - 1]->Process(loot, player, store, lootMode, 0);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1687,7 +1706,6 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode,
|
|||||||
LootStoreItem* item = *i;
|
LootStoreItem* item = *i;
|
||||||
if (!(item->lootmode & lootMode)) // Do not add if mode mismatch
|
if (!(item->lootmode & lootMode)) // Do not add if mode mismatch
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!item->Roll(rate, player, loot, store))
|
if (!item->Roll(rate, player, loot, store))
|
||||||
continue; // Bad luck for the entry
|
continue; // Bad luck for the entry
|
||||||
|
|
||||||
@@ -1700,7 +1718,8 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode,
|
|||||||
uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
|
uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT));
|
||||||
sScriptMgr->OnAfterRefCount(player, loot, rate, lootMode, item, maxcount, store);
|
sScriptMgr->OnAfterRefCount(player, loot, rate, lootMode, item, maxcount, store);
|
||||||
for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
|
for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator
|
||||||
Referenced->Process(loot, store, lootMode, player, item->groupid);
|
// we're no longer in the top level, so isTopLevel is false
|
||||||
|
Referenced->Process(loot, store, lootMode, player, item->groupid, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1713,7 +1732,17 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode,
|
|||||||
// Now processing groups
|
// Now processing groups
|
||||||
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
|
for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i)
|
||||||
if (LootGroup* group = *i)
|
if (LootGroup* group = *i)
|
||||||
group->Process(loot, player, store, lootMode);
|
{
|
||||||
|
// Rate.Drop.Item.GroupAmount is only in effect for the top loot template level
|
||||||
|
if (isTopLevel)
|
||||||
|
{
|
||||||
|
group->Process(loot, player, store, lootMode, sWorld->getRate(RATE_DROP_ITEM_GROUP_AMOUNT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group->Process(loot, player, store, lootMode, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if template includes at least 1 quest drop entry
|
// True if template includes at least 1 quest drop entry
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ public:
|
|||||||
// Adds an entry to the group (at loading stage)
|
// Adds an entry to the group (at loading stage)
|
||||||
void AddEntry(LootStoreItem* item);
|
void AddEntry(LootStoreItem* item);
|
||||||
// Rolls for every item in the template and adds the rolled items the the loot
|
// Rolls for every item in the template and adds the rolled items the the loot
|
||||||
void Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId = 0) const;
|
void Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId = 0, bool isTopLevel = true) const;
|
||||||
void CopyConditions(ConditionList conditions);
|
void CopyConditions(ConditionList conditions);
|
||||||
bool CopyConditions(LootItem* li, uint32 conditionLootId = 0) const;
|
bool CopyConditions(LootItem* li, uint32 conditionLootId = 0) const;
|
||||||
|
|
||||||
|
|||||||
@@ -436,8 +436,8 @@ enum Rates
|
|||||||
RATE_DROP_ITEM_LEGENDARY,
|
RATE_DROP_ITEM_LEGENDARY,
|
||||||
RATE_DROP_ITEM_ARTIFACT,
|
RATE_DROP_ITEM_ARTIFACT,
|
||||||
RATE_DROP_ITEM_REFERENCED,
|
RATE_DROP_ITEM_REFERENCED,
|
||||||
|
|
||||||
RATE_DROP_ITEM_REFERENCED_AMOUNT,
|
RATE_DROP_ITEM_REFERENCED_AMOUNT,
|
||||||
|
RATE_DROP_ITEM_GROUP_AMOUNT,
|
||||||
RATE_SELLVALUE_ITEM_POOR,
|
RATE_SELLVALUE_ITEM_POOR,
|
||||||
RATE_SELLVALUE_ITEM_NORMAL,
|
RATE_SELLVALUE_ITEM_NORMAL,
|
||||||
RATE_SELLVALUE_ITEM_UNCOMMON,
|
RATE_SELLVALUE_ITEM_UNCOMMON,
|
||||||
|
|||||||
@@ -492,7 +492,9 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
_rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfigMgr->GetOption<float>("Rate.Drop.Item.Artifact", 1.0f);
|
_rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfigMgr->GetOption<float>("Rate.Drop.Item.Artifact", 1.0f);
|
||||||
_rate_values[RATE_DROP_ITEM_REFERENCED] = sConfigMgr->GetOption<float>("Rate.Drop.Item.Referenced", 1.0f);
|
_rate_values[RATE_DROP_ITEM_REFERENCED] = sConfigMgr->GetOption<float>("Rate.Drop.Item.Referenced", 1.0f);
|
||||||
_rate_values[RATE_DROP_ITEM_REFERENCED_AMOUNT] = sConfigMgr->GetOption<float>("Rate.Drop.Item.ReferencedAmount", 1.0f);
|
_rate_values[RATE_DROP_ITEM_REFERENCED_AMOUNT] = sConfigMgr->GetOption<float>("Rate.Drop.Item.ReferencedAmount", 1.0f);
|
||||||
|
_rate_values[RATE_DROP_ITEM_GROUP_AMOUNT] = sConfigMgr->GetOption<float>("Rate.Drop.Item.GroupAmount", 1.0f);
|
||||||
_rate_values[RATE_DROP_MONEY] = sConfigMgr->GetOption<float>("Rate.Drop.Money", 1.0f);
|
_rate_values[RATE_DROP_MONEY] = sConfigMgr->GetOption<float>("Rate.Drop.Money", 1.0f);
|
||||||
|
|
||||||
_rate_values[RATE_REWARD_BONUS_MONEY] = sConfigMgr->GetOption<float>("Rate.RewardBonusMoney", 1.0f);
|
_rate_values[RATE_REWARD_BONUS_MONEY] = sConfigMgr->GetOption<float>("Rate.RewardBonusMoney", 1.0f);
|
||||||
_rate_values[RATE_XP_KILL] = sConfigMgr->GetOption<float>("Rate.XP.Kill", 1.0f);
|
_rate_values[RATE_XP_KILL] = sConfigMgr->GetOption<float>("Rate.XP.Kill", 1.0f);
|
||||||
_rate_values[RATE_XP_BG_KILL_AV] = sConfigMgr->GetOption<float>("Rate.XP.BattlegroundKillAV", 1.0f);
|
_rate_values[RATE_XP_BG_KILL_AV] = sConfigMgr->GetOption<float>("Rate.XP.BattlegroundKillAV", 1.0f);
|
||||||
|
|||||||
Reference in New Issue
Block a user