From 41751451f689218fc83fe2ff11e4f32d36d68934 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Thu, 9 Oct 2025 15:26:26 +0200 Subject: [PATCH] Fix fusion pokemon aquiring illegal movesets (#7896) --- include/pokemon.h | 20 ++- src/data/pokemon/form_change_table_pointers.h | 19 +++ src/data/pokemon/form_change_tables.h | 12 +- src/party_menu.c | 120 ++++++++++++++++-- 4 files changed, 151 insertions(+), 20 deletions(-) diff --git a/include/pokemon.h b/include/pokemon.h index 1e31c425b6..f58ebbba1a 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -631,6 +631,13 @@ struct FormChange u16 param3; }; +enum FusionExtraMoveHandling +{ + FORGET_EXTRA_MOVES, + SWAP_EXTRA_MOVES_KYUREM_WHITE, + SWAP_EXTRA_MOVES_KYUREM_BLACK +}; + struct Fusion { u16 fusionStorageIndex; @@ -639,11 +646,22 @@ struct Fusion u16 targetSpecies2; u16 fusingIntoMon; u16 fusionMove; - u16 unfuseForgetMove; + enum FusionExtraMoveHandling extraMoveHandling; }; extern const struct Fusion *const gFusionTablePointers[NUM_SPECIES]; +#if P_FUSION_FORMS +#if P_FAMILY_KYUREM +#if P_FAMILY_RESHIRAM +extern const u16 gKyurenWhiteSwapMoveTable[][2]; +#endif //P_FAMILY_RESHIRAM +#if P_FAMILY_ZEKROM +extern const u16 gKyurenBlackSwapMoveTable[][2]; +#endif //P_FAMILY_ZEKROM +#endif //P_FAMILY_KYUREM +#endif //P_FUSION_FORMS + #define NUM_UNOWN_FORMS 28 #define GET_UNOWN_LETTER(personality) (( \ diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index ea2cdfd2a2..ad2e6a040d 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -34,3 +34,22 @@ const struct Fusion *const gFusionTablePointers[NUM_SPECIES] = #endif //P_FAMILY_CALYREX #endif //P_FUSION_FORMS }; + +#if P_FUSION_FORMS +#if P_FAMILY_KYUREM +#if P_FAMILY_RESHIRAM +const u16 gKyurenWhiteSwapMoveTable[][2] = +{ + {MOVE_SCARY_FACE, MOVE_FUSION_FLARE}, + {MOVE_GLACIATE, MOVE_ICE_BURN}, +}; +#endif //P_FAMILY_RESHIRAM +#if P_FAMILY_ZEKROM +const u16 gKyurenBlackSwapMoveTable[][2] = +{ + {MOVE_SCARY_FACE, MOVE_FUSION_BOLT}, + {MOVE_GLACIATE, MOVE_FREEZE_SHOCK}, +}; +#endif //P_FAMILY_ZEKROM +#endif //P_FAMILY_KYUREM +#endif //P_FUSION_FORMS diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index ed80ae2178..ad8a7e90ca 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -755,8 +755,8 @@ static const struct FormChange sLandorusFormChangeTable[] = { #if P_FAMILY_KYUREM static const struct Fusion sKyuremFusionTable[] = { - {0, ITEM_DNA_SPLICERS, SPECIES_KYUREM, SPECIES_RESHIRAM, SPECIES_KYUREM_WHITE}, - {0, ITEM_DNA_SPLICERS, SPECIES_KYUREM, SPECIES_ZEKROM, SPECIES_KYUREM_BLACK}, + {0, ITEM_DNA_SPLICERS, SPECIES_KYUREM, SPECIES_RESHIRAM, SPECIES_KYUREM_WHITE, MOVE_NONE, SWAP_EXTRA_MOVES_KYUREM_WHITE}, + {0, ITEM_DNA_SPLICERS, SPECIES_KYUREM, SPECIES_ZEKROM, SPECIES_KYUREM_BLACK, MOVE_NONE, SWAP_EXTRA_MOVES_KYUREM_BLACK}, {FUSION_TERMINATOR}, }; #endif //P_FAMILY_KYUREM @@ -998,8 +998,8 @@ static const struct FormChange sMimikyuTotemFormChangeTable[] = { #if P_FAMILY_NECROZMA static const struct Fusion sNecrozmaFusionTable[] = { - {1, ITEM_N_SOLARIZER, SPECIES_NECROZMA, SPECIES_SOLGALEO, SPECIES_NECROZMA_DUSK_MANE, MOVE_SUNSTEEL_STRIKE, MOVE_CONFUSION}, - {2, ITEM_N_LUNARIZER, SPECIES_NECROZMA, SPECIES_LUNALA, SPECIES_NECROZMA_DAWN_WINGS, MOVE_MOONGEIST_BEAM, MOVE_CONFUSION}, + {1, ITEM_N_SOLARIZER, SPECIES_NECROZMA, SPECIES_SOLGALEO, SPECIES_NECROZMA_DUSK_MANE, MOVE_SUNSTEEL_STRIKE, FORGET_EXTRA_MOVES}, + {2, ITEM_N_LUNARIZER, SPECIES_NECROZMA, SPECIES_LUNALA, SPECIES_NECROZMA_DAWN_WINGS, MOVE_MOONGEIST_BEAM, FORGET_EXTRA_MOVES}, {FUSION_TERMINATOR}, }; @@ -1266,8 +1266,8 @@ static const struct FormChange sUrshifuRapidStrikeFormChangeTable[] = { #if P_FAMILY_CALYREX static const struct Fusion sCalyrexFusionTable[] = { - {3, ITEM_REINS_OF_UNITY, SPECIES_CALYREX, SPECIES_GLASTRIER, SPECIES_CALYREX_ICE, MOVE_GLACIAL_LANCE, MOVE_CONFUSION}, - {3, ITEM_REINS_OF_UNITY, SPECIES_CALYREX, SPECIES_SPECTRIER, SPECIES_CALYREX_SHADOW, MOVE_ASTRAL_BARRAGE, MOVE_CONFUSION}, + {3, ITEM_REINS_OF_UNITY, SPECIES_CALYREX, SPECIES_GLASTRIER, SPECIES_CALYREX_ICE, MOVE_GLACIAL_LANCE, FORGET_EXTRA_MOVES}, + {3, ITEM_REINS_OF_UNITY, SPECIES_CALYREX, SPECIES_SPECTRIER, SPECIES_CALYREX_SHADOW, MOVE_ASTRAL_BARRAGE, FORGET_EXTRA_MOVES}, {FUSION_TERMINATOR}, }; #endif //P_FAMILY_CALYREX diff --git a/src/party_menu.c b/src/party_menu.c index e6568c34bf..3b05551cb2 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -6113,13 +6113,14 @@ void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task) #define tAnimWait data[2] #define tNextFunc 3 -#define fusionType data[7] -#define firstFusion data[8] -#define firstFusionSlot data[9] -#define fusionResult data[10] -#define secondFusionSlot data[11] -#define unfuseSecondMon data[12] -#define moveToLearn data[13] +#define fusionType data[6] +#define firstFusion data[7] +#define firstFusionSlot data[8] +#define fusionResult data[9] +#define secondFusionSlot data[10] +#define unfuseSecondMon data[11] +#define moveToLearn data[12] +#define tExtraMoveHandling data[13] #define forgetMove data[14] #define storageIndex data[15] @@ -6254,6 +6255,75 @@ static void RestoreFusionMon(struct Pokemon *mon) } } +static void DeleteInvalidFusionMoves(struct Pokemon *mon, u32 species) +{ + for (u32 i = 0; i < MAX_MON_MOVES; i++) + { + u32 move = GetMonData(mon, MON_DATA_MOVE1 + i); + bool32 toDelete = TRUE; + const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); + for (u32 j = 0; learnset[j].move != LEVEL_UP_MOVE_END;j++) + { + if (learnset[j].move == move) + { + toDelete = FALSE; + break; + } + } + if (!toDelete) + continue; + const u16 *learnset2 = GetSpeciesTeachableLearnset(species); + for (u32 j = 0; learnset2[j] != MOVE_UNAVAILABLE;j++) + { + if (learnset2[j] == move) + { + toDelete = FALSE; + break; + } + } + if (!toDelete) + continue; + const u16 *learnset3 = GetSpeciesEggMoves(species); + for (u32 j = 0; learnset3[j] != MOVE_UNAVAILABLE;j++) + { + if (learnset3[j] == move) + { + toDelete = FALSE; + break; + } + } + if (toDelete) + DeleteMove(mon, move); + } +} + +static void SwapFusionMonMoves(struct Pokemon *mon, const u16 moveTable[][2], u32 mode) +{ + u32 oldMoveIndex, newMoveIndex; + if (mode == FUSE_MON) + { + oldMoveIndex = 0; + newMoveIndex = 1; + } + else //mode == UNFUSE_MON + { + oldMoveIndex = 1; + newMoveIndex = 0; + } + for (u32 i = 0; i < MAX_MON_MOVES; i++) + { + u32 move = GetMonData(mon, MON_DATA_MOVE1 + i); + for (u32 j = 0; j < 2; j++) + { + if (move == moveTable[j][oldMoveIndex]) + { + SetMonData(mon, MON_DATA_MOVE1 + i, &moveTable[j][newMoveIndex]); + SetMonData(mon, MON_DATA_PP1 + i, &gMovesInfo[moveTable[j][newMoveIndex]].pp); + } + } + } + +} static void Task_TryItemUseFusionChange(u8 taskId) { struct Pokemon *mon = &gPlayerParty[gTasks[taskId].firstFusionSlot]; @@ -6345,15 +6415,38 @@ static void Task_TryItemUseFusionChange(u8 taskId) case 6: if (!IsPartyMenuTextPrinterActive()) { - if (gTasks[taskId].moveToLearn != 0) + if (gTasks[taskId].fusionType == FUSE_MON) { - if (gTasks[taskId].fusionType == FUSE_MON) +#if P_FAMILY_KYUREM +#if P_FAMILY_RESHIRAM + if (gTasks[taskId].tExtraMoveHandling == SWAP_EXTRA_MOVES_KYUREM_WHITE) + SwapFusionMonMoves(mon, gKyurenWhiteSwapMoveTable, FUSE_MON); +#endif //P_FAMILY_RESHIRAM +#if P_FAMILY_ZEKROM + if (gTasks[taskId].tExtraMoveHandling == SWAP_EXTRA_MOVES_KYUREM_BLACK) + SwapFusionMonMoves(mon, gKyurenBlackSwapMoveTable, FUSE_MON); +#endif //P_FAMILY_ZEKROM +#endif //P_FAMILY_KYUREM + if (gTasks[taskId].moveToLearn != 0) FormChangeTeachMove(taskId, gTasks[taskId].moveToLearn, gTasks[taskId].firstFusionSlot); - else + } + else //(gTasks[taskId].fusionType == UNFUSE_MON) + { +#if P_FAMILY_KYUREM +#if P_FAMILY_RESHIRAM + if (gTasks[taskId].tExtraMoveHandling == SWAP_EXTRA_MOVES_KYUREM_WHITE) + SwapFusionMonMoves(mon, gKyurenWhiteSwapMoveTable, UNFUSE_MON); +#endif //P_FAMILY_RESHIRAM +#if P_FAMILY_ZEKROM + if (gTasks[taskId].tExtraMoveHandling == SWAP_EXTRA_MOVES_KYUREM_BLACK) + SwapFusionMonMoves(mon, gKyurenBlackSwapMoveTable, UNFUSE_MON); +#endif //P_FAMILY_ZEKROM +#endif //P_FAMILY_KYUREM + if ( gTasks[taskId].tExtraMoveHandling == FORGET_EXTRA_MOVES) { - DeleteMove(mon, gTasks[taskId].forgetMove); + DeleteInvalidFusionMoves(mon, gTasks[taskId].fusionResult); if (!DoesMonHaveAnyMoves(mon)) - FormChangeTeachMove(taskId, gTasks[taskId].moveToLearn, gTasks[taskId].firstFusionSlot); + FormChangeTeachMove(taskId, MOVE_CONFUSION, gTasks[taskId].firstFusionSlot); } } gTasks[taskId].tState++; @@ -6400,7 +6493,7 @@ void ItemUseCB_Fusion(u8 taskId, TaskFunc taskFunc) task->storageIndex = itemFusion[i].fusionStorageIndex; task->fusionResult = itemFusion[i].targetSpecies1; task->unfuseSecondMon = itemFusion[i].targetSpecies2; - task->moveToLearn = itemFusion[i].unfuseForgetMove; + task->tExtraMoveHandling = itemFusion[i].extraMoveHandling; task->forgetMove = itemFusion[i].fusionMove; TryItemUseFusionChange(taskId, taskFunc); return; @@ -6440,6 +6533,7 @@ void ItemUseCB_Fusion(u8 taskId, TaskFunc taskFunc) task->fusionResult = itemFusion[i].fusingIntoMon; task->secondFusionSlot = gPartyMenu.slotId; task->moveToLearn = itemFusion[i].fusionMove; + task->tExtraMoveHandling = itemFusion[i].extraMoveHandling; // Start Fusion TryItemUseFusionChange(taskId, taskFunc); return;