[7131] Ignore loot rates for some internal loot tables and batter loot checking at load.

This commit is contained in:
VladimirMangos 2009-01-21 05:34:57 +03:00
parent 1718653e63
commit 93662a1fb3
3 changed files with 65 additions and 37 deletions

View file

@ -34,17 +34,17 @@ static Rates const qualityToRate[MAX_ITEM_QUALITY] = {
RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT
}; };
LootStore LootTemplates_Creature( "creature_loot_template", "creature entry"); LootStore LootTemplates_Creature( "creature_loot_template", "creature entry", true);
LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id"); LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id", true);
LootStore LootTemplates_Fishing( "fishing_loot_template", "area id"); LootStore LootTemplates_Fishing( "fishing_loot_template", "area id", true);
LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry"); LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry", true);
LootStore LootTemplates_Item( "item_loot_template", "item entry"); LootStore LootTemplates_Item( "item_loot_template", "item entry", true);
LootStore LootTemplates_Milling( "milling_loot_template", "item entry"); LootStore LootTemplates_Milling( "milling_loot_template", "item entry (herb)", true);
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid"); LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid", true);
LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry"); LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry (ore)", true);
LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id"); LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id (with mail template)",false);
LootStore LootTemplates_Reference( "reference_loot_template", "reference id"); LootStore LootTemplates_Reference( "reference_loot_template", "reference id", false);
LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id"); LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id", true);
class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed) class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed)
{ {
@ -53,7 +53,7 @@ class LootTemplate::LootGroup // A set of loot def
bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry
bool HasQuestDropForPlayer(Player const * player) const; bool HasQuestDropForPlayer(Player const * player) const;
// The same for active quests of the player // 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, bool rate) 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
@ -64,7 +64,7 @@ class LootTemplate::LootGroup // A set of loot def
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
LootStoreItem const * Roll() const; // Rolls an item from the group, returns NULL if all miss their chances LootStoreItem const * Roll(bool rate) const; // Rolls an item from the group, returns NULL if all miss their chances
}; };
//Remove all data and free all memory //Remove all data and free all memory
@ -228,17 +228,17 @@ void LootStore::ReportNotExistedId(uint32 id) const
// Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation) // Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation)
// RATE_DROP_ITEMS is no longer used for all types of entries // RATE_DROP_ITEMS is no longer used for all types of entries
bool LootStoreItem::Roll() const bool LootStoreItem::Roll(bool rate) const
{ {
if(chance>=100.f) if(chance>=100.f)
return true; return true;
if(mincountOrRef < 0) // reference case if(mincountOrRef < 0) // reference case
return roll_chance_f(chance*sWorld.getRate(RATE_DROP_ITEM_REFERENCED)); return roll_chance_f(chance* (rate ? sWorld.getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f));
ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid);
float qualityModifier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; float qualityModifier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f;
return roll_chance_f(chance*qualityModifier); return roll_chance_f(chance*qualityModifier);
} }
@ -377,7 +377,7 @@ void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner)
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); // Processing is done there, callback via Loot::AddItem() tab->Process(*this, store,store.IsRatesAllowed ()); // Processing is done there, callback via Loot::AddItem()
// Setting access rights fow group-looting case // Setting access rights fow group-looting case
if(!loot_owner) if(!loot_owner)
@ -763,7 +763,7 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem& item)
} }
// Rolls an item from the group, returns NULL if all miss their chances // Rolls an item from the group, returns NULL if all miss their chances
LootStoreItem const * LootTemplate::LootGroup::Roll() const LootStoreItem const * LootTemplate::LootGroup::Roll(bool rate) const
{ {
if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
{ {
@ -775,7 +775,7 @@ LootStoreItem const * LootTemplate::LootGroup::Roll() const
return &ExplicitlyChanced[i]; return &ExplicitlyChanced[i];
ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid); ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid);
float qualityMultiplier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; float qualityMultiplier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f;
Roll -= ExplicitlyChanced[i].chance * qualityMultiplier; Roll -= ExplicitlyChanced[i].chance * qualityMultiplier;
if (Roll < 0) if (Roll < 0)
return &ExplicitlyChanced[i]; return &ExplicitlyChanced[i];
@ -812,9 +812,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 // 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, bool rate) const
{ {
LootStoreItem const * item = Roll(); LootStoreItem const * item = Roll(rate);
if (item != NULL) if (item != NULL)
loot.AddItem(*item); loot.AddItem(*item);
} }
@ -899,21 +899,21 @@ void LootTemplate::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 LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) const void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 groupId) const
{ {
if (groupId) // Group reference uses own processing of the group if (groupId) // Group reference uses own processing of the group
{ {
if (groupId > Groups.size()) if (groupId > Groups.size())
return; // Error message already printed at loading stage return; // Error message already printed at loading stage
Groups[groupId-1].Process(loot); Groups[groupId-1].Process(loot,rate);
return; return;
} }
// Rolling non-grouped items // Rolling non-grouped items
for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i ) for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i )
{ {
if ( !i->Roll() ) if (!i->Roll(rate))
continue; // Bad luck for the entry continue; // Bad luck for the entry
if (i->mincountOrRef < 0) // References processing if (i->mincountOrRef < 0) // References processing
@ -924,7 +924,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co
continue; // Error message already printed at loading stage continue; // Error message already printed at loading stage
for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator
Referenced->Process(loot, store, i->group); // Ref processing Referenced->Process(loot, store, rate, i->group);
} }
else // Plain entries (not a reference, not grouped) else // Plain entries (not a reference, not grouped)
loot.AddItem(*i); // Chance is already checked, just add loot.AddItem(*i); // Chance is already checked, just add
@ -932,7 +932,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co
// 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 )
i->Process(loot); i->Process(loot,rate);
} }
// True if template includes at least 1 quest drop entry // True if template includes at least 1 quest drop entry
@ -1143,9 +1143,17 @@ void LoadLootTemplates_Milling()
// remove real entries and check existence loot // remove real entries and check existence loot
for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i)) {
ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i);
if(!proto)
continue;
if((proto->BagFamily & BAG_FAMILY_MASK_HERBS)==0)
continue;
if(ids_set.count(proto->ItemId)) if(ids_set.count(proto->ItemId))
ids_set.erase(proto->ItemId); ids_set.erase(proto->ItemId);
}
// output error for any still listed (not referenced from appropriate table) ids // output error for any still listed (not referenced from appropriate table) ids
LootTemplates_Milling.ReportUnusedIds(ids_set); LootTemplates_Milling.ReportUnusedIds(ids_set);
@ -1184,9 +1192,17 @@ void LoadLootTemplates_Prospecting()
// remove real entries and check existence loot // remove real entries and check existence loot
for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i)) {
ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i);
if(!proto)
continue;
if((proto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)==0)
continue;
if(ids_set.count(proto->ItemId)) if(ids_set.count(proto->ItemId))
ids_set.erase(proto->ItemId); ids_set.erase(proto->ItemId);
}
// output error for any still listed (not referenced from appropriate table) ids // output error for any still listed (not referenced from appropriate table) ids
LootTemplates_Prospecting.ReportUnusedIds(ids_set); LootTemplates_Prospecting.ReportUnusedIds(ids_set);
@ -1200,8 +1216,15 @@ void LoadLootTemplates_QuestMail()
// remove real entries and check existence loot // remove real entries and check existence loot
ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates(); ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates();
for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr ) for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr )
if(ids_set.count(itr->first)) {
if(!itr->second->GetRewMailTemplateId())
continue;
if(!ids_set.count(itr->first))
LootTemplates_QuestMail.ReportNotExistedId(itr->first);
else
ids_set.erase(itr->first); ids_set.erase(itr->first);
}
// output error for any still listed (not referenced from appropriate table) ids // output error for any still listed (not referenced from appropriate table) ids
LootTemplates_QuestMail.ReportUnusedIds(ids_set); LootTemplates_QuestMail.ReportUnusedIds(ids_set);

View file

@ -75,7 +75,7 @@ struct LootStoreItem
group(_group), maxcount(_maxcount), conditionId(_conditionId), group(_group), maxcount(_maxcount), conditionId(_conditionId),
needs_quest(_chanceOrQuestChance < 0) {} needs_quest(_chanceOrQuestChance < 0) {}
bool Roll() const; // Checks if the entry takes it's chance (at loot generation) bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation)
bool IsValid(LootStore const& store, uint32 entry) const; bool IsValid(LootStore const& store, uint32 entry) const;
// Checks correctness of values // Checks correctness of values
}; };
@ -127,7 +127,8 @@ typedef std::set<uint32> LootIdSet;
class LootStore class LootStore
{ {
public: public:
explicit LootStore(char const* name, char const* entryName) : m_name(name), m_entryName(entryName) {} explicit LootStore(char const* name, char const* entryName, bool ratesAllowed)
: m_name(name), m_entryName(entryName), m_ratesAllowed(m_ratesAllowed) {}
virtual ~LootStore() { Clear(); } virtual ~LootStore() { Clear(); }
void Verify() const; void Verify() const;
@ -145,6 +146,7 @@ class LootStore
char const* GetName() const { return m_name; } char const* GetName() const { return m_name; }
char const* GetEntryName() const { return m_entryName; } char const* GetEntryName() const { return m_entryName; }
bool IsRatesAllowed() const { return m_ratesAllowed; }
protected: protected:
void LoadLootTable(); void LoadLootTable();
void Clear(); void Clear();
@ -152,6 +154,7 @@ class LootStore
LootTemplateMap m_LootTemplates; LootTemplateMap m_LootTemplates;
char const* m_name; char const* m_name;
char const* m_entryName; char const* m_entryName;
bool m_ratesAllowed;
}; };
class LootTemplate class LootTemplate
@ -163,7 +166,7 @@ class LootTemplate
// 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, uint8 GroupId = 0) const; void Process(Loot& loot, LootStore const& store, bool rate, uint8 GroupId = 0) const;
// True if template includes at least 1 quest drop entry // True if template includes at least 1 quest drop entry
bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const; bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const;
@ -312,6 +315,7 @@ void LoadLootTemplates_Skinning();
void LoadLootTemplates_Disenchant(); void LoadLootTemplates_Disenchant();
void LoadLootTemplates_Prospecting(); void LoadLootTemplates_Prospecting();
void LoadLootTemplates_QuestMail(); void LoadLootTemplates_QuestMail();
void LoadLootTemplates_Reference(); void LoadLootTemplates_Reference();
inline void LoadLootTables() inline void LoadLootTables()
@ -326,6 +330,7 @@ inline void LoadLootTables()
LoadLootTemplates_Disenchant(); LoadLootTemplates_Disenchant();
LoadLootTemplates_Prospecting(); LoadLootTemplates_Prospecting();
LoadLootTemplates_QuestMail(); LoadLootTemplates_QuestMail();
LoadLootTemplates_Reference(); LoadLootTemplates_Reference();
} }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7130" #define REVISION_NR "7131"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__