• 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?".
  • Forum moderator applications are now open! Click here for details.
  • 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.

[Other✓] I want to add more types to hidden power

853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
can I get some help on figuring out the hidden power calculation, pretty much how it decides the type of the move. this is the current function,
and the values for the types are 0x0-0x11. (fixed typo, type wasn't 0x13 that was number of types in my rom)
any new types would have to be added at 0x17 on.
Code:
[SPOILER]static void atkC1_hiddenpowercalc(void)
{
    s32 powerBits, typeBits;

    powerBits = ((gBattleMons[gBattlerAttacker].hpIV & 2) >> 1)
              | ((gBattleMons[gBattlerAttacker].attackIV & 2) << 0)
              | ((gBattleMons[gBattlerAttacker].defenseIV & 2) << 1)
              | ((gBattleMons[gBattlerAttacker].speedIV & 2) << 2)
              | ((gBattleMons[gBattlerAttacker].spAttackIV & 2) << 3)
              | ((gBattleMons[gBattlerAttacker].spDefenseIV & 2) << 4);
    typeBits  = ((gBattleMons[gBattlerAttacker].hpIV & 1) << 0)
              | ((gBattleMons[gBattlerAttacker].attackIV & 1) << 1)
              | ((gBattleMons[gBattlerAttacker].defenseIV & 1) << 2)
              | ((gBattleMons[gBattlerAttacker].speedIV & 1) << 3)
              | ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4)
              | ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5);
    gDynamicBasePower = (40 * powerBits) / 63 + 30;
    gBattleStruct->dynamicMoveType = (15 * typeBits) / 63 + 1;
    if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
        ++gBattleStruct->dynamicMoveType;
    gBattleStruct->dynamicMoveType |= 0xC0;
    ++gBattlescriptCurrInstr;[/SPOILER]
I think the most important part is here, but I don't know bitwise, to try calculating the outcomes.
gBattleStruct->dynamicMoveType = (15 * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
++gBattleStruct->dynamicMoveType;
gBattleStruct->dynamicMoveType |= 0xC0;
 
Last edited:
1,591
Posts
10
Years
  • Age 30
  • Seen Mar 20, 2024
You're on the right track, the important parts are dynamicMoveType = (15 * typeBits) / 63 + 1; and
Code:
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType++;
The 15 here is what determines how many possible types you can have. The bit shifting lines are taking each IV, determining whether it's odd or even, and then combining the results into a number between 0 and 63 (this is the maximum value you can store in six bits; 0b111111 = 63). So as an example, if you've got all odd IVs, you get:
15*63/63 + 1 = 15 + 1 = 16

TYPE_MYSTERY is 9, so you add another 1 to that as 16 > 9, and get 17 which is TYPE_DARK. The first +1 ensures that normal type hidden power can't exist, and the second +1 does the same for TYPE_MYSTERY.

So if you wanted three more hidden power types, you'd replace the the 15 with 18, and that would give you 18 possible hidden power types:
18*63/63 + 1 = 19, (and + 1 from the >= TYPE_MYSTERY statement = 20)

This will also change the IV combinations needed to get all the existing hidden power types.
 
853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
You're on the right track, the important parts are dynamicMoveType = (15 * typeBits) / 63 + 1; and
Code:
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType++;
The 15 here is what determines how many possible types you can have. The bit shifting lines are taking each IV, determining whether it's odd or even, and then combining the results into a number between 0 and 63 (this is the maximum value you can store in six bits; 0b111111 = 63). So as an example, if you've got all odd IVs, you get:
15*63/63 + 1 = 15 + 1 = 16

TYPE_MYSTERY is 9, so you add another 1 to that as 16 > 9, and get 17 which is TYPE_DARK. The first +1 ensures that normal type hidden power can't exist, and the second +1 does the same for TYPE_MYSTERY.

So if you wanted three more hidden power types, you'd replace the the 15 with 18, and that would give you 18 possible hidden power types:
18*63/63 + 1 = 19, (and + 1 from the >= TYPE_MYSTERY statement = 20)

This will also change the IV combinations needed to get all the existing hidden power types.

MIND Blown!! Thank you so much, and I never realized what those "++" signs everywhere meant until you explained that.

Alright since I've only added one type I'll go ahead and change that 15 to 16 so I can have the option of a fairy type hidden power.

I was close, I was able to figure that the max was 63, but I was reading it wrong and didn't cancel out, instead dividing by 64, which gave me 1 type less, i.e 14.
Which stumped me.

Thanks again for helping out so quick.


Edit:
Another thought/question, is setting it to 16 enough to get fairy type, or would I need to do something else/go higher, to get over the non-battle types?
Since fairy is technically 23.
 
Last edited:
1,591
Posts
10
Years
  • Age 30
  • Seen Mar 20, 2024
MIND Blown!! Thank you so much, and I never realized what those "++" signs everywhere meant until you explained that.

Alright since I've only added one type I'll go ahead and change that 15 to 16 so I can have the option of a fairy type hidden power.

I was close, I was able to figure that the max was 63, but I was reading it wrong and didn't cancel out, instead dividing by 64, which gave me 1 type less, i.e 14.
Which stumped me.

Thanks again for helping out so quick.


Edit:
Another thought/question, is setting it to 16 enough to get fairy type, or would I need to do something else/go higher, to get over the non-battle types?
Since fairy is technically 23.
No problem! "x++" is usually short hand for "x = x + 1", but can also mean other things if it's operating on a pointer.

I think you can set it to 16, then define Fairy to be type 18 and increase NUMBER_OF_MON_TYPES to 19. In pokeemerald at least it looks like the non-battle types are handled using NUMBER_OF_MON_TYPES so you don't need to worry about them. If that's not the case and fairy has to come after those types, then you'll need some extra code to skip over them. Something like this would work:
Code:
    if (gBattleStruct->dynamicMoveType >= [first non-battle type] && gBattleStruct->dynamicMoveType <= [last non-battle type])
        gBattleStruct->dynamicMoveType = TYPE_FAIRY;
One issue with this though is hidden power fairy will be more common than the other types.
 
853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
No problem! "x++" is usually short hand for "x = x + 1", but can also mean other things if it's operating on a pointer.

I think you can set it to 16, then define Fairy to be type 18 and increase NUMBER_OF_MON_TYPES to 19. In pokeemerald at least it looks like the non-battle types are handled using NUMBER_OF_MON_TYPES so you don't need to worry about them. If that's not the case and fairy has to come after those types, then you'll need some extra code to skip over them. Something like this would work:
Code:
    if (gBattleStruct->dynamicMoveType >= [first non-battle type] && gBattleStruct->dynamicMoveType <= [last non-battle type])
        gBattleStruct->dynamicMoveType = TYPE_FAIRY;
One issue with this though is hidden power fairy will be more common than the other types.

Thanks, and interesting, side note if I want to do plus 2, is that 3+ or 4+ i.e "+++"

the type thing is a little confusing, pretty much the number of types field already excludes the non-battle types, so while fairy is 0x17 the number of abilities is 0x13.

Spoiler:


Once I figured how to add more I thought I may need to know how that would effect the odds of each type or what the conditions were.
Code:
    if (gBattleStruct->dynamicMoveType >= [first non-battle type] && gBattleStruct->dynamicMoveType <= [last non-battle type])
        gBattleStruct->dynamicMoveType = TYPE_FAIRY;

but as far as getting over the types, I was thinking doing what they did with mystery, like use >= dark type add 5
or maybe I could do something else, like remove the one of the plus 1's to remove the normal or mystery exclusion and then set one of the excluded types to be fairy instead.

I saw that used in another function,
something like

if (gBattleStruct->dynamicMoveType == TYPE_NORMAL)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;

I think the latter would be the easiest, can you tell me what I have to remove to get normal back in the calculations?
 
1,591
Posts
10
Years
  • Age 30
  • Seen Mar 20, 2024
Thanks, and interesting, side note if I want to do plus 2, is that 3+ or 4+ i.e "+++"

the type thing is a little confusing, pretty much the number of types field already excludes the non-battle types, so while fairy is 0x17 the number of abilities is 0x13.




Once I figured how to add more I thought I may need to know how that would effect the odds of each type or what the conditions were.
Code:
    if (gBattleStruct->dynamicMoveType >= [first non-battle type] && gBattleStruct->dynamicMoveType <= [last non-battle type])
        gBattleStruct->dynamicMoveType = TYPE_FAIRY;

but as far as getting over the types, I was thinking doing what they did with mystery, like use >= dark type add 5
or maybe I could do something else, like remove the one of the plus 1's to remove the normal or mystery exclusion and then set one of the excluded types to be fairy instead.

I saw that used in another function,
something like

if (gBattleStruct->dynamicMoveType == TYPE_NORMAL)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;

I think the latter would be the easiest, can you tell me what I have to remove to get normal back in the calculations?

There's no short hand for +2 or anything higher, +1 is a special case just because it's so widely used in programming (mostly in counters - think for loops, timers, etc.). You can do x-- though, which is the same as x = x -1.
Are you editing the CFRU by any chance? In the pokeemerald expansions fairy type is just added right after dark type, but I guess skipping the non-battle types would be necessary for the CFRU.

I think replacing the TYPE_MYSTERY check for TYPE_FAIRY is a very good solution, nice and simple. You could just replace:
Code:
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
++gBattleStruct->dynamicMoveType;
With:
Code:
if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;

If you want normal type hidden power to be a thing, remove the +1 in the type equation. i.e.
Code:
gBattleStruct->dynamicMoveType = (15 * typeBits) / 63;
The plus one ensures that this equation can't equal zero (which would be normal type), so removing it will give a Pokemon with all zero IVs HP normal.
 
853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
There's no short hand for +2 or anything higher, +1 is a special case just because it's so widely used in programming (mostly in counters - think for loops, timers, etc.). You can do x-- though, which is the same as x = x -1.
Are you editing the CFRU by any chance? In the pokeemerald expansions fairy type is just added right after dark type, but I guess skipping the non-battle types would be necessary for the CFRU.

I think replacing the TYPE_MYSTERY check for TYPE_FAIRY is a very good solution, nice and simple. You could just replace:
Code:
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
++gBattleStruct->dynamicMoveType;
With:
Code:
if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;

If you want normal type hidden power to be a thing, remove the +1 in the type equation. i.e.
Code:
gBattleStruct->dynamicMoveType = (15 * typeBits) / 63;
The plus one ensures that this equation can't equal zero (which would be normal type), so removing it will give a Pokemon with all zero IVs HP normal.

I see thanks, think I mostly understand the formula now, awesome. I'll go ahead and make that mystery = fairy change, (I'll leave normal out, since a 0 IV mon isn't very desireable)
and no I'm not using cfru, I switched to decomp a little while ago, and I'm working on an expanded version of pokefirered.

by porting things from pokeemerald.

its essentially the decomp cfru a lot of people were wanting, but also just my own base, since I have several other things added/working on adding.

Good to know about the plus 1 thing, gotta go back and change some code now.

Thanks again.


huh now that I think about it I could probably use the same trick for adjusting odds of each type, if I ever figure/take the time to break down everything that goes into it. Cool.
 
Last edited:
853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
I might be mistaken, but won't this basically replace Hidden Power Dark with Fairy?

My thinking is that before the numbers worked like this:
Code:
 i | i + 1
 9 | TYPE_FIRE (10)
10 | TYPE_WATER (11)
11 | TYPE_GRASS (12)
12 | TYPE_ELECTRIC (13)
13 | TYPE_PSYCHIC (14)
14 | TYPE_ICE (15)
15 | TYPE_DRAGON (16)
16 | TYPE_DARK (17)
But now that you've replaced ++ (i.e. + 1) with turning TYPE_MYSTERY (8) into TYPE_FAIRY (18) you get this:
Code:
 i | i == 8 ? 18 : i
 9 | TYPE_FAIRY (18)
10 | TYPE_FIRE (10)
11 | TYPE_WATER (11)
12 | TYPE_GRASS (12)
13 | TYPE_ELECTRIC (13)
14 | TYPE_PSYCHIC (14)
15 | TYPE_ICE (15)
16 | TYPE_DRAGON (16)

I think you both need to generate a number that's 1 bigger and remap TYPE_MYSTERY to TYPE_FAIRY to have all the types. This might actually be working on your thread? I saw you and Buffel Saft made some changes to how dynamicMoveType was calculated.


Thanks for the response mgriffin, I didn't realize that but, sounds plausible.

I'm basically shooting in the dark since I didn't understand anything of bitwise before I started on this.

Ok, so the default adds a second plus 1, in the case dynamic type is greater or equal to type mystery.

I think I see what you're saying in that removing the plus 1 puts mystery back into the fold, but its also adding a type to the list that wasn't there before, creating a net loss.
(since the number of possible types was already maxed out before adding mystery.)

So I think it'll be ok if I just change the 15 to 16 as well removing the plus 1. That should balance I guess.
removing the plus 1 adds a type back into the pool, while raising the value to 16 increases the total number of type outcomes by 1.

So if I'm correct on this the real solution should be this.

gBattleStruct->dynamicMoveType = (16 * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;


edit, lol so I check the code in my rom, and I already had it set to 16, I just forgot that part needed to be done, with everything else I was working on. *faceplam*
thanks again for catching that. :)
 
Last edited:
1,591
Posts
10
Years
  • Age 30
  • Seen Mar 20, 2024
Thanks for the response mgriffin, I didn't realize that but, sounds plausible.
So if I'm correct on this the real solution should be this.

gBattleStruct->dynamicMoveType = (16 * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;


edit, lol so I check the code in my rom, and I already had it set to 16, I just forgot that part needed to be done, with everything else I was working on. *faceplam*
thanks again for catching that. :)
Yep that's correct!

Guess I should give you a quick explanation of what those bitshifts are doing too:
<< and >> are the left shift and right shift operators; they take a value and shift all of its bits by the number of bits you specify. E.g. 0b01 << 1 = 0b10 = 2 in decimal.
This code gets the IVs of a Pokemon, performs an AND operation on them, shifts the result, and then ORs them all together:
Code:
...
| ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4)
| ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5)
As an example, let's say a mon has a 31 IV in special attack and 30 in special defense (we'll ignore the other stats for simplicity). First you have (31 & 1) << 4
The AND in binary looks like this:
0b00011111 &
0b00000001
It compares the bits in the same positions in both numbers, and if both are set (1), the result will also have a 1 in that position. So 31 & 1 = 0b00000001, as only the last bit is set in both. Then, you left shift that four times, which gives you
0b00010000.
Then you have (30 & 1) << 5, which is 0b00011110 & 0b00000001 = 0b00000000 as none of the bits are set in the same positions in both numbers. Left shifting this effectively does nothing as there's nothing to shift, so the result is also 0.

Finally you have 0b00010000 OR 0b00000000. This is the same idea as AND, but bits in the result will be set if they're set in either value, instead of in both. So 0b00010000 OR 0b00000000 = 0b00010000.

If you had 0b00010000 OR 0b00000001 instead, you'd get 0b00010001.

So this code:
Code:
    typeBits  = ((gBattleMons[gBattlerAttacker].hpIV & 1) << 0)
              | ((gBattleMons[gBattlerAttacker].attackIV & 1) << 1)
              | ((gBattleMons[gBattlerAttacker].defenseIV & 1) << 2)
              | ((gBattleMons[gBattlerAttacker].speedIV & 1) << 3)
              | ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4)
              | ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5)
Takes the last bit of each IV and "sticks them together" into one number. As one last example, let's say we have a mon with the following IVs: 31/30/31/31/30/31 (in the same order as the code above). You'd get:
0b00000001
| 0b00000000
| 0b00001000
| 0b00010000
| 0b00000000
| 0b00100000
= 0b00101101 = 45, which you can put into the type calc equation.

Hope that makes at least some sense!
 
853
Posts
3
Years
  • Age 33
  • Seen Nov 9, 2023
Yep that's correct!

Guess I should give you a quick explanation of what those bitshifts are doing too:
<< and >> are the left shift and right shift operators; they take a value and shift all of its bits by the number of bits you specify. E.g. 0b01 << 1 = 0b10 = 2 in decimal.
This code gets the IVs of a Pokemon, performs an AND operation on them, shifts the result, and then ORs them all together:
Code:
...
| ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4)
| ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5)
As an example, let's say a mon has a 31 IV in special attack and 30 in special defense (we'll ignore the other stats for simplicity). First you have (31 & 1) << 4
The AND in binary looks like this:
0b00011111 &
0b00000001
It compares the bits in the same positions in both numbers, and if both are set (1), the result will also have a 1 in that position. So 31 & 1 = 0b00000001, as only the last bit is set in both. Then, you left shift that four times, which gives you
0b00010000.
Then you have (30 & 1) << 5, which is 0b00011110 & 0b00000001 = 0b00000000 as none of the bits are set in the same positions in both numbers. Left shifting this effectively does nothing as there's nothing to shift, so the result is also 0.

Finally you have 0b00010000 OR 0b00000000. This is the same idea as AND, but bits in the result will be set if they're set in either value, instead of in both. So 0b00010000 OR 0b00000000 = 0b00010000.

If you had 0b00010000 OR 0b00000001 instead, you'd get 0b00010001.

So this code:
Code:
    typeBits  = ((gBattleMons[gBattlerAttacker].hpIV & 1) << 0)
              | ((gBattleMons[gBattlerAttacker].attackIV & 1) << 1)
              | ((gBattleMons[gBattlerAttacker].defenseIV & 1) << 2)
              | ((gBattleMons[gBattlerAttacker].speedIV & 1) << 3)
              | ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4)
              | ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5)
Takes the last bit of each IV and "sticks them together" into one number.
Hope that makes at least some sense!

*Whistles* wow, ok very cool. thanks for the quick bitwise explanation, and yeah I completely understand that. Well said. :)
 
Back
Top