• Hi, Guest!
    Some images might be missing as we move away from using embedded images, sorry for the mess!
    From now on, you'll be required to use a third party to host images. You can learn how to add images here, and if your thread is missing images you can request them here.
    Do not use Discord to host any images you post, these links expire quickly!
Random ID from GameData

v20.1 Random ID from GameData 2022-06-02

This resource pertains to version 20.1 of Pokémon Essentials.
Pokémon Essentials Version
v20.1 ➖
This is a guide on how to create a method that gets a random ID from game data. (items, Pokémon, etc.) This is most commonly used for events that give the player a random item out of a set, like the tree in the default maps that gives the player a random Apricorn.

Note - This was written in v20, but it's compatible with v19 as well.

Pool​

The basic idea here is pretty simple -
  • Create an empty array
  • Add the ID of each entry in the data to the array
  • Sample the array
Ruby:
  pool = []
  GameData::Item.each { |item|
  pool.push(item.id)
  }
  item= pool.sample

You can see all the kinds of GameData in this section of the scripts -
1654123453542.png

Looking at the script in question will also let you look at the different attributes of the data - broad stuff like name or ID, or class-specific stuff like the base power of moves or weaknesses of a type.

Conditions​

It's not super helpful to just get every ID that exists out there, so you'll want to include a check to see if the entry matches whatever criteria you have for it. This can be pretty much anything - any attribute of the data can be checked against whatever you'd like. Some checks have custom methods for them - for example, while you could check item.has_flag?("Berry"), you could also check item.is_berry?. These checks can be found in the script sections mentioned above, and are sometimes listed on the wiki as well. (For example, the item checks are on the Manipulating items article)

Sometimes you won't have a special method for what you want, though, so you'll just have to write it out by hand. This can be pretty much anything, so I'm not going to go into too much detail, but a few points to remember -
  • == is to check one value against another, = is to set it. You want to use ==, not =.
  • You can check if a string of text includes another string with .include?("")
    • For example, say I want an NPC who loves red, and gives me items with "red" in their name - Red Shards, Red Nectar, Red Flutes, Red Cards, etc. I could do item.name.include?("Red").
      • This can get tricky, though, because you might not always think of all the items this could call. This is case-sensitive, but if it wasn't, then Sacred Ash could have also been pulled. Make sure to check your PBS with Ctrl+F, and try to use capitalization and spacing to make sure you're only getting what you want. (Or just create the array directly, honestly)
  • || means "or", && means "and". You can have parenthesis around two conditions to make them into one condition.
    • For example, say I want a berry or Apricorn that costs less than 500. I would write this as (item.is_berry? || is_apricorn?) && item.price < 500
  • ! is put in front of a check to see if it's false.
    • For example, say I want to give a random Pokémon, but I don't want it to be in the Undiscovered egg group. (which includes most Legendaries) I could write !species.egg_groups.include?(:Undiscovered)

Blacklist​

You might have cases where you want to make sure specific IDs aren't in the pool. (For example, with my red item NPC, they would also be giving out the Red Chain and Red Orb - too story-important to be given by a random NPC)

You'll want to create another array, this one containing every ID you don't want.
Ruby:
blacklist = [:MASTERBALL,:BEASTBALL]
Then you'd just check to make sure that the blacklist didn't include the ID - !blacklist.include?(item.id)

Examples​

Try writing these out on your own, then compare them to the answer given.

A random Berry
Ruby:
  GameData::Item.each { |item|
  pool.push(item.id) if GameData::Item.get(item).is_berry?
  }
  item = pool.sample
A random fossil, including the Gen 8 half fossils.
Ruby:
  pool = []
  GameData::Item.each { |item|
  pool.push(item.id) if (item.name.include?("Fossil") || item.is_fossil?)
  }
  item = pool.sample
This one is a little tricky! The Gen 8 fossils aren't given the fossil flag, because you need two of them to receive a Pokémon. But we can't just check for "Fossil" in the name, because then we'd leave out the Old Amber - so we need to check for either/or.
A random TM that the player doesn't have
Ruby:
  pool = []
  GameData::Item.each { |item|
  pool.push(item.id) if (item.is_TM? && !$bag.has?(item.id))
  }
  item = pool.sample
You can run checks that aren't just about the game data!

(If you're playtesting this and getting errors, remember that default Essentials doesn't have any TMs, they're all TRs)
A random Fire-type TM
Ruby:
  pool = []
  GameData::Item.each { |item|
  pool.push(item.id) if (item.is_TM? && GameData::Move.get(item.move).type == :FIRE)
  }
  item = pool.sample
Since the item data only has the move ID, we have to do a little work to get the move's data.
A random Water-type Pokémon that isn't a starter from Gens 1-4, and isn't a Legendary or Mythical.
Ruby:
  blacklist = [
  :SQUIRTLE,:WARTORTLE,:BLASTOISE,
  :TOTODILE,:CROCONAW,:FERALIGATR,
  :MUDKIP,:MARSHTOMP,:SWAMPERT,
  :PIPLUP,:PRINPLUP,:EMPOLEON,
  :MANAPHY]
  GameData::Species.each { |species|
  pool.push(species.id) if (species.types.include?(:WATER) && !species.egg_groups.include?(:Undiscovered) && !blacklist.include?(species))
  }
  species = pool.sample
A little harder than it sounds! Manaphy actually isn't in the Undiscovered egg group, so we have to add it to the blacklist. You also need to remember that the starter evolutions are a different species from their prevos, so you need to add them to the blacklist as well. (Technically, you could check if a Pokémon evolved from a species in the blacklist, but that's overcomplicating things a bit when we've already got so many checks)

Using this code​

So, that's how to write this, but where do we put it?

If you're using this just for one event, you can actually run the whole thing as a script command, and do whatever you want with the variable. Here's an example of that with the default map's Apricorn tree -

Ruby:
  pool = []
    GameData::Item.each { |item|
    pool.push(item.id) if (item.is_apricorn?)
  }
  item = pool.sample
  pbItemBall(item)

If you plan on using this in multiple different locations, you may find it easier to create a new method in the script editor.
Ruby:
def pbRandomApricorn
  pool = []
    GameData::Item.each { |item|
    pool.push(item.id) if (item.is_apricorn?)
  }
  item = pool.sample
  pbItemBall(item)
end
You can also make a method return the generated ID, so you could do something else with it. (Maybe an NPC who asks for a random item?)

Ruby:
def pbRandomApricorn
  pool = []
    GameData::Item.each { |item|
    pool.push(item.id) if (item.is_apricorn?)
  }
  item = pool.sample
  return item
end
1654128428796.png

Similar Resources​

Credits
This is largely based on Luka's Randomizer EX code, so credit should go to him.
Author
TechSkylander1518
Views
2,045
First release
Last update
Rating
0.00 star(s) 0 ratings

More resources from TechSkylander1518

Back
Top