Log in

View Full Version : Loottables


Zothen
06-04-2011, 02:12 PM
1.

Lets take Gynok Moltor for example:

He got 2 lootdrops : 2885 and 90097, but...

2885 has a probability of 50 and
90997 a probability of 100.

Is this supposed to work? Is the probability added up to 150 and then divided? Or is the lootdrop 90997 always rolled and 2885 does not have any chance to drop?


2. Can I make a lootdrop with a probability of 1/1000 for example?

3.
Another question:
I saw loottables with only 1 lootdrop in it, which sometimes got a probability below 100. Well, thats okay as some mobs arent supposed to drop loot every time. But what about the "chance" column in the lootdrop_entries table? Do the chances sum need to be 100?

Wolfling
06-04-2011, 03:26 PM
1. 2885
50 means its a 50% chance it will be picked, if it does, then it looks in the loot entries which on mine has a 5or6% chance to drop one of the rusty weapons,

90097 is 100, so will always get selected, and one of the two rings will get selected, as they are set 50/50 - so you will always get one of them
if you changes the multiplier to 2, then you always get 2 rings

2. you could, just give it low odds, 5% probability of being picked 5% chance of dropping the item ( that isn't the math, play around with it )

3. as explained above, and no, chance dosn't have to =100 that is why sometimes you will get nothing from that loot entry

Zothen
06-06-2011, 05:22 AM
Thank you very much! :)

trevius
06-06-2011, 06:21 AM
Maybe I am misunderstanding the explanation above, but this is how it works:

The chance field of the lootdrop_entries table does not have to equal 100. No matter what the total is for all entries in that lootdrop_id, the chance is basically a percentage of the total of the entries.

Here are some examples:

1. If there is only 1 lootdrop entry, the chance is 100% no matter if you set it to 1 or to 100.

2. If there are 3 loot drop entries that you want to all have equal drop chances, you can set each to 33, or you can set each to 100 or any other equal value and the chance will be divided equally.

3. If you have 3 entries and 1 is 100 and the other 2 are 50, then 1 of them will have 50% chance while the other 2 have 25% chance each.

Basically, it just totals up the chances and randoms and sees if the random outcome is less than the chance of the entry it is checking.

Zothen
06-06-2011, 10:34 AM
And the chance column works the same way as the probability column?

If thats really the way it works, then do I really always get 2 items of one lootdrop when the multiplier is set to 2? Wouldnt it be more random if I can get 0-2 items of a lootdrop, setting the multplier to 2 and the lootdrop entries to a max total chance of 50? Or is THAT handled with probability?

image
06-06-2011, 10:46 AM
for (int32 i=0; i<lts->NumEntries; i++) {
for (int32 k = 1; k <= lts->Entries[i].multiplier; k++) {
if ( MakeRandomInt(0,99) < lts->Entries[i].probability) {
AddLootDropToNPC(npc,lts->Entries[i].lootdrop_id, itemlist);
}
}

pretty much:
- For each lootdrop entry that exists on the mob we iterate (tied to whatever x loottable).
- Then inside each lootdrop, we iterate x times (multiplier).
- Inside the nested for loop we use a random 0-99, if the value is less than the probability you set, we attempt to spawn an item from that lootdrop.

In AddLootDropToNPC (determine the actual item):
- We add up the all the 'chance' values into totalchance (of each item in lootdrop_entries).
- To hit a good chance (its a RandomInt 0-totalchance). The random value must be chance=0 OR chance=100 OR this is the only item in the table (totalchance=itemchance) OR finally the random value is less than the current item chance. The first item that hits one of these conditions is your result. These should order as they are in the DB (so the first lootdrop_entries entry for this lootdrop in the db is the first item entry we check).

trevius
06-06-2011, 11:11 PM
Yeah, that explanation pretty much covers it all. The only correction I would make is about this:

These should order as they are in the DB (so the first lootdrop_entries entry for this lootdrop in the db is the first item entry we check).

To help decrease favoritism for items earlier in the DB order, we instead pick a random point in the total list to start at and then iterate until we get a successful roll. So, if we have 10 items in the same lootdrop_id, we would random 1 to 10 and (or 0 to 9 whatever) and start at the random spot that was picked, then continue to the next and so on.

On the question of multiple drops; that is set in the lootable_entries table with the multiplier and probability fields. So, if you want 0 to 2 possible drops from your lootdrop_id, you can set the multiplier to 2, then the probability to anything from 1 to 99 depending on how often you want 1 or 2 to drop. The multiplier is the max possible items from the lootdrop_id that can be dropped, and the probability is the chance for each multiplier to drop. If you set the multiplier to 10 and the probability to 10%, you would probably average about 1 drop per kill (in theory anyway), but could be anywhere from 0 to 10 at any time.

Zothen
06-07-2011, 08:10 AM
I am enlightened now ;)

well, almost...

lootdrop example:
lootdrop1 multiplier 1 prob 50
lootdrop2 multiplier 2 prob 100

so 3 lootdrop rolls altogether, right? lets say first roll is 43, it yields an item from lootdrop1, the other 2 rolls dont matter, cause its a guaranteed drop, makes a total of 3 item drops...?

Now to the chances. Does the current server release really favors items on top of the list or not? I remember reading an older post from you, trevius, about that topic...

image
06-07-2011, 08:24 AM
SELECT lootdrop_id, item_id, item_charges, equip_item, chance FROM lootdrop_entries WHERE lootdrop_id=%i order by chance desc

Thats the actual mysql query to get the lootdrop entries. They are added into memshare this way (so first result from this query is pos 0, second is position 1, etc.). Unless there is something else Trevius is talking about.

trevius
06-07-2011, 08:51 AM
Here is the code that handles the loot drops being added. Note the part highlighted in green where it picks a random entry from the total number of entries to start at and resets it back to 0 if it rolls past the end of the list.

loottables.cpp
// Called by AddLootTableToNPC
// maxdrops = size of the array npcd
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;

// This is Wiz's updated Pool Looting functionality. Eventually, the database format should be moved over to use this
// or implemented to support both methods. (A unique identifier in lootable_entries indicates to roll for a pool item
// in another table.
#ifdef POOLLOOTING
printf("POOL!\n");
int32 chancepool = 0;
int32 loot_items[100];
int8 equipitem[100];
int32 itemchance[100];
int16 itemcharges[100];
int8 i = 0;

for (int m=0;m < 100;m++) {
loot_items[m]=0;
itemchance[m]=0;
itemcharges[m]=0;
equipitem[m]=0;
}

for (int k=0; k<lds->NumEntries; k++)
{
loot_items[i] = lds->Entries[k].item_id;
int chance = lds->Entries[k].chance;
itemcharges[i] = lds->Entries[k].item_charges;
equipitem[i] = lds->Entries[k].equip_item;

/*
im not sure what this is trying to accomplish...
LinkedListIterator<ServerLootItem_Struct*> iterator(*itemlist);
iterator.Reset();
while(iterator.MoreElements())
{
if (iterator.GetData()->item_id == loot_items[i])
{
chance /= 5;
}
iterator.Advance();
}*/

chance += chancepool;
chancepool += lds->Entries[k].chance;
itemchance[i] = chance;
i++;
}
int32 res;
i = 0;

if (chancepool!=0) { //avoid divide by zero if some mobs have 0 for chancepool
res = MakeRandomInt(0, chancepool-1);
}
else {
res = 0;
}

while (loot_items[i] != 0) {
if (res <= itemchance[i])
break;
else
i++;
}
const Item_Struct* dbitem = GetItem(items[i]);
npc->AddLootDrop(dbitem, itemlist, lds->Entries[k].item_charges, lds->Entries[k].equip_item, false);

#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 = MakeRandomInt(0, totalchance-1);
#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++; //Cycle to the next droppable item in the list
} //end loop
#endif

}

This should prevent it from favoring items at the top of the list. It has been a while since I really looked into how these are all handled (not since that old thread Zothen referred to), but I think the way I described things so far in this thread should be accurate.

And yes, Zothen, your example of having 3 drops from that setup is correct. With those settings, you could have either 2 or 3 drops, depending on if the 50% probability one wins the roll or not.

image
06-07-2011, 08:54 AM
Gotcha. nm

Zothen
06-09-2011, 02:52 AM
Thank you both very much! That was very helpful.

quetark
06-14-2011, 12:50 AM
I'm pretty sure I understand all of this conversation and it's right in line with what I figured out on my own, but I must be missing something because I can't seem to get my new loot to drop. My goal was this: Get all the mobs that are supposed to drop the "ornate defiant scepter" (item ID: 50557) to drop it.

I started by trying to get Hill Giants in Rathe Mts to drop it 100% of the time, just so I could see it drop and then I'd back the % off to about 5. Here's what I did:

1. Add an entry into lootdrop_entries. the previous high value was 90495 so I made mine 90496:
insert into lootdrop_entries (lootdrop_id, item_id, item_charges, equip_item, chance) VALUES (90496, 50557, 1, 0, 100);
[Aside: does 'equip_item' mean the hill giant would have it equipped as his weapon?]

2. figure out that hill giants in rathe mts all use the same loot table (1839):
SELECT npc_types.id,npc_types.name,npc_types.loottable_id
FROM npc_types JOIN spawnentry ON npc_types.id=spawnentry.npcID
JOIN spawn2 ON spawnentry.spawngroupID = spawn2.spawngroupID
JOIN zone ON spawn2.zone = zone.short_name
where npc_types.name='a_hill_giant' and short_name='rathemtn';

3. Add a new entry into that loot table for my new loot drop, giving it a 100% chance of dropping:
insert into loottable_entries (loottable_id, lootdrop_id, multiplier, probability) VALUES (1839, 90496, 1, 100);

That seems pretty straight-forward to me, but none of my hill giants have dropped a scepter. What did I do wrong?

blackdragonsdg
06-14-2011, 02:11 AM
quetark, you appear to be missing the lootdrop entry. Try this:

INSERT INTO `lootdrop` (`id`, `name`) VALUES (90496, 'HG');

trevius
06-14-2011, 02:31 AM
Also make sure you restarted your server after you added the loot tables so they can take effect.

quetark
06-14-2011, 08:00 AM
The lootdrop table entry is what I was missing. Thank you! That seems like a pretty useless table, but apparently it's significant. My first HG kill dropped the scepter as expected. Thanks guys!

Zothen
06-17-2011, 06:05 AM
Hmm, I would like to add defiant gear to most of the mobs, but since the loottables are loaded globally, I fear that memory usage will explode.

Will there be a problem if there are too many long loottables and if so, is it hard to make loottables load per zone instead?

Zothen
06-23-2011, 07:32 AM
No one knows?

Burningsoul
06-23-2011, 03:34 PM
You could do it with georges' d2 loot editor. Get the ID's for the tier of defiant armor you'd want, plug them in the custom item list, and set the appropriate level range. Play around with the values, as you'll need to run it a few times on each level range (so keep the % of mobs to drop loot low).

Zothen
06-25-2011, 06:37 AM
Well, I know how to link the defiant gear to the mobs loottables. My question was if it will have a dramatic impact on the memory usage if I add defiant (or other missing gear from ZAM) to most of the NPCs.

blackdragonsdg
06-25-2011, 08:49 PM
Never really paid much attention to the amount of memory being used after adding loot tables but if there is some change it should be negligible. If you are really worried about it then backup your db then make the changes and see what happens.