fonsleenaars / tqdb

Python parser for the Titan Quest Anniversary Edition, Ragnarok, Atlantis, Eternal Ember DLC database.
https://tq-db.net
MIT License
50 stars 15 forks source link

Filter bosses/heroes listed as being able to drop items by using item level + loot table item min/max level #36

Closed giffsapros closed 5 years ago

giffsapros commented 6 years ago

Some bosses/heroes listed on website as being able to drop a specific item from their loot pool don't appear to actually be able to do so if the item's level is outside of the loot table's level ranges, and it does not appear that the item drop chances listed on the website take this into account. Below, I document evidence for why I think this is the case.

Over the last two weeks, I did about 2000 Hydra chest runs, hoping to get a specific drop from it (see my username). During this time, I did not get any such drops, but I did not get any Aphrodite's Favor drops either. What follows is an estimation of the probability of Aphrodite's Favor not dropping during this time.

Per the website, each item dropped from the Hydra's chest has a 0.077% chance of being an Aphrodite's Favor drop - this may not be completely accurate, but it's good enough for an order-of-magnitude calculation. From the extracted game files, the Hydra loot table is hydra_default_55-57, and using the numSpawnMinEquation and numSpawnMaxEquation attribute values, we estimate that the chest should drop ~9 items each time (rounding down for the sake of a conservative estimate). Therefore, the chance of obtaining at least one Aphrodite's Favor drop each Hydra run is ~ 0.69%.

Given this drop rate for Aphrodite's Favor, the probability that no Aphrodite's Favors are dropped in 2000 Hydra chest runs is then ~ 0.0001% i.e. a one-in-a-million occurrence, which is what happened to me. It's possible that this could just be due to RNG, but I suspect that what's happening here is that it's actually not possible for Aphrodite's Favor to drop from Hydra. I think that this is likely because Aphrodite's Favor has an item level of 80 (according to its itemLevel attribute), and in the legendary amulet drop table used by the Hydra chest (amulet_l01), the maximum possible level of the items that are allowed to drop from this table is 69, per the maxItemLevelEquation value, and as such Aphrodite's Favor can't actually drop from the amulet_l01 table. Some evidence that this is how the min/maxItemLevelEquation work can be found in page 51 of the Grim Dawn modding guide - of course, this is assuming that the Grim Dawn engine has the same underlying mechanics as Titan Quest.

Finally, note that this is just the calculation for Aphrodite's Favor; I spotchecked several other legendary items which did not get dropped during those 2000 runs (e.g. Kraken's Fist, Fingerbone of Boreas), and found that they too, had an item level outside of the max item level specified for their corresponding drop table.

The upshot of all this is: I don't believe it's possible for the Hydra (or other Act 1 bosses) to drop Sapros and other high-level legendaries any more. It may have been possible in the past - I've seen some posts where people mention getting Sapros drops from the Hydra - but I suspect it isn't any more.

If this is correct, then I think it would be useful to filter the bosses/heroes listed on the website as having an item in their drop table down to those who are actually able to drop the item, based on the item level and the maxItemLevelEquation of the loot table the boss/hero is using.

fonsleenaars commented 6 years ago

Agreed, the complexity of the actual drop table is higher than what the parser currently uses (just grab all possible drops, adjust the weights per table and calculate the final possibility).

What you're suggesting does seem to be the better idea, however it requires 2 fundamental changes in the current setup:

  1. Provide input into an equation of some sort from the website through an input field
  2. Provide a mechanism from the parser to translate the equations in the database to easy equations for input from step 1.

I agree it should be the end goal of the parser, however it will take me some time to run through the other issues first. The current priority is on getting the attributes/statistics per item to match what's in-game, as I seem to have hit quite a few exceptions after the last big update.

Thanks for the suggestion though, it'll help me get on track quickly after sorting out the current issues.

giffsapros commented 6 years ago

I wouldn't think you would need to update the website with any sort of additional user input - unless you wanted to allow website users to toggle the filtering? I was just thinking that the parser would check whether the item's level fell within the ranges defined by the loot table's minItemLevelEquation and maxItemLevelEquation, and if not, omit the item from the index built for the loot table's drops, so that bosses using that loot table would not be listed as being able to drop the item on the website.

Even with that limited scope, I agree it would be tricky to get this to work, depending on how complex the equations present in the database attributes are. Seems like you would have to write code for parsing the individual equations, or attempt to just evaluate the mathematical expressions directly as code with Python's eval function (lol).

Definitely understand if this isn't a priority though. Cheers!

fonsleenaars commented 5 years ago

Since I've worked on getting the loot tables expanded and added some more sources to it, it's time to make this a priority now. Work on it will begin now and it should be included in the next release.

fonsleenaars commented 5 years ago

You were absolutely right about the min and max levels capping what can be dropped.

This solves the initial problem, we can now:

The second problem is the following, the bell curve weights are applied based on the targetLevel. For example, looking at the armband_e01.dbr file in the loot tables, we have:

minItemLevelEquation,36 * 1
maxItemLevelEquation,47 * 1
bellSlope,200.000000;200.000000;200.000000;100.000000;100.000000;100.000000;100.000000;100.000000;100.000000;100.000000;100.000000;100.000000
targetLevelEquation,((20 + parentLevel) / 2) * (1+(averagePlayerLevel / 75))

The bellSlope values are mapped for each level between the min and max, so basically:

Level 36: 200 Level 37: 200 Level 38: 200 Level 39: 100 ... Level 47: 100

The targetLevel sets the starting point for the list above. If the targetLevel comes out to 39, then 39 will start with 200, and so on.

For now I'm going to just run the min and max and remove the initial batch of items that can't even drop and then I'm going to think about how to handle step 2.

fonsleenaars commented 5 years ago

@giffsapros I have deployed the new data set (which has implemented the first step, removing items outside the range) to the staging environment here: https://staging.tq-db.net/monsters

You can browse around and see if this matches up better with what you found. The second step, which will apply the weights as I've described above will be implemented soon as well.

fonsleenaars commented 5 years ago

The second step has also been implemented, is currently live on staging and will be pushed to production with the 1.2.1 milestone for the parser.