Added a non-RNG, PID-preserving way to modify pokemon nature.
(wip) Preserve shiny value when changing nature. (WIP) Preserve shiny value. (WIP) Preserve nature. (WIP) Removed some debugging statements. (WIP) Removed more debugging statements. (WIP) Nature changing now supports Unown.
This commit is contained in:
parent
7d420b22e8
commit
e9d01b4808
@ -181,6 +181,7 @@
|
||||
#define MON_DATA_SPEED2 86
|
||||
#define MON_DATA_SPATK2 87
|
||||
#define MON_DATA_SPDEF2 88
|
||||
#define MON_DATA_NATURE 89
|
||||
|
||||
// Ribbon IDs used by TV and Pokénav
|
||||
#define CHAMPION_RIBBON 0
|
||||
|
||||
@ -3980,6 +3980,9 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
|
||||
| (substruct3->worldRibbon << 26);
|
||||
}
|
||||
break;
|
||||
case MON_DATA_NATURE:
|
||||
return boxMon->personality % 25;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -4032,6 +4035,10 @@ void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg)
|
||||
break;
|
||||
case MON_DATA_SPECIES2:
|
||||
break;
|
||||
case MON_DATA_NATURE: // Calculate stats after settings
|
||||
SetBoxMonData(&mon->box, field, data);
|
||||
CalculateMonStats(mon);
|
||||
break;
|
||||
default:
|
||||
SetBoxMonData(&mon->box, field, data);
|
||||
break;
|
||||
@ -4298,6 +4305,81 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
|
||||
substruct3->spDefenseIV = (ivs >> 25) & MAX_IV_MASK;
|
||||
break;
|
||||
}
|
||||
case MON_DATA_NATURE:
|
||||
{
|
||||
u32 pid = boxMon->personality;
|
||||
u32 otId = boxMon->otId;
|
||||
s8 diff = (data[0] % 25) - (pid % 25); // difference between new nature and current nature, [-24,24]
|
||||
bool8 preserveShiny = FALSE;
|
||||
bool8 preserveLetter = FALSE;
|
||||
u16 shinyValue = HIHALF(pid) ^ LOHALF(pid);
|
||||
s32 tweak;
|
||||
u32 pidTemp;
|
||||
// See https://bulbapedia.bulbagarden.net/wiki/Personality_value#Nature
|
||||
// Goal here is to preserve as much of the PID as possible
|
||||
// To preserve gender & substruct order, we add/subtract multiples of 5376 that is 0 % 256, 0 % 24, 1 % 25
|
||||
// i.e, to increase the nature by n % 25, we add n*5376 % 19200 (LCM of 24, 25, 256) to the pid
|
||||
// Ability number is determined by parity and so adding multiples of 5376 preserves it
|
||||
// TODO: For genderless pokemon, 576/600 can be used instead of 5376/19200
|
||||
if (diff == 0) // No change
|
||||
break;
|
||||
else if (diff < 0)
|
||||
diff = 25+diff;
|
||||
tweak = (diff*5376) % 19200;
|
||||
pidTemp = pid + tweak;
|
||||
// If the pokemon is shiny or if changing the PID would make it shiny, preserve its shiny value
|
||||
if (IsShinyOtIdPersonality(otId, pid) || IsShinyOtIdPersonality(otId, pidTemp))
|
||||
preserveShiny = TRUE;
|
||||
if (substruct0->species == SPECIES_UNOWN) // Preserve Unown letter
|
||||
preserveLetter = TRUE;
|
||||
if (preserveShiny && preserveLetter) { // honestly though, how many shiny Unown are out there ?
|
||||
while (pidTemp > pid) {
|
||||
if ((HIHALF(pidTemp) ^ LOHALF(pidTemp) ^ shinyValue) < SHINY_ODDS)
|
||||
if (GET_UNOWN_LETTER(pidTemp) == GET_UNOWN_LETTER(pid))
|
||||
break;
|
||||
pidTemp += 19200;
|
||||
}
|
||||
} else if (preserveShiny) {
|
||||
while (pidTemp > pid) {
|
||||
if ((HIHALF(pidTemp) ^ LOHALF(pidTemp) ^ shinyValue) < SHINY_ODDS)
|
||||
break;
|
||||
pidTemp += 19200;
|
||||
}
|
||||
} else if (preserveLetter) {
|
||||
while (pidTemp > pid) {
|
||||
if (GET_UNOWN_LETTER(pidTemp) == GET_UNOWN_LETTER(pid))
|
||||
break;
|
||||
pidTemp += 19200;
|
||||
}
|
||||
}
|
||||
if (pidTemp < pid) { // overflow; search backwards
|
||||
tweak -= 19200;
|
||||
pidTemp = pid + tweak;
|
||||
if (preserveShiny && preserveLetter) {
|
||||
while (pidTemp < pid) {
|
||||
if ((HIHALF(pidTemp) ^ LOHALF(pidTemp) ^ shinyValue) < SHINY_ODDS)
|
||||
if (GET_UNOWN_LETTER(pidTemp) == GET_UNOWN_LETTER(pid))
|
||||
break;
|
||||
pidTemp -= 19200;
|
||||
}
|
||||
} else if (preserveShiny) {
|
||||
while (pidTemp < pid) {
|
||||
if ((HIHALF(pidTemp) ^ LOHALF(pidTemp) ^ shinyValue) < SHINY_ODDS)
|
||||
break;
|
||||
pidTemp -= 19200;
|
||||
}
|
||||
} else if (preserveLetter) {
|
||||
while (pidTemp < pid) {
|
||||
if (GET_UNOWN_LETTER(pidTemp) == GET_UNOWN_LETTER(pid))
|
||||
break;
|
||||
pidTemp -= 19200;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pid % 24 == pidTemp % 24 || pid % 256 == pidTemp % 256)
|
||||
boxMon->personality = pidTemp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -4878,7 +4960,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
temp2 = itemEffect[itemEffectParam];
|
||||
dataSigned = GetMonData(mon, sGetMonDataEVConstants[temp1], NULL);
|
||||
evChange = temp2;
|
||||
|
||||
|
||||
if (evChange > 0) // Increasing EV (HP or Atk)
|
||||
{
|
||||
// Has EV increase limit already been reached?
|
||||
@ -4976,7 +5058,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
{
|
||||
if (!usedByAI)
|
||||
{
|
||||
// Restore HP
|
||||
// Restore HP
|
||||
dataUnsigned = GetMonData(mon, MON_DATA_HP, NULL) + dataUnsigned;
|
||||
if (dataUnsigned > GetMonData(mon, MON_DATA_MAX_HP, NULL))
|
||||
dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL);
|
||||
@ -5055,7 +5137,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex);
|
||||
}
|
||||
SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned);
|
||||
|
||||
|
||||
// Heal battler PP too (if applicable)
|
||||
if (gMain.inBattle
|
||||
&& battlerId != MAX_BATTLERS_COUNT && !(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED)
|
||||
@ -5092,7 +5174,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
|
||||
case 5:
|
||||
effectFlags = itemEffect[i];
|
||||
temp1 = 0;
|
||||
|
||||
|
||||
// Loop through and try each of the ITEM5 effects
|
||||
while (effectFlags != 0)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user