Other I want to add more types to hidden power

Started by Meister_anon~Master_o f_None May 8th, 2021 4:09 PM
  • 361 views
  • 10 replies
Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
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.
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;
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;
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Buffel Saft

Male
Seen 57 Minutes Ago
Posted 17 Hours Ago
1,041 posts
7.8 Years
You're on the right track, the important parts are
dynamicMoveType = (15 * typeBits) / 63 + 1;
and
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.
Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
You're on the right track, the important parts are
dynamicMoveType = (15 * typeBits) / 63 + 1;
and
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.
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
well either way that narrowed it down so I'm sure its one of those.

the value I need is either 16 or 21.
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Buffel Saft

Male
Seen 57 Minutes Ago
Posted 17 Hours Ago
1,041 posts
7.8 Years
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:
    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.
Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
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:
    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:
// Pokemon types type order found in list_menu.c
#define TYPE_NORMAL 0x00
#define TYPE_FIGHTING 0x01
#define TYPE_FLYING 0x02
#define TYPE_POISON 0x03
#define TYPE_GROUND 0x04
#define TYPE_ROCK 0x05
#define TYPE_BUG 0x06
#define TYPE_GHOST 0x07
#define TYPE_STEEL 0x08
#define TYPE_MYSTERY 0x09
#define TYPE_FIRE 0x0a
#define TYPE_WATER 0x0b
#define TYPE_GRASS 0x0c
#define TYPE_ELECTRIC 0x0d
#define TYPE_PSYCHIC 0x0e
#define TYPE_ICE 0x0f
#define TYPE_DRAGON 0x10
#define TYPE_DARK 0x11
#define TYPE_FAIRY 0x17 //fairy addition
#define NUMBER_OF_MON_TYPES 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.
    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?
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Buffel Saft

Male
Seen 57 Minutes Ago
Posted 17 Hours Ago
1,041 posts
7.8 Years
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.
    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:
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
++gBattleStruct->dynamicMoveType;
With:
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.
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.
Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
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:
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
++gBattleStruct->dynamicMoveType;
With:
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.
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.
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
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:
 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:
 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. :)
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Buffel Saft

Male
Seen 57 Minutes Ago
Posted 17 Hours Ago
1,041 posts
7.8 Years
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:
...
| ((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:
    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!
Seen 12 Hours Ago
Posted 22 Hours Ago
753 posts
172 Days
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:
...
| ((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:
    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. :)
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA