// Loads a *_loot_template DB table into loot store // All checks of the loaded template are called from here, no error reports at loot generation required void LootStore::LoadLootTable() { LootTemplateMap::const_iterator tab; uint32 count = 0; // Clearing store (for reloading case) Clear(); sLog.outString( "%s :", GetName()); // 0 1 2 3 4 5 6 7 8 QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, groupid, mincountOrRef, maxcount, lootcondition, condition_value1, condition_value2 FROM %s",GetName()); if (result) { barGoLink bar(result->GetRowCount()); do { Field *fields = result->Fetch(); bar.step(); uint32 entry = fields[0].GetUInt32(); uint32 item = fields[1].GetUInt32(); float chanceOrQuestChance = fields[2].GetFloat(); uint8 group = fields[3].GetUInt8(); int32 mincountOrRef = fields[4].GetInt32(); uint32 maxcount = fields[5].GetUInt32(); ConditionType condition = (ConditionType)fields[6].GetUInt8(); uint32 cond_value1 = fields[7].GetUInt32(); uint32 cond_value2 = fields[8].GetUInt32(); if(maxcount > std::numeric_limits<uint8>::max()) { sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount,std::numeric_limits<uint8>::max()); continue; // error already printed to log/console. } if(!PlayerCondition::IsValid(condition,cond_value1, cond_value2)) { sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item); continue; // error already printed to log/console. } // (condition + cond_value1/2) are converted into single conditionId uint16 conditionId = objmgr.GetConditionId(condition, cond_value1, cond_value2); LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, group, conditionId, mincountOrRef, maxcount); if (!storeitem.IsValid(*this,entry)) // Validity checks continue; // Looking for the template of the entry // often entries are put together if (m_LootTemplates.empty() || tab->first != entry) {
// Rolls for every item in the template and adds the rolled items the the loot void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, 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 if (!Groups[groupId - 1]) return; Groups[groupId - 1]->Process(loot, lootMode); return; } // Rolling non-grouped items for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i) { LootStoreItem* item = *i; if (!(item->lootmode & lootMode)) // Do not add if mode mismatch continue; if (!item->Roll(rate)) continue; // Bad luck for the entry if (item->reference > 0) // References processing { LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(item->reference); if (!Referenced) continue; // Error message already printed at loading stage uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT)); for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator Referenced->Process(loot, rate, lootMode, item->groupid); } else // Plain entries (not a reference, not grouped) loot.AddItem(*item); // Chance is already checked, just add } // Now processing groups for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i) if (LootGroup* group = *i) group->Process(loot, lootMode); }
// Loads a *_loot_template DB table into loot store // All checks of the loaded template are called from here, no error reports at loot generation required uint32 LootStore::LoadLootTable() { LootTemplateMap::const_iterator tab; // Clearing store (for reloading case) Clear(); // 0 1 2 3 4 5 6 QueryResult result = WorldDatabase.PQuery("SELECT Entry, Item, Reference, Chance, QuestRequired, LootMode, GroupId, MinCount, MaxCount FROM %s", GetName()); if (!result) return 0; uint32 count = 0; do { Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 item = fields[1].GetUInt32(); uint32 reference = fields[2].GetUInt32(); float chance = fields[3].GetFloat(); bool needsquest = fields[4].GetBool(); uint16 lootmode = fields[5].GetUInt16(); uint8 groupid = fields[6].GetUInt8(); uint8 mincount = fields[7].GetUInt8(); uint8 maxcount = fields[8].GetUInt8(); if (groupid >= 1 << 7) // it stored in 7 bit field { TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d Item %d: GroupId (%u) must be less %u - skipped", GetName(), entry, item, groupid, 1 << 7); return 0; } LootStoreItem* storeitem = new LootStoreItem(item, reference, chance, needsquest, lootmode, groupid, mincount, maxcount); if (!storeitem->IsValid(*this, entry)) // Validity checks { delete storeitem; continue; } // Looking for the template of the entry // often entries are put together if (m_LootTemplates.empty() || tab->first != entry) { // Searching the template (in case template Id changed) tab = m_LootTemplates.find(entry); if (tab == m_LootTemplates.end()) { std::pair< LootTemplateMap::iterator, bool > pr = m_LootTemplates.insert(LootTemplateMap::value_type(entry, new LootTemplate())); tab = pr.first; } } // else is empty - template Id and iter are the same // finally iter refers to already existed or just created <entry, LootTemplate> // Adds current row to the template tab->second->AddEntry(storeitem); ++count; } while (result->NextRow()); Verify(); // Checks validity of the loot store return count; }