• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Eventing Question] Givining a random item

172
Posts
7
Years
    • Seen Sep 6, 2022
    Hey guys, im trying to make an event where a character can talk to a NPC and when they do, the npc will give a random item based off of a set pool of items. Does anyone know how to do this? I just need to know how to set the pool of items in the event and how to make it choose from random. thanks :)
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    Something along these lines maybe?

    Code:
    pool = [:POTION,:POKEBALL,:ANTIDOTE,:PARALYZEHEAL]
    index = ??? # generate random number from 0 to pool.length-1
    item = pool[index]
    # give item to player

    This assumes that all items should be equally likely.
     
    172
    Posts
    7
    Years
    • Seen Sep 6, 2022
    Something along these lines maybe?

    Code:
    pool = [:POTION,:POKEBALL,:ANTIDOTE,:PARALYZEHEAL]
    index = ??? # generate random number from 0 to pool.length-1
    item = pool[index]
    # give item to player

    This assumes that all items should be equally likely.

    I think I got one that works properly. it looks something like this.
    Code:
    items=[
    :SITRUSBERRY,:ORANBERRY,:LEAFSTONE,
    :MIRACLESEED,:SUNSTONE,:CHESTOBERRY,]
    random2=0
    loop do
    random2=rand(items.length)
    break if hasConst?(PBItems,items[
    random2])
    end
    Kernel.pbReceiveItem(getConst(
    PBItems,items[random2]))
    I basically copied it from the follow pokemon script and just tweaked and took out a few things.
    I probably don't even need more of that stuff in there because it sets a self switch after giving the item, but this is just the basic one that I copied and works.
     
    Last edited:
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    Awesome, it looks to me like it will work fine.

    I have a small comment about this bit from the perspective of a software developer:

    Code:
    loop do
      random2=rand(items.length)
      break if hasConst?(PBItems,items[random2])
    end

    This generates a random element from the list until it finds one that actually exists in PBItems. You could argue that this is appropriate for a script intended for other people to install, but my view is that it's a great way to hide typo-related errors (and trap your script in an infinite loop if you somehow make 100% typos/delete all the items from the game).

    Personally I'd prefer to write that particular part as simply:
    Code:
    random2=rand(items.length)

    And get an error if an invalid item happens to be picked. Or possibly even something like this:

    Code:
    throw "error" unless items.all? { |i| hasConst?(PBItems,i) }
    random2=rand(items.length)

    Not exactly sure how throw works in Ruby, but the intention here is to double-check the whole list of items and ensure that they all exist so that you don't have the possibility of you never encountering an error for a non-existent item but a player does (because by chance the particular buggy numbers never came up).
     
    Last edited:
    172
    Posts
    7
    Years
    • Seen Sep 6, 2022
    Awesome, it looks to me like it will work fine.

    I have a small comment about this bit from the perspective of a software developer:



    This generates a random element from the list until it finds one that actually exists in PBItems. You could argue that this is appropriate for a script intended for other people to install, but my view is that it's a great way to hide typo-related errors (and trap your script in an infinite loop if you somehow make 100% typos/delete all the items from the game).

    Personally I'd prefer to write that particular part as simply:
    Code:
    random2=rand(items.length)

    And get an error if an invalid item happens to be picked. Or possibly even something like this:

    Code:
    throw "error" unless items.all? { |i| hasConst?(PBItems,i) }
    random2=rand(items.length)

    Not exactly sure how throw works in Ruby, but the intention here is to double-check the whole list of items and ensure that they all exist so that you don't have the possibility of you never encountering an error for a non-existent item but a player does (because by chance the particular buggy numbers never came up).
    yeah I took out the part with the loop and it still works fine. although its still in the pokemon follower script lol.
    but I dont think that could happen as long as the names are written into the code properly right?
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    yeah I took out the part with the loop and it still works fine. although its still in the pokemon follower script lol.
    but I dont think that could happen as long as the names are written into the code properly right?

    Yeah, if all the names are correct then it's 100% the same with or without the loop.
     

    Ego13

    hollow_ego
    311
    Posts
    6
    Years
  • The way you do it is perfectly fine. Just want to add my solution to this question, which only is one line shorter but also more readable in my opinion.

    Code:
    Kernel.pbReceiveItem(item.random)
    item.random returns a random element of your item pool and the way you set this up actually allows to directly you it in pbReceiveItem

    @mggriffin : There is no need for a throw exception in Pokemon Essentials. If you ever get an error it will always tell you in what script section and in which line the error occured and what kind of error it is. I think this true for Ruby in general.
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    The way you do it is perfectly fine. Just want to add my solution to this question, which only is one line shorter but also more readable in my opinion.

    Code:
    Kernel.pbReceiveItem(item.random)
    item.random returns a random element of your item pool and the way you set this up actually allows to directly you it in pbReceiveItem
    For what it's worth I much prefer this to any of the other solutions in this thread.

    @mggriffin : There is no need for a throw exception in Pokemon Essentials. If you ever get an error it will always tell you in what script section and in which line the error occured and what kind of error it is. I think this true for Ruby in general.
    It's not important, but as-written I did need to throw something because hasConst? only returns a bool not throws an error. Perhaps getConst throws? Or maybe it returns nil? Anyway, I digress :)
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    I'm notsure what you mean by that :confused:

    So the intention of this code:

    Code:
    throw "error" unless items.all? { |i| hasConst?(PBItems,i) }

    Is to check that all the items in the list are valid items before we randomly choose one to give to the player. The idea is that this will catch 100% of typos, whereas without this check you'll only know that you made a typo if the random number generator chooses that item.

    Of course maybe the really sensible thing to do is write the list more like this:

    Code:
    items = [PBItems::POTION, PBItems::ANTIDOTE]

    Because by being explicit about the module here you'll get an error if the constant doesn't exist, and you don't have to litter your code with defensive checks.

    The behavior is now slightly different, PBItems::POTION is equivalent to getConst(PBItems, :POTION), but that wouldn't be an issue in this example.
     
    Last edited:

    Ego13

    hollow_ego
    311
    Posts
    6
    Years
  • So the intention of this code:

    Code:
    throw "error" unless items.all? { |i| hasConst?(PBItems,i) }

    Is to check that all the items in the list are valid items before we randomly choose one to give to the player. The idea is that this will catch 100% of typos, whereas without this check you'll only know that you made a typo if the random number generator chooses that item.

    Of course maybe the really sensible thing to do is write the list more like this:

    Code:
    items = [PBItems::POTION, PBItems::ANTIDOTE]

    Because by being explicit about the module here you'll get an error if the constant doesn't exist, and you don't have to litter your code with defensive checks.

    The behavior is now slightly different, PBItems::POTION is equivalent to getConst(PBItems, :POTION), but that wouldn't be an issue in this example.

    Ah I see so it is a way to check the spelling. I feel like this should be more a debug thingy and then it would be easier to check them by hand or by simply testing it out by giving each item once.
    Also I feel like "[PBItems::POTION" gives room for more misspelling, besides I don't think this works with the item giving method (I might be wrong though)
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    Ah I see so it is a way to check the spelling. I feel like this should be more a debug thingy and then it would be easier to check them by hand or by simply testing it out by giving each item once.
    That's reasonable. In my day job I've broken code by having typos that weren't covered in testing so my preference is that the game doesn't even start if there's an error in it (so that I know immediately after making a change if something is broken), but if you have different experiences who am I to judge? And besides, fan games aren't quite as high-stakes as business software :D
    Also I feel like "[PBItems::POTION" gives room for more misspelling, besides I don't think this works with the item giving method (I might be wrong though)
    If you misspell you'll get an error the moment the code tries to run because Ruby gets sad if you say Foo::BAR and BAR isn't defined in Foo. I don't know if it works in this specific example either, but a lot of Essentials' methods have a check that's like "if argument is a symbol then do getConst", and in these cases it's fine to pass in a ::-ed name because getConst is basically just that.
     

    Ego13

    hollow_ego
    311
    Posts
    6
    Years
  • That's reasonable. In my day job I've broken code by having typos that weren't covered in testing so my preference is that the game doesn't even start if there's an error in it (so that I know immediately after making a change if something is broken), but if you have different experiences who am I to judge? And besides, fan games aren't quite as high-stakes as business software :D

    The big advantage of fan games is that they can take as much time for debugging as they need to. And even if a game breaking error occurs you can easily fix it. I had some game crashing bugs in my latest release and was able to fix it within minutes and upload a patch and an updated version. For any oher software dev I would totally agree with you.
     
    Back
    Top