Making a Loot Box Calculator using Python (Rocket League)
Aloeb83 (42)

If you currently play any number of well-known video games today, you are likely familiar with the idea of loot boxes. For those who may be unaware, a loot box is an in-game chest that will randomly give you one or more items that can only be acquired through those means. It honestly acts very similarly a pack of trading cards and like trading card packs, the main way to receive these loot boxes, (or at least open them) is buy paying for them with real money.

However, unlike trading card packs, which tend to have at least one card of the highest or second highest rarity in each pack, most loot boxes don’t, if any do at all. This can lead to frustration as the most rare items are often the most sought after, meaning they most likely require more and more money to be spent if you hope to get it and if you don’t know how likely you are to get it, you may end up spending more money then you’d probably want to. However, for at least some loot boxes, we can figure out the odds of getting specific items, and in turn, find out around how much we would spend if we kept going for it.

That is what we’re going to do today. We’re going to create a calculator that factors in all the statistical odds of getting the loot box item that you want. And while every loot box is different, most of the same principles can be applied regardless of what game you’re trying to calculate for. So, let’s get started. For my example I am going to be using the game Rocket League and their loot box: “Crates.”

Step 1: Getting the Odds

In order to even begin you need to be able to know the odds of each specific factor that may have an effect on the final calculation. That means that some research is required on our part. Fortunately for our example, Psyonix, the makers of Rocket League, have released almost all of the information we need, and for the rest, we can easily find that out on our own. So, what are these odds?

First, each item has one of 5 rarities. These are: Rare, Very Rare, Import, Exotic, and Black Market. Second most of the items can be “painted.” This simply means that it can have a different color scheme then the item would normally have otherwise, and this spectrum has a maximum of 13 different colors. Not all items can get every color, but for our equation that factor is not that big of a deal.

Third, the item can be “certified.” Each item in the game will track one of serval stats that you gain with that item, but certification means that the item will track a stat it wouldn’t normally track, and like the paint colors, it comes in a maximum of 15 certifications, and not all items can have every one. However, the game’s community has determined, overall, that some certifications are better than others, and have put them into a list of 5 tiers, with Tier 1 having one certification, Tiers 2-3 having 3 each and Tiers 4-5 having 4 each. This is how we’ll divide this portion of our equation once we get there.

Finally, we need to know how many items of matching rarity to the item the player wants exists in that crate. Luckily for us, we can make the person using our calculator enter that all by themselves. Now, I know that is a lot of info for anyone who is unfamiliar with Rocket League or how their loot boxes work, but we can now apply the odds Psyonix has given to us, and the ones we find ourselves.

Step 2: Doing the Math

Since we have all this info now, we can simplify this info into an algebraic equation. The equation would go like this:

final = (rare * paint * specific * certified * tier)/quantity

Let’s quickly break down each variable:

final: The final number we are looking to get before we turn the number into a percentage or use it to find the total “cost” of getting the item.

rare: The rarity of the item we’re looking for.

paint: Is the item “painted”? Yes or no? That’s it.

specific: How many specific colors is the person looking for if the item is painted? 1? Any of the 13? Or anything in between?

certified: Like paint, we just want to know if the item is or isn’t certified.

tier: Which of the 5 tiers does our certified item fall into.

and finally,

quantity: How many items of like rareness exist in the crate.

Now that we have our equation, we need to know the what the exact odds for each variable is. For the items rarity, the spread of percentages goes like this: 55%, 28%, 12%, 4%, 1%. The 55% is for the least valuable “Rare” items, while the 1% is the most valuable “Black Market” items. These percentages represent the likeliness of getting an item of that specific value regardless of what the actual item is. For the chance of an item being painted or certified, it’s a 25% chance for both, there are a max of 13 different colors for painted items, and 5 different tiers for certified ones. Lastly, the quantity of items of matching rarity change from crate to crate, so that number must be added by whomever is using our calculator.

At this point we have both our equation and the numbers needed to fill in the variables, so we have the ability to calculate these odds on our own. That means the next step is actually making our calculator.

Step 3: Programming the Calculator

Since we have all the info we need to get started, the programming of this calculator is actually a lot simpler than it may seem. For this example I’ll be using the Python language, but this can be done using other languages like Javascript.

We are going to use 3 main components for this calculator: (1) Lists, (2) Dictionaries, and (3) User inputs, but the first thing we want to add to our code is this:

import Math

We want to do this, so that at our end product is a little bit cleaner than it might otherwise be, as we’ll be rounding a couple of numbers at the end.

Our next step is to create lists with all the possible percentages for each variable, excluding quantity, as again, that is inputed by the user of the calculator. While these aren’t the best names to use for variables, I used the first letter of each variable in our final equation to store the percentages in a list, r for rare, p for paint, s for specific, etc. We also want to store each percentage in its decimal form, so instead of storing 55% in the list, we would store .55.

Our lists should end up looking like this:

r = [.55, .28, .12, .04, .01]
p = [.25, 1]
s = [.08, .15, .23, .31, .38, .46, .54, .62, .69, .77, .85, .92, 1]
c = [.25, 1]
t = [.07, .2, .2, .27, .27, 1]

You’ll notice that most of the lists’ final value is 1. This is so that if there is nothing specific in done to that variable it won’t mess up our equation. For example, if the item they want is painted, but they don’t care which color, the specific variable will fill-in 1 in its place to make sure that the final number is correct.

You may also notice that the lists s and t have percentages in them, but we never found those numbers specifically. These numbers were found through divided up one number by the maximum possible results. For example, if someone wants only one specific color for their painted item, the percentage of getting that number would be 1/13 (with 13 being the max number of colors) which equals .08 or 8% if they wanted 2 it’d be 2/13 = .15, and so on. Similarly, as discussed earlier, each tier either has 1, 3, or 4, certifications in them out of the maximum 15, so each tiers percent is based on how many certifications were in the tier divided by 15. Again, the 1s exist in case they are fine with all colors (which would be 13/13) or they didn’t care about the certification tier (15/15).

Now that we have all our lists, we can make our first dictionary. Since we already have our equation in a certain order, it makes sense, that we start with a dictionary for rareness, and end with our one for tiers. Now, making each dictionary is actually pretty simple. All we need to do is assign each possible user answer with the correct index of the matching list. For example, if the user inputs “Exotic” as the rarity, we want it to index our “r” list so that it comes up with the result of .04 or 4%. Remember, the indexes start with the first value being 0, so our result for the “Exotic” input should be r[3].

Filling everything in, our dictionary looks like this:

rarity = {
  "Rare": r[0],
  "Very Rare": r[1],
  "Import": r[2],
  "Exotic": r[3],
  "Black Market": r[4],
}

Each of our following dictionaries will look very similar, with the only differences being what the user is able to input, (like numbers for how many colors/tiers, of Y/N for any Yes or No question) and how many possible results there will need to be (like 13 for colors which would be indexed as s[12]).

Before we can add the rest of the dictionaries, we need to make it so that our calculator can correctly access the part of the list that we need it to for our rarity. Luckily, it only takes 2 lines of code to do that.

rareness = input("Choose rarity: ")
rare = rarity[rareness]

This allows us to easily access our dictionary and grab the correct result before it replaces the rare variable in the final equation. We can now do the same thing with our next variable of paint.

is_it = {
  "Y": p[0],
  "N": p[1],
}
painted = input("Is this item painted? Y/N?")
paint = is_it[painted]

Personally, since we want our input to be either Y for yes or N for no, it should be specified in the question itself so that our user doesn’t input something incorrect and break our calculator before they get halfway through. We’ll end up doing the same thing when we ask if the item if certified or not.

Now, our next variable is color and while we will and the dictionary like normal, to get the correct number for our variable, we’re actually going to use and if-then statement. Why? Well, if the item they want is not painted, our calculator should skip the question of color entirely. If it doesn’t, our final result will be incorrect. So, how would we do this? Well, if the item is painted, (meaning the result indexed in our paint variable was p[0]) we want it to as the question and get its result as normal, otherwise, we want it to make the variable simply equal 1.

It would look like this:

color = {
  "1": s[0],
  "2": s[1],
  "3": s[2],
  "4": s[3],
  "5": s[4],
  "6": s[5],
  "7": s[6],
  "8": s[7],
  "9": s[8],
  "10": s[9],
  "11": s[10],
  "12": s[11],
  "13": s[12],
}

if paint == p[0]:
  specifics = input("Are you looking for any specific colors? How many? (Max:13)")
  specific = color[specifics]
else: 
  specific = 1

(Again, not the best variable names, I know)

Running this code, the computer will ignore the question of color if our item is not painted, and we do that same thing if our item is not certified, making sure that it doesn’t ask for a specific tier.

certification = {
  "Y": c[0],
  "N": c[1],
}

item = input("Is the item certified? Y/N?")
certified = certification[item]

skills = {
  "1": t[0],
  "2": t[1],
  "3": t[2],
  "4": t[3],
  "5": t[4],
  "Any": t[5],
}

if certified == c[0]:
  tiers = input("What type of certification? (For Tiers 1-5 enter that number, if any tier write Any)")
  tier = skills[tiers]
else:
  tier = 1

And that’s it for our dictionaries, the last things we need to do is get the quantity of the items of matching rarity, put our equation from the beginning into our code, and printing the result both in percentage form, while also telling them how many crates need to be opened, on average, before they get their item. Since you earn crates in Rocket League, but open them by buying an item call “keys,” we’ll tell them how many keys they would need to buy on average.

First, the quantity. To get the quantity, we simply use the same input function as we’ve been using throughout, but if we just do that, it will recognize the number as a string, rather then a number. To fix this, we simply put our input function inside of an int() function changing the number from a string to an integer. Next with just add our final equation into the code. The resulting code should look like this:

quantity = int(input("How many items of matching rarity are in your crate?"))
final = (rare * paint * specific * certified * tier)/quantity

Last but not least, we need to print out the result to our user. We use a simple print statement for this, while also using string concatenation to add our results into a nice looking sentence. Here’s how my last line of code looks.

print("There is a " + str(round(final*100, 2)) + "% chance that you will get your desired item. On average, it'll take " + str(math.ceil(1/final)) + " keys to get the item you are looking for.”)

You’ll notice that the first number is rounded, and after the *100 (in order to make our result a proper percent) there is a 2. This makes it so that our number doesn’t ever go past the second decimal point. This is done so that it gives off a cleaner look. You’ll see that the second number has “math.ceil” before it. This rounds the number up, no matter how small the decimal point may be, so the we get a full round number for the number of keys the person would need.

And that’s it! We have made a functioning calculator that determines the odds of getting specific items from crates in Rocket League. Try out the end product of what was made down below. Play a game that also uses loot boxes? Why not try to make a calculator for it?

Tips for Making Your Own Calculator

  1. Remember that many of the principles behind the calculator will be the same no matter what game you are using it for. So long as you can get all the numbers that you need, and can create an equation that will provide the correct answer, you pretty much have everything you need to be able to make a calculator yourself.

  2. Use better variable names than I did. I know that my variable names were not very good as many of them were too similar to each other. I recommend avoiding doing what I did in this regard as it could end up causing errors if you make just a simple typo.

  3. Keep it simple! I spent months trying to get this calculator to work, and I just couldn’t do it. The problem? I was trying to make it too complex. I was trying to do something that was way above my current skill level. It wasn’t until about a week ago that I realized I could simplify it way down and actually make a working end product. So don’t overcomplicate it.

That is it for this tutorial. I want to thank everyone who read this, as this is my first time entering a competition like this, so I don’t have a real gauge to know how well I did with it. So again, thank you for sticking through until the end, and I hope that you all enjoyed and could use this information in one way or another.

-Aloeb83

You are viewing a single comment. View All
Nanowrimoijk (37)

how are you supposed to type in your answer? it keeps popping up errors

Aloeb83 (42)

@Nanowrimoijk For choosing the rarity, the options are these: (Rare, Very Rare, Import, Exotic, Black Market) Everything else will ask for Y for Yes or N for No, a number or Any. Any words, or the Y/N answer, need to be capitalized for the code to run properly, so that's probably why the error occurred.