• 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.

[Scripting Question] Hidden abilities occur naturally

38
Posts
9
Years
    • Seen Apr 20, 2024
    I found this Script on Relic Castle by Michael "Link". It's supposed to make Pokemon have their hidden abilities like their regular abilities naturally, whether when encountering Pokemon in the wild or when you're gifted a Pokemon or if you're fighting a trainer his/her Pokemon can have a hidden ability if the Pokemon is randomly generated, just like in Pokemon Reborn.
    I added the script to my game but the problem is the only abilities the Pokemon gets are the first regular ability or the first hidden ability defined in the PBS. Let's say I add a bunch of abilities to Archen the PBS lines look like this:

    Abilities=DEFEATIST,RUNAWAY
    HiddenAbility=EARLYBIRD,KEENEYE,SANDRUSH

    Every Archen I get have either Defeatist or Early Bird as an ability, it ignores Run Away, Keen Eye and Sand Rush. I tried with over 50 Pokemon with the same results. I have many Fakemon with more than one hidden ability. Some have 6 abilities in total with 2 regular ones and 4 HAs which is the maximum in essentials.
    I don't know how to fix the script to work as intended, I replied on the Relic Castle thread but got no response unfortunately.
    I also found out that debug mode doesn't list all the Pokemon abilities when using this script like this:
    khhKtZr.png


    When it should display this:
    ggvvDMc.png

    Can someone help me?
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    At a guess I'd say that this line:
    Code:
        abil=@abilityflag!=nil ? @abilityflag: (@personalID%3)
    Means that there can only be up to three abilities chosen by the personalID (the two regular ones, and one hidden one) because of the % 3, and how that value is used in the rest of the code.
     
    Last edited:
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    I changed the %3 to %6 before posting this because I read this thread but nothing changed, I don't know what else needs to be changed.
     
    Last edited:
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    I guess you should work out what abil, h1, h2, h3 and h4 are for your example. I suspect they might not be what you think they are.
     
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    I'm sorry but I'm still a beginner when it comes to scripting, can you explain a bit more in details. I can find my way when messing with abilities and battle related scripts but when it comes to how Ruby gets info from the PBS files and how it uses it I'm completely clueless. For example I have no idea what
    dexdata=pbOpenDexData or dexdata.fgetb means. Sorry for asking too much.
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    So Essentials gets data from the PBS in two steps:
    1. It takes the PBS file and turns it into a big ol' series of bytes. This happens in the compiler.
    2. It takes the compiled bytes, and extracts values from them. This is what pbOpenDexData and fgetb do respectively (specifically fgetb extracts one byte—i.e. a value from 0 to 255, there are other fgetX functions that extract different ranges of values by reading more than just one byte).

    It's important to note that once things are compiled into bytes Essentials just uses logic like "the ability bytes are from X to Y", so it's very important that the Xs and Ys are the same in every place in the code they appear. e.g. if your compiler doesn't write the hidden ability bytes to the file, or writes bytes for different data at those locations you'd get some very weird behavior.

    But to start with I think you should simply print out what all those values are, so that you can simulate the path that's taken through the code in your head. You can do that with something like
    Code:
    p "abil=#{abil}, h1234=#{h1}, #{h2}, #{h3}, #{h4}"
     
    Last edited:
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    Thanks for explaining in details, I'll try to mess around with it later since I'm going to sleep right now. I have a dumb question though, where should I put the line you posted so I can see the values of the those variables?
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    It's gotta be a place where all those variables are in scope, so there's a bunch of places in ability, but personally I'd stick it under "dexdata.close"
     
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    Alright so I printed the values of abil and h1, h2, h3 and h4 here's what I got, I'll refer to regular ability as RA and hidden as HA:
    Spoiler:

    I'm assuming h1, h2, h3, and h4 are the hidden abilities values and as you can see h2 and h4 are always 0 so I think they're not getting the correct data from the PBS files. How can I change their values since all of them have the same expression
    Code:
    hX=dexdata.fgetb
    do I have to change number 40 in this line?
    Code:
    pbDexDataOffset(dexdata,@species,40)
    Same thing for ret1 and ret2 I'm also assuming they contain the values of both RA, the first ability have no problems but the second never shows up. I'm guessing I have to change this
    Code:
    pbDexDataOffset(dexdata,@species,2)
    Last thing is I don't know how Fakemon #4 got its second HA I tried receiving it again multiple times but I only got either the first RA or first HA. The second HA shows up when I'm using debug to see the abilities list so its values is being imported from the PBS.
    You should know that I'm still using %6 instead of %3 in
    Code:
    abil=@abilityflag!=nil ? @abilityflag: (@personalID%3)

    Update: I changed every dexdata.fgetb with dexdata.fgetw and it seems to be working so far.
     
    Last edited:
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    Update: I changed every dexdata.fgetb with dexdata.fgetw and it seems to be working so far.
    Glad you sorted it out! If you wanted to confirm that you did the right thing you could try checking the compiler to see that it writes two bytes for each ability. I think there's a section for each PBS file, and at the top of each section is a data structure that describes the layout of the bytes. But it's probably unnecessary if you've tested with all four hidden abilities and nothing has broken :)
     
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    I don't know how to check the compiler, but I can confirm that all the abilities work. When I use the debug mode to modify a Pokemon I can give it any ability and all of them work. And any Pokemon I get can have any ability assigned to it. Also h2 and h4 aren't 0 anymore, so it should be working fine. Again thanks a lot for all your help I really appreciate it.
     
    1,403
    Posts
    10
    Years
    • Seen Apr 29, 2024
    In case you're curious as to why it was h2 and h4, that's because of endianness. Basically if you write a two-byte number that could fit in one byte, the first byte will contain that number, and the second contains a zero.

    Also, it would be great if you could consider posting your fixed version of the resource here (giving credit and linking to the original author and post over on RC).
     
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    In case you're curious as to why it was h2 and h4, that's because of endianness. Basically if you write a two-byte number that could fit in one byte, the first byte will contain that number, and the second contains a zero.
    I see, thanks about that I still have a long way to completely understand how everything works in Essentials.

    Also, it would be great if you could consider posting your fixed version of the resource here (giving credit and linking to the original author and post over on RC).
    Sure thing here is the code:
    Code:
    ################################################################################
    # Ability
    ################################################################################
    # Returns the index of this Pokémon's ability.
      def abilityIndex
        abil=@abilityflag!=nil ? @abilityflag : (@personalID%6)
        return abil
      end
    
    # Returns the ID of this Pokemon's ability.
      def ability
        abil=abilityIndex
        dexdata=pbOpenDexData
          pbDexDataOffset(dexdata,@species,2)
          ret1=dexdata.fgetw
          ret2=dexdata.fgetw
          pbDexDataOffset(dexdata,@species,40)
          h1=dexdata.fgetw
          h2=dexdata.fgetw
          h3=dexdata.fgetw
          h4=dexdata.fgetw
        dexdata.close
        ret=ret1
        if abil==2
          return h1 if h1>0
          abil=(@personalID&1)
        elsif abil==3
          return h2 if h2>0
          abil=(@personalID&1)
        elsif abil==4
          return h3 if h3>0
          abil=(@personalID&1)
        elsif abil==5
          return h4 if h4>0
          abil=(@personalID&1)
        end
        if abil==1
          ret=ret2
          ret=ret1 if ret2==0
        end
        return ret
      end
    
     # Returns whether this Pokémon has a particular ability.
      def hasAbility?(value=0)
        if value==0
          return self.ability>0
        else
          if value.is_a?(String) || value.is_a?(Symbol)
            value=getID(PBAbilities,value)
          end
          return self.ability==value
        end
        return false
      end
      
    # Sets this Pokémon's ability to a particular ability (if possible).
      def setAbility(value)
        @abilityflag=value
      end
    
      def hasHiddenAbility?
        abil=abilityIndex
        return abil!=nil && abil>=2
      end
    
    # Returns the list of abilities this Pokémon can have.
      def getAbilityList
        abils=[]; ret=[[],[]]
        dexdata=pbOpenDexData
        pbDexDataOffset(dexdata,@species,2)
        abils.push(dexdata.fgetw)
        abils.push(dexdata.fgetw)
        pbDexDataOffset(dexdata,@species,40)
        abils.push(dexdata.fgetw)
        abils.push(dexdata.fgetw)
        abils.push(dexdata.fgetw)
        abils.push(dexdata.fgetw)
        dexdata.close
        for i in 0...abils.length
          next if !abils[i] || abils[i]<=0
          ret[0].push(abils[i]); ret[1].push(i)
        end
        return ret
      end
    As for the second block of code it should be the same as indicated the RC post you'll also find the installation steps there just change the first block of code with this one . All the credits goes to Michael from Relic Castle and Marcello (Reborn team).
     
    Last edited:

    Maruno

    Lead Dev of Pokémon Essentials
    5,285
    Posts
    16
    Years
  • The trouble with scripts like this is that they take a blunderbuss approach to installation. "Replace all this code with mine" despite it being unnecessary to replace most of these methods and it actually removing def hasAbility? in the process. Also, it was made in an older version of Essentials and then just not updated (as you can tell by its use of fgetb which Essentials stopped using for abilities in v16, and by the method I just mentioned being omitted).

    Code:
      def abilityIndex
        abil=@abilityflag!=nil ? @abilityflag : (@personalID&[COLOR="Red"]6[/COLOR])
        return abil
      end
    That's all you needed to change. Just that one digit. You don't need to change the debug code at all. Although, to be fair, that makes each hidden ability have 1/6 chance of appearing, and the chances of any unused hidden ability slots is distributed to the two regular abilities (so if you has one hidden ability, it would have 1/6 chance and each of the two regular abilities would have 5/12 chance each so they're not all equally probable). You could fill in hidden ability slots with copies of an ability to alter these probabilities, I guess.

    I am of course assuming you're using the latest version of Essentials.
     
    38
    Posts
    9
    Years
    • Seen Apr 20, 2024
    Yes, I'm using the latest Essentials. I had to check a clean copy of Essentials that's where I saw fgetw because that seems the only thing that's changed. The thing is I was checking Reborn script and it was almost identical to the script posted by Michael except it used dexdata,@species,29 instead of dexdata,@species,2 and when I changed %3 to %6 in Reborn it worked but not in my game that's what confused me the most and led me to think that I had to change dexdata,@species,2. But Reborn probably uses an older version of Essentials that's why it had fgetb. I admit that didn't understand the script fully but I tried to look at it logically like why is this different than that etc... so I was changing small details left and right until I changed fgetb and it finally worked.
    Also thanks for explaining the abilities probabilities, I'll use your suggestion for filling empty slots.
    I also added hasAbility? in the script I posted, thanks for pointing it out.
     
    Last edited:
    Back
    Top