View Single Post
  #22  
Old 01-15-2010, 08:31 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

After looking at this again, maybe trying a slight modification like this would work.

Change the part in Red here from zone/loottables.cpp:

Code:
void ZoneDatabase::AddLootDropToNPC(NPC* npc,int32 lootdrop_id, ItemList* itemlist) {
	const LootDrop_Struct* lds = GetLootDrop(lootdrop_id);
	if (!lds) {
	 //   LogFile->write(EQEMuLog::Error, "Database Or Memory error GetLootDrop(%i) == 0, npc:%s", lootdrop_id, npc->GetName());
		return;
	}
	if(lds->NumEntries == 0)	//nothing possible to add
		return;

//Removed code for pool looting which isn't applicable to this example

#else
	//non-pool based looting

	int32 r;
	int32 totalchance = 0;
	for (r = 0; r < lds->NumEntries; r++) {
		totalchance += lds->Entries[r].chance;
	}
	uint32 thischance = 0;
	unsigned short k;
	bool found = false;
	
	while(!found) {
		k = MakeRandomInt(0, lds->NumEntries-1);
		
		thischance = lds->Entries[k].chance;
		unsigned int drop_chance = rand() % totalchance;
#if EQDEBUG>=11
			LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, total chance:%i this chance:%i, drop roll:%i", npc->GetName(), totalchance, thischance, drop_chance);
#endif
		if (   totalchance == 0 
			|| thischance == 100
			|| thischance == totalchance // only droppable item in loot table
			|| drop_chance < thischance	//can never be true if thischance is 0
			) {
			found = true;
			int32 itemid = lds->Entries[k].item_id;
			
			const Item_Struct* dbitem = GetItem(itemid);
			npc->AddLootDrop(dbitem, itemlist, lds->Entries[k].item_charges, lds->Entries[k].equip_item, false);
			
			break;
			//continue;
		}	//end if it will drop
	}	//end loop
#endif
Into the part in blue here:

Code:
void ZoneDatabase::AddLootDropToNPC(NPC* npc,int32 lootdrop_id, ItemList* itemlist) {
	const LootDrop_Struct* lds = GetLootDrop(lootdrop_id);
	if (!lds) {
	 //   LogFile->write(EQEMuLog::Error, "Database Or Memory error GetLootDrop(%i) == 0, npc:%s", lootdrop_id, npc->GetName());
		return;
	}
	if(lds->NumEntries == 0)	//nothing possible to add
		return;

//Removed code for pool looting which isn't applicable to this example

#else
	//non-pool based looting

	int32 r;
	int32 totalchance = 0;
	for (r = 0; r < lds->NumEntries; r++) {
		totalchance += lds->Entries[r].chance;
	}
	uint32 thischance = 0;
	unsigned short k;
	bool found = false;
	
	k = MakeRandomInt(0, lds->NumEntries-1);

	while(!found) {
		if (k > (lds->NumEntries - 1)) {
			k = 0;
		}

		thischance = lds->Entries[k].chance;
		unsigned int drop_chance = rand() % totalchance;
#if EQDEBUG>=11
			LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, total chance:%i this chance:%i, drop roll:%i", npc->GetName(), totalchance, thischance, drop_chance);
#endif
		if (   totalchance == 0 
			|| thischance == 100
			|| thischance == totalchance // only droppable item in loot table
			|| drop_chance < thischance	//can never be true if thischance is 0
			) {
			found = true;
			int32 itemid = lds->Entries[k].item_id;
			
			const Item_Struct* dbitem = GetItem(itemid);
			npc->AddLootDrop(dbitem, itemlist, lds->Entries[k].item_charges, lds->Entries[k].equip_item, false);
			
			break;
			//continue;
		}	//end if it will drop
		k++;
	}	//end loop
#endif
Basically, what that will do is to make it so it only runs the RNG 1 time to decide the starting point to loop through the table entries. That is apposed to using the RNG every time it loops to chose a random entry to check if it will drop or not.

If there is an issue with the loot drop system, as far as I can tell, it would have to be due to the RNG itself. I think it is pretty well-known that the RNG is never as random as it really should be. This will at least prevent the RNG from repeatedly hitting the same drop over and over as it decides loot. There will still be RNG involved, but this should at least force it to continue down the list after it selects the random starting entry to check first.

I have personally seen some drop issues that point to there being a definite problem with drop rates. I think that it may work fine when repopping the same NPC over and over as in the example Cavedude gave. But, my theory is that the problem is something to do with server or zone restarts that cause it to give preference to certain drops for the first time a NPC spawns after a zone/server restart. I don't know why that would be the case, but that is just my best guess.

Either way, it might be worth giving this a long test to see if there is any improvement through feedback of players and testing and such.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 01-20-2010 at 10:23 PM..
Reply With Quote