Oh yeah I added some code for a min_count and the column in my database. I could see instances where you would need a minimum count. Some mobs are always supposed to drop one item, this is more efficient instead of a different loot table for just one item at 100%
So overall the changes I made are the loot is rolled in random order, there is a min drop and a float for the random chance. From my testing it appears solid, but I would need to test it for a few days to be sure.
Code: Select all
void ZoneServer::AddLoot(NPC* npc){
vector<int32> loot_tables = GetSpawnLootList(npc->GetDatabaseID(), GetZoneID(), npc->GetLevel(), race_types_list.GetRaceType(npc->GetModelType()));
if(loot_tables.size() > 0){
vector<LootDrop*>* loot_drops = 0;
vector<LootDrop*>::iterator loot_drop_itr;
LootTable* table = 0;
vector<int32>::iterator loot_list_itr;
float chance = 0;
for(loot_list_itr = loot_tables.begin(); loot_list_itr != loot_tables.end(); loot_list_itr++){
table = GetLootTable(*loot_list_itr);
if(table && table->maxcoin > 0){
chance = rand()%100;
if(table->coin_probability >= chance){
if(table->maxcoin > table->mincoin)
npc->AddLootCoins(table->mincoin + rand()%(table->maxcoin - table->mincoin));
}
}
chance = rand()%100;
if(table && (table->lootdrop_probability < 100 || table->lootdrop_probability >= chance)){
loot_drops = GetLootDrops(*loot_list_itr);
if(loot_drops){
LootDrop* drop = 0;
int16 count = 0;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle(loot_drops->begin(), loot_drops->end(), std::default_random_engine(seed));
while(count < table->minlootitems){
for(loot_drop_itr = loot_drops->begin(); loot_drop_itr != loot_drops->end(); loot_drop_itr++){
drop = *loot_drop_itr;
chance = (float)rand()/((float)(RAND_MAX))*100;
if(drop->probability >= chance){
count++;
npc->AddLootItem(drop->item_id, drop->item_charges);
LogWrite(MISC__TODO, 1, "TODO", "Auto-Equip new looted items\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
//if(drop->equip_item)
}
if(table->maxlootitems > 0 && count >= table->maxlootitems)
break;
}
}
for(loot_drop_itr = loot_drops->begin(); loot_drop_itr != loot_drops->end(); loot_drop_itr++){
drop = *loot_drop_itr;
chance = (float)rand()/((float)(RAND_MAX))*100;
if(drop->probability >= chance){
count++;
npc->AddLootItem(drop->item_id, drop->item_charges);
LogWrite(MISC__TODO, 1, "TODO", "Auto-Equip new looted items\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
//if(drop->equip_item)
}
if(table->maxlootitems > 0 && count >= table->maxlootitems)
break;
}
}
}
}
}
}Also in world.h
Code: Select all
struct LootTable{
string name;
int32 mincoin;
int32 maxcoin;
int16 minlootitems;
int16 maxlootitems;
float lootdrop_probability;
float coin_probability;
};Code: Select all
if (database_new.Select(&result, "SELECT id, name, mincoin, maxcoin, minlootitems, maxlootitems, lootdrop_probability, coin_probability FROM loottable")) {
LogWrite(LOOT__DEBUG, 0, "Loot", "--Loading LootTables...");
LootTable* table = 0;
// Load loottable from DB
while(result.Next()) {
int32 id = result.GetInt32Str("id");
table = new LootTable;
table->name = result.GetStringStr("name");
table->mincoin = result.GetInt32Str("mincoin");
table->maxcoin = result.GetInt32Str("maxcoin");
table->minlootitems = result.GetInt16Str("minlootitems");
table->maxlootitems = result.GetInt16Str("maxlootitems");
table->lootdrop_probability = result.GetFloatStr("lootdrop_probability");
table->coin_probability = result.GetFloatStr("coin_probability");
zone->AddLootTable(id, table);
LogWrite(LOOT__DEBUG, 5, "Loot", "---Loading LootTable '%s' (id: %u)", table->name.c_str(), id);
LogWrite(LOOT__DEBUG, 5, "Loot", "---min_coin: %u, max_coin: %u, min_items: %i, max_items: %i, prob: %.2f, coin_prob: %.2f", table->mincoin, table->maxcoin, table->minlootitems, table->maxlootitems, table->lootdrop_probability, table->coin_probability);
count++;
}
LogWrite(LOOT__DEBUG, 0, "Loot", "--Loaded %u loot table%s.", count, count == 1 ? "" : "s");
}