From 3b9b24312a3b74d7cb7ad00f5371d7b01b86640a Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sun, 30 Mar 2025 13:31:27 +0200 Subject: [PATCH 1/3] Fixes Tera Type not being carried over to during form change / evolution --- src/pokemon.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/pokemon.c b/src/pokemon.c index ef90f10ba3..a2d4ed3ab9 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1198,6 +1198,9 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value); SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); + u32 teraType = (boxMon->personality & 0x1) == 0 ? gSpeciesInfo[species].types[0] : gSpeciesInfo[species].types[1]; + SetBoxMonData(boxMon, MON_DATA_TERA_TYPE, &teraType); + if (fixedIV < USE_RANDOM_IVS) { SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV); @@ -2789,18 +2792,9 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) break; case MON_DATA_TERA_TYPE: if (gSpeciesInfo[substruct0->species].forceTeraType) - { retVal = gSpeciesInfo[substruct0->species].forceTeraType; - } - else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality - { - const u8 *types = gSpeciesInfo[substruct0->species].types; - retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; - } else - { retVal = substruct0->teraType; - } break; case MON_DATA_EVOLUTION_TRACKER: evoTracker.asField.a = substruct1->evolutionTracker1; From d767211c4aa0802eac5e46885558ea692bd3e71e Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Mon, 31 Mar 2025 14:49:40 +0200 Subject: [PATCH 2/3] helper function to get the species type based on personality --- include/pokemon.h | 1 + src/debug.c | 4 ++-- src/pokemon.c | 6 ++++++ src/script_pokemon_util.c | 4 ++-- test/pokemon.c | 2 ++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/pokemon.h b/include/pokemon.h index 1326e81329..574eafce0e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -809,5 +809,6 @@ u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler); uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier); u32 GetRegionalFormByRegion(u32 species, u32 region); bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion); +u32 GetTeraTypeFromPersonality(struct Pokemon *mon); #endif // GUARD_POKEMON_H diff --git a/src/debug.c b/src/debug.c index 8a20e6b2b1..4443e004d8 100644 --- a/src/debug.c +++ b/src/debug.c @@ -3416,8 +3416,8 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu SetMonData(&mon, MON_DATA_DYNAMAX_LEVEL, &dmaxLevel); // tera type - if (teraType >= NUMBER_OF_MON_TYPES) - teraType = TYPE_NONE; + if (teraType == TYPE_NONE || teraType == TYPE_MYSTERY || teraType >= NUMBER_OF_MON_TYPES) + teraType = GetTeraTypeFromPersonality(&mon); SetMonData(&mon, MON_DATA_TERA_TYPE, &teraType); //IVs diff --git a/src/pokemon.c b/src/pokemon.c index a2d4ed3ab9..2e4ea13f2e 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -7057,3 +7057,9 @@ bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion) } return FALSE; } + +u32 GetTeraTypeFromPersonality(struct Pokemon *mon) +{ + const u8 *types = gSpeciesInfo[GetMonData(mon, MON_DATA_SPECIES)].types; + return (GetMonData(mon, MON_DATA_PERSONALITY) & 0x1) == 0 ? types[0] : types[1]; +} diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 77ce6411db..7288870441 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -373,8 +373,8 @@ static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u SetMonData(&mon, MON_DATA_DYNAMAX_LEVEL, &dmaxLevel); // tera type - if (teraType >= NUMBER_OF_MON_TYPES) - teraType = TYPE_NONE; + if (teraType == TYPE_NONE || teraType == TYPE_MYSTERY || teraType >= NUMBER_OF_MON_TYPES) + teraType = GetTeraTypeFromPersonality(&mon); SetMonData(&mon, MON_DATA_TERA_TYPE, &teraType); // EV and IV diff --git a/test/pokemon.c b/test/pokemon.c index 97e034dc82..16aadee798 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -57,6 +57,8 @@ TEST("Terastallization type is reset to the default types when setting Tera Type CreateMon(&mon, SPECIES_PIDGEY, 100, 0, FALSE, 0, OT_ID_PRESET, 0); SetMonData(&mon, MON_DATA_TERA_TYPE, &teraType); EXPECT_EQ(teraType, GetMonData(&mon, MON_DATA_TERA_TYPE)); + if (typeNone == TYPE_NONE) + typeNone = GetTeraTypeFromPersonality(&mon); SetMonData(&mon, MON_DATA_TERA_TYPE, &typeNone); typeNone = GetMonData(&mon, MON_DATA_TERA_TYPE); EXPECT(typeNone == gSpeciesInfo[SPECIES_PIDGEY].types[0] From abfabb9699827b8a4f98c8c733c4d3930b8605b7 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Tue, 1 Apr 2025 15:57:04 +0200 Subject: [PATCH 3/3] revert fallback --- src/pokemon.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pokemon.c b/src/pokemon.c index 2e4ea13f2e..789935c654 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2792,9 +2792,18 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) break; case MON_DATA_TERA_TYPE: if (gSpeciesInfo[substruct0->species].forceTeraType) + { retVal = gSpeciesInfo[substruct0->species].forceTeraType; + } + else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality + { + const u8 *types = gSpeciesInfo[substruct0->species].types; + retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; + } else + { retVal = substruct0->teraType; + } break; case MON_DATA_EVOLUTION_TRACKER: evoTracker.asField.a = substruct1->evolutionTracker1;