public bool IsValid(LootStore store, uint entry) { if (mincount == 0) { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: wrong mincount ({3}) - skipped", store.GetName(), entry, itemid, reference); return(false); } if (reference == 0) // item (quest or non-quest) entry, maybe grouped { ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(itemid); if (proto == null) { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: item does not exist - skipped", store.GetName(), entry, itemid); return(false); } if (chance == 0 && groupid == 0) // Zero chance is allowed for grouped entries only { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: equal-chanced grouped entry, but group not defined - skipped", store.GetName(), entry, itemid); return(false); } if (chance != 0 && chance < 0.000001f) // loot with low chance { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: low chance ({3}) - skipped", store.GetName(), entry, itemid, chance); return(false); } if (maxcount < mincount) // wrong max count { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: max count ({3}) less that min count ({4}) - skipped", store.GetName(), entry, itemid, maxcount, reference); return(false); } } else // mincountOrRef < 0 { if (needs_quest) { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: quest chance will be treated as non-quest chance", store.GetName(), entry, itemid); } else if (chance == 0) // no chance for the reference { Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: zero chance is specified for a reference, skipped", store.GetName(), entry, itemid); return(false); } } return(true); // Referenced template existence is checked at whole store level }
public void Verify(LootStore lootstore, uint id, byte group_id = 0) { float chance = RawTotalChance(); if (chance > 101.0f) // @todo replace with 100% when DBs will be ready Log.outError(LogFilter.Sql, "Table '{0}' entry {1} group {2} has total chance > 100% ({3})", lootstore.GetName(), id, group_id, chance); if (chance >= 100.0f && !EqualChanced.Empty()) Log.outError(LogFilter.Sql, "Table '{0}' entry {1} group {2} has items with chance=0% but group total chance >= 100% ({3})", lootstore.GetName(), id, group_id, chance); }
// Calls processor of corresponding LootTemplate (which handles everything including references) public bool FillLoot(uint lootId, LootStore store, Player lootOwner, bool personal, bool noEmptyError = false, LootModes lootMode = LootModes.Default) { // Must be provided if (lootOwner == null) { return(false); } LootTemplate tab = store.GetLootFor(lootId); if (tab == null) { if (!noEmptyError) { Log.outError(LogFilter.Sql, "Table '{0}' loot id #{1} used but it doesn't have records.", store.GetName(), lootId); } return(false); } _itemContext = lootOwner.GetMap().GetDifficultyLootItemContext(); tab.Process(this, store.IsRatesAllowed(), (byte)lootMode); // Processing is done there, callback via Loot.AddItem() // Setting access rights for group loot case Group group = lootOwner.GetGroup(); if (!personal && group != null) { roundRobinPlayer = lootOwner.GetGUID(); for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.next()) { Player player = refe.GetSource(); if (player) // should actually be looted object instead of lootOwner but looter has to be really close so doesnt really matter { FillNotNormalLootFor(player, player.IsAtGroupRewardDistance(lootOwner)); } } for (byte i = 0; i < items.Count; ++i) { ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(items[i].itemid); if (proto != null) { if (proto.GetQuality() < group.GetLootThreshold()) { items[i].is_underthreshold = true; } } } } // ... for personal loot else { FillNotNormalLootFor(lootOwner, true); } return(true); }