From 620e69945d1dea0f5429e7fd1e3330704711a10b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 20 Oct 2022 13:14:32 -0300 Subject: [PATCH 001/131] Form change for starting and ending battles. Adjusted PP for Iron Head/Behemoth moves --- include/battle_util.h | 1 + include/pokemon.h | 2 +- src/battle_main.c | 20 +---- src/battle_script_commands.c | 4 +- src/battle_util.c | 20 +++-- src/data/pokemon/form_change_table_pointers.h | 33 ++++++++ src/data/pokemon/form_change_tables.h | 75 +++++++++++++++++++ src/pokemon.c | 35 ++++----- 8 files changed, 146 insertions(+), 44 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index a456cc1e63..59ddad9406 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -150,6 +150,7 @@ u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 bool32 CanMegaEvolve(u8 battlerId); void UndoMegaEvolution(u32 monId); void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut); +void BattleFormChange(u32 monId, u32 side, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); struct Pokemon *GetIllusionMonPtr(u32 battlerId); diff --git a/include/pokemon.h b/include/pokemon.h index c4015d5621..fa5bfc663e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -564,7 +564,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); bool32 ShouldShowFemaleDifferences(u16 species, u32 personality); -void TryToSetBattleFormChangeMoves(struct Pokemon *mon); +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); u32 GetMonFriendshipScore(struct Pokemon *pokemon); #endif // GUARD_POKEMON_H diff --git a/src/battle_main.c b/src/battle_main.c index 5b6e724c90..9d75e901c0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -602,21 +602,9 @@ static void CB2_InitBattleInternal(void) for (i = 0; i < PARTY_SIZE; i++) { // Player's side - targetSpecies = GetFormChangeTargetSpecies(&gPlayerParty[i], FORM_BATTLE_BEGIN, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&gPlayerParty[i], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&gPlayerParty[i]); - TryToSetBattleFormChangeMoves(&gPlayerParty[i]); - } + BattleFormChange(i, B_SIDE_PLAYER, FORM_BATTLE_BEGIN); // Opponent's side - targetSpecies = GetFormChangeTargetSpecies(&gEnemyParty[i], FORM_BATTLE_BEGIN, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&gEnemyParty[i], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&gEnemyParty[i]); - TryToSetBattleFormChangeMoves(&gEnemyParty[i]); - } + BattleFormChange(i, B_SIDE_OPPONENT, FORM_BATTLE_BEGIN); } gBattleCommunication[MULTIUSE_STATE] = 0; @@ -3264,7 +3252,7 @@ void FaintClearSetData(void) UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); gBattleStruct->overwrittenAbilities[gActiveBattler] = ABILITY_NONE; - + // If the fainted mon was involved in a Sky Drop if (gBattleStruct->skyDropTargets[gActiveBattler] != 0xFF) { @@ -5219,7 +5207,7 @@ static void HandleEndTurn_FinishBattle(void) for (i = 0; i < PARTY_SIZE; i++) { UndoMegaEvolution(i); - UndoFormChange(i, B_SIDE_PLAYER, FALSE); + BattleFormChange(i, B_SIDE_PLAYER, FORM_BATTLE_END); DoBurmyFormChange(i); } #if B_RECALCULATE_STATS >= GEN_5 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index eaa7bbde1a..bfc9bfc42f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14109,7 +14109,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - UndoFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FALSE); + BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_BATTLE_END), gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -14163,7 +14163,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - UndoFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FALSE); + BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_BATTLE_END), gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); diff --git a/src/battle_util.c b/src/battle_util.c index 9dbdb1abfc..92f79cd8d1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9726,15 +9726,19 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) break; } } - if (!isSwitchingOut) +} + +void BattleFormChange(u32 monId, u32 side, u16 method) +{ + u32 targetSpecies; + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + if (targetSpecies != SPECIES_NONE) { - targetSpecies = GetFormChangeTargetSpecies(&party[monId], FORM_BATTLE_END, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&party[monId]); - TryToSetBattleFormChangeMoves(&party[monId]); - } + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + CalculateMonStats(&party[monId]); } } diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 90be7112b6..63971f1325 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -25,6 +25,10 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ARCEUS_FAIRY] = sArceusFormChangeTable, #endif #if P_GEN_5_POKEMON == TRUE + [SPECIES_DARMANITAN] = sDarmanitanFormChangeTable, + [SPECIES_DARMANITAN_ZEN_MODE] = sDarmanitanFormChangeTable, + [SPECIES_DARMANITAN_GALARIAN] = sDarmanitanGalarianFormChangeTable, + [SPECIES_DARMANITAN_ZEN_MODE_GALARIAN] = sDarmanitanGalarianFormChangeTable, [SPECIES_TORNADUS] = sTornadusFormChangeTable, [SPECIES_TORNADUS_THERIAN] = sTornadusFormChangeTable, [SPECIES_THUNDURUS] = sThundurusFormChangeTable, @@ -33,6 +37,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_LANDORUS_THERIAN] = sLandorusFormChangeTable, [SPECIES_KELDEO] = sKeldeoFormChangeTable, [SPECIES_KELDEO_RESOLUTE] = sKeldeoFormChangeTable, + [SPECIES_MELOETTA] = sMeloettaFormChangeTable, + [SPECIES_MELOETTA_PIROUETTE] = sMeloettaFormChangeTable, [SPECIES_GENESECT] = sGenesectFormChangeTable, [SPECIES_GENESECT_DOUSE_DRIVE] = sGenesectFormChangeTable, [SPECIES_GENESECT_SHOCK_DRIVE] = sGenesectFormChangeTable, @@ -40,6 +46,10 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_GENESECT_CHILL_DRIVE] = sGenesectFormChangeTable, #endif #if P_GEN_6_POKEMON == TRUE + [SPECIES_GRENINJA_BATTLE_BOND] = sGreninjaBattleBondFormChangeTable, + [SPECIES_GRENINJA_ASH] = sGreninjaBattleBondFormChangeTable, + [SPECIES_AEGISLASH] = sAegislashFormChangeTable, + [SPECIES_AEGISLASH_BLADE] = sAegislashFormChangeTable, [SPECIES_XERNEAS] = sXerneasFormChangeTable, [SPECIES_XERNEAS_ACTIVE] = sXerneasFormChangeTable, [SPECIES_HOOPA] = sHoopaFormChangeTable, @@ -50,6 +60,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ORICORIO_POM_POM] = sOricorioFormChangeTable, [SPECIES_ORICORIO_PAU] = sOricorioFormChangeTable, [SPECIES_ORICORIO_SENSU] = sOricorioFormChangeTable, + [SPECIES_WISHIWASHI] = sWishiwashiFormChangeTable, + [SPECIES_WISHIWASHI_SCHOOL] = sWishiwashiFormChangeTable, [SPECIES_SILVALLY] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_BUG] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_DARK] = sSilvallyFormChangeTable, @@ -68,8 +80,29 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_SILVALLY_ROCK] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_STEEL] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_WATER] = sSilvallyFormChangeTable, + [SPECIES_MIMIKYU] = sMimikyuFormChangeTable, + [SPECIES_MIMIKYU_BUSTED] = sMimikyuFormChangeTable, + [SPECIES_MINIOR] = sMiniorRedFormChangeTable, + [SPECIES_MINIOR_CORE_RED] = sMiniorRedFormChangeTable, + [SPECIES_MINIOR_METEOR_BLUE] = sMiniorBlueFormChangeTable, + [SPECIES_MINIOR_CORE_BLUE] = sMiniorBlueFormChangeTable, + [SPECIES_MINIOR_METEOR_GREEN] = sMiniorGreenFormChangeTable, + [SPECIES_MINIOR_CORE_GREEN] = sMiniorGreenFormChangeTable, + [SPECIES_MINIOR_METEOR_INDIGO] = sMiniorIndigoFormChangeTable, + [SPECIES_MINIOR_CORE_INDIGO] = sMiniorIndigoFormChangeTable, + [SPECIES_MINIOR_METEOR_ORANGE] = sMiniorOrangeFormChangeTable, + [SPECIES_MINIOR_CORE_ORANGE] = sMiniorOrangeFormChangeTable, + [SPECIES_MINIOR_METEOR_VIOLET] = sMiniorVioletFormChangeTable, + [SPECIES_MINIOR_CORE_VIOLET] = sMiniorVioletFormChangeTable, + [SPECIES_MINIOR_METEOR_YELLOW] = sMiniorYellowFormChangeTable, + [SPECIES_MINIOR_CORE_YELLOW] = sMiniorYellowFormChangeTable, #endif #if P_GEN_8_POKEMON == TRUE + [SPECIES_CRAMORANT] = sCramorantFormChangeTable, + [SPECIES_CRAMORANT_GULPING] = sCramorantFormChangeTable, + [SPECIES_CRAMORANT_GORGING] = sCramorantFormChangeTable, + [SPECIES_MORPEKO] = sMorpekoFormChangeTable, + [SPECIES_MORPEKO_HANGRY] = sMorpekoFormChangeTable, [SPECIES_ZACIAN] = sZacianFormChangeTable, [SPECIES_ZACIAN_CROWNED_SWORD] = sZacianFormChangeTable, [SPECIES_ZAMAZENTA] = sZamazentaFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 94da0add36..551b7484d9 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -97,6 +97,22 @@ static const struct FormChange sArceusFormChangeTable[] = { #endif #if P_GEN_5_POKEMON == TRUE + +static const struct FormChange sDarmanitanFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_DARMANITAN}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMeloettaFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MELOETTA}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sTornadusFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, @@ -132,6 +148,16 @@ static const struct FormChange sGenesectFormChangeTable[] = { #endif #if P_GEN_6_POKEMON == TRUE +static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAegislashFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_AEGISLASH}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sXerneasFormChangeTable[] = { {FORM_BATTLE_BEGIN, SPECIES_XERNEAS_ACTIVE}, {FORM_BATTLE_END, SPECIES_XERNEAS, }, @@ -153,6 +179,10 @@ static const struct FormChange sOricorioFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, {FORM_CHANGE_END}, }; +static const struct FormChange sWishiwashiFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_WISHIWASHI}, + {FORM_CHANGE_END}, +}; static const struct FormChange sSilvallyFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, @@ -175,9 +205,54 @@ static const struct FormChange sSilvallyFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, {FORM_CHANGE_END}, }; + +static const struct FormChange sMimikyuFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MIMIKYU}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMiniorRedFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_END}, +}; +static const struct FormChange sMiniorBlueFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_END}, +}; +static const struct FormChange sMiniorGreenFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_END}, +}; +static const struct FormChange sMiniorIndigoFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_END}, +}; +static const struct FormChange sMiniorOrangeFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_END}, +}; +static const struct FormChange sMiniorVioletFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_END}, +}; +static const struct FormChange sMiniorYellowFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_END}, +}; + #endif #if P_GEN_8_POKEMON == TRUE +static const struct FormChange sCramorantFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_CRAMORANT}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMorpekoFormChangeTable[] = { + {FORM_BATTLE_END, SPECIES_MORPEKO}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sZacianFormChangeTable[] = { {FORM_BATTLE_BEGIN, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, {FORM_BATTLE_END, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, diff --git a/src/pokemon.c b/src/pokemon.c index 98ac992560..1a748fb24a 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4096,6 +4096,17 @@ void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot) SetMonData(mon, MON_DATA_PP1 + slot, &gBattleMoves[move].pp); } +static void SetMonMoveSlot_KeepPP(struct Pokemon *mon, u16 move, u8 slot) +{ + u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + u8 currPP = GetMonData(mon, MON_DATA_PP1 + slot, NULL); + u8 newPP = CalculatePPWithBonus(move, ppBonuses, slot); + u8 finalPP = min(currPP, newPP); + + SetMonData(mon, MON_DATA_MOVE1 + slot, &move); + SetMonData(mon, MON_DATA_PP1 + slot, &finalPP); +} + void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot) { mon->moves[slot] = move; @@ -8474,20 +8485,21 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gBaseStats[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } -void TryToSetBattleFormChangeMoves(struct Pokemon *mon) +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) { int i, j; u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); const struct FormChange *formChanges = gFormChangeTablePointers[species]; - u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - if (formChanges == NULL) + if (formChanges == NULL || (method != FORM_BATTLE_BEGIN && method != FORM_BATTLE_END)) return; for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) { - if ((formChanges[i].method == FORM_BATTLE_BEGIN || formChanges[i].method == FORM_BATTLE_END) - && formChanges[i].param2 && formChanges[i].param3 && formChanges[i].targetSpecies == species) + if (formChanges[i].method == method + && formChanges[i].param2 + && formChanges[i].param3 + && formChanges[i].targetSpecies != species) { u16 originalMove = formChanges[i].param2; u16 newMove = formChanges[i].param3; @@ -8495,20 +8507,9 @@ void TryToSetBattleFormChangeMoves(struct Pokemon *mon) for (j = 0; j < MAX_MON_MOVES; j++) { u16 currMove = GetMonData(mon, MON_DATA_MOVE1 + j, NULL); - u8 totalPp = gBattleMoves[currMove].pp; // Get current move's max PP - u8 currPp = GetMonData(mon, MON_DATA_PP1 + j, NULL); // Get current move's remaining PP - u8 diffPp = totalPp - currPp; // Current move's PP difference - u8 finalPp = gBattleMoves[newMove].pp - diffPp; // Apply the PP difference to the new move - if (currMove == originalMove) - { - if (finalPp > gBattleMoves[newMove].pp) - finalPp = 0; - SetMonMoveSlot(mon, newMove, j); - SetMonData(mon, MON_DATA_PP1 + j, &finalPp); - } + SetMonMoveSlot_KeepPP(mon, newMove, j); } - SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); break; } } From ff494edb85ce17bec2b1ecb2163305b195678566 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 20 Oct 2022 16:57:34 -0300 Subject: [PATCH 002/131] Refactored ItemUseOutOfBattle_FormChange to not use secondaryId --- src/data/items.h | 27 ++++++++------------------- src/party_menu.c | 2 +- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/data/items.h b/src/data/items.h index b0b53c31f5..78d2e72aba 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -3193,7 +3193,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3207,7 +3206,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3221,7 +3219,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3235,7 +3232,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -9071,7 +9067,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_REVEAL_GLASS] = @@ -9083,7 +9078,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_DNA_SPLICERS] = @@ -9093,9 +9087,8 @@ const struct Item gItems[] = .price = 0, .description = sDNASplicersDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_ZYGARDE_CUBE] = @@ -9119,7 +9112,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_N_SOLARIZER] = @@ -9129,9 +9121,8 @@ const struct Item gItems[] = .price = 0, .description = sNSolarizerDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_N_LUNARIZER] = @@ -9141,9 +9132,8 @@ const struct Item gItems[] = .price = 0, .description = sNLunarizerDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_REINS_OF_UNITY] = @@ -9153,9 +9143,8 @@ const struct Item gItems[] = .price = 0, .description = sReinsOfUnityDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, // Battle Mechanic Key Items diff --git a/src/party_menu.c b/src/party_menu.c index eaeadabab0..3c8b163c54 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5591,7 +5591,7 @@ static void Task_TryItemUseFormChange(u8 taskId) bool32 TryItemUseFormChange(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; - u16 targetSpecies = GetFormChangeTargetSpecies(mon, ItemId_GetSecondaryId(gSpecialVar_ItemId), gSpecialVar_ItemId); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_ITEM_USE, gSpecialVar_ItemId); if (targetSpecies != SPECIES_NONE) { From b74f0777daf19a01fa4892000bab55a6f6285403 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 20 Oct 2022 17:22:58 -0300 Subject: [PATCH 003/131] Renamed form change constants --- include/constants/pokemon.h | 14 +- src/battle_main.c | 6 +- src/battle_script_commands.c | 4 +- src/data/pokemon/form_change_tables.h | 216 +++++++++++++------------- src/daycare.c | 2 +- src/party_menu.c | 4 +- src/pokemon.c | 12 +- src/pokemon_storage_system.c | 2 +- src/script_pokemon_util.c | 2 +- 9 files changed, 131 insertions(+), 131 deletions(-) diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 5167f5f55f..cacbdc55c0 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -317,13 +317,13 @@ #define EVO_MODE_OVERWORLD_SPECIAL 5 // Form change types -#define FORM_CHANGE_END 0 -#define FORM_ITEM_HOLD 1 -#define FORM_ITEM_USE 2 -#define FORM_MOVE 3 -#define FORM_WITHDRAW 4 -#define FORM_BATTLE_BEGIN 5 -#define FORM_BATTLE_END 6 +#define FORM_CHANGE_END 0 +#define FORM_CHANGE_ITEM_HOLD 1 +#define FORM_CHANGE_ITEM_USE 2 +#define FORM_CHANGE_MOVE 3 +#define FORM_CHANGE_WITHDRAW 4 +#define FORM_CHANGE_BATTLE_BEGIN 5 +#define FORM_CHANGE_BATTLE_END 6 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 diff --git a/src/battle_main.c b/src/battle_main.c index 9d75e901c0..8a3cbcfcdb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -602,9 +602,9 @@ static void CB2_InitBattleInternal(void) for (i = 0; i < PARTY_SIZE; i++) { // Player's side - BattleFormChange(i, B_SIDE_PLAYER, FORM_BATTLE_BEGIN); + BattleFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_BEGIN); // Opponent's side - BattleFormChange(i, B_SIDE_OPPONENT, FORM_BATTLE_BEGIN); + BattleFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BATTLE_BEGIN); } gBattleCommunication[MULTIUSE_STATE] = 0; @@ -5207,7 +5207,7 @@ static void HandleEndTurn_FinishBattle(void) for (i = 0; i < PARTY_SIZE; i++) { UndoMegaEvolution(i); - BattleFormChange(i, B_SIDE_PLAYER, FORM_BATTLE_END); + BattleFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); DoBurmyFormChange(i); } #if B_RECALCULATE_STATS >= GEN_5 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index bfc9bfc42f..060a9e7170 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14109,7 +14109,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_BATTLE_END), + BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -14163,7 +14163,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_BATTLE_END), + BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 551b7484d9..1f2e926bb3 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,97 +1,97 @@ /* -FORM_ITEM_HOLD: +FORM_CHANGE_ITEM_HOLD: Form change activates when the specified item is given to or taken from the selected Pokémon. Alternatively, form change activates when the specified item is is given to or taken from the selected Pokémon that has a particular ability. param1 = item to hold param2 = ability to check for, optional -FORM_ITEM_USE: +FORM_CHANGE_ITEM_USE: Form change activates when the item is used on the selected Pokémon. param1 = item to use param2 = DAY if form change activates in the daytime, optional NIGHT if form change activates at nighttime, optional -FORM_MOVE: +FORM_CHANGE_MOVE: Form change activates when the Pokémon learns or forgets the move. param1 = move to check for param2 = WHEN_LEARNED if form change activates when move is forgotten WHEN_FORGOTTEN if form change activates when move is learned -FORM_WITHDRAW: +FORM_CHANGE_WITHDRAW: Form change activates when the Pokémon is withdrawn from the PC or Daycare. no parameters -FORM_BATTLE_BEGIN: +FORM_CHANGE_BATTLE_BEGIN: Form change activates when the Pokémon is sent out at the beginning of a battle param1 = item to hold, optional param2 = a move that will be replaced, optional param3 = a new move to replace it with, optional -FORM_BATTLE_END: +FORM_CHANGE_BATTLE_END: Form change activates at the end of a battle param1 = item to hold, optional param2 = a move that will be replaced, optional param3 = a new move to replace it with, optional */ -// FORM_MOVE param2 Arguments +// FORM_CHANGE_MOVE param2 Arguments #define WHEN_LEARNED 0 #define WHEN_FORGOTTEN 1 -// FORM_ITEM_USE param2 Arguments +// FORM_CHANGE_ITEM_USE param2 Arguments #define DAY 1 #define NIGHT 2 #if P_GEN_4_POKEMON == TRUE static const struct FormChange sGiratinaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, {FORM_CHANGE_END}, }; static const struct FormChange sShayminFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, - // {FORM_WITHDRAW, SPECIES_SHAYMIN}, + {FORM_CHANGE_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, + // {FORM_CHANGE_WITHDRAW, SPECIES_SHAYMIN}, {FORM_CHANGE_END}, }; static const struct FormChange sArceusFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_ARCEUS, ITEM_NONE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIST_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIGHTINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_SKY_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_FLYINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_TOXIC_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_POISONIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_STONE_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_ROCKIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_EARTH_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_GROUNDIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_INSECT_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_BUGINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_SPOOKY_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_GHOSTIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_IRON_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_STEELIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FLAME_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FIRIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_SPLASH_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_WATERIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_MEADOW_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_GRASSIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ZAP_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ELECTRIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_MIND_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_PSYCHIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICICLE_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRACO_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRAGONIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DREAD_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS, ITEM_NONE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIST_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIGHTINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_SKY_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_FLYINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_TOXIC_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_POISONIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_STONE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_ROCKIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_EARTH_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_GROUNDIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_INSECT_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_BUGINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_SPOOKY_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_GHOSTIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_IRON_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_STEELIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FLAME_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_SPLASH_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_WATERIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_MEADOW_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_GRASSIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ZAP_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ELECTRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_MIND_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_PSYCHIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICICLE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRACO_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRAGONIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DREAD_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, {FORM_CHANGE_END}, }; #endif @@ -99,144 +99,144 @@ static const struct FormChange sArceusFormChangeTable[] = { #if P_GEN_5_POKEMON == TRUE static const struct FormChange sDarmanitanFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_DARMANITAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, {FORM_CHANGE_END}, }; static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_END}, }; static const struct FormChange sMeloettaFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MELOETTA}, + {FORM_CHANGE_BATTLE_END, SPECIES_MELOETTA}, {FORM_CHANGE_END}, }; static const struct FormChange sTornadusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; static const struct FormChange sThundurusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; static const struct FormChange sLandorusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; static const struct FormChange sKeldeoFormChangeTable[] = { - // {FORM_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, - // {FORM_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, + // {FORM_CHANGE_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, + // {FORM_CHANGE_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, {FORM_CHANGE_END}, }; static const struct FormChange sGenesectFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_GENESECT, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_DOUSE_DRIVE, ITEM_DOUSE_DRIVE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_DOUSE_DRIVE, ITEM_DOUSE_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, {FORM_CHANGE_END}, }; #endif #if P_GEN_6_POKEMON == TRUE static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, {FORM_CHANGE_END}, }; static const struct FormChange sAegislashFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_AEGISLASH}, + {FORM_CHANGE_BATTLE_END, SPECIES_AEGISLASH}, {FORM_CHANGE_END}, }; static const struct FormChange sXerneasFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_XERNEAS_ACTIVE}, - {FORM_BATTLE_END, SPECIES_XERNEAS, }, + {FORM_CHANGE_BATTLE_BEGIN, SPECIES_XERNEAS_ACTIVE}, + {FORM_CHANGE_BATTLE_END, SPECIES_XERNEAS, }, {FORM_CHANGE_END}, }; static const struct FormChange sHoopaFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, - // {FORM_WITHDRAW, SPECIES_HOOPA}, + {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, + // {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, {FORM_CHANGE_END}, }; #endif #if P_GEN_7_POKEMON == TRUE static const struct FormChange sOricorioFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_ORICORIO, ITEM_RED_NECTAR}, - {FORM_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, - {FORM_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, - {FORM_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO, ITEM_RED_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, {FORM_CHANGE_END}, }; static const struct FormChange sWishiwashiFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_WISHIWASHI}, + {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, {FORM_CHANGE_END}, }; static const struct FormChange sSilvallyFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, {FORM_CHANGE_END}, }; static const struct FormChange sMimikyuFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MIMIKYU}, + {FORM_CHANGE_BATTLE_END, SPECIES_MIMIKYU}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorRedFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorBlueFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorGreenFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorIndigoFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorOrangeFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorVioletFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorYellowFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_END}, }; @@ -244,30 +244,30 @@ static const struct FormChange sMiniorYellowFormChangeTable[] = { #if P_GEN_8_POKEMON == TRUE static const struct FormChange sCramorantFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_CRAMORANT}, + {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, {FORM_CHANGE_END}, }; static const struct FormChange sMorpekoFormChangeTable[] = { - {FORM_BATTLE_END, SPECIES_MORPEKO}, + {FORM_CHANGE_BATTLE_END, SPECIES_MORPEKO}, {FORM_CHANGE_END}, }; static const struct FormChange sZacianFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, - {FORM_BATTLE_END, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, + {FORM_CHANGE_BATTLE_BEGIN, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, + {FORM_CHANGE_BATTLE_END, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, {FORM_CHANGE_END}, }; static const struct FormChange sZamazentaFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, - {FORM_BATTLE_END, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, + {FORM_CHANGE_BATTLE_BEGIN, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, + {FORM_CHANGE_BATTLE_END, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, {FORM_CHANGE_END}, }; static const struct FormChange sEnamorusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; #endif diff --git a/src/daycare.c b/src/daycare.c index 18bc45eb01..fc44e200e6 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -255,7 +255,7 @@ static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) species = GetBoxMonData(&daycareMon->mon, MON_DATA_SPECIES); BoxMonToMon(&daycareMon->mon, &pokemon); - newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_WITHDRAW, 0); + newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_CHANGE_WITHDRAW, 0); if (newSpecies != SPECIES_NONE) { SetMonData(&pokemon, MON_DATA_SPECIES, &newSpecies); CalculateMonStats(&pokemon); diff --git a/src/party_menu.c b/src/party_menu.c index 3c8b163c54..1071825a6b 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5591,7 +5591,7 @@ static void Task_TryItemUseFormChange(u8 taskId) bool32 TryItemUseFormChange(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_ITEM_USE, gSpecialVar_ItemId); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_USE, gSpecialVar_ItemId); if (targetSpecies != SPECIES_NONE) { @@ -5626,7 +5626,7 @@ void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task) } void TryItemHoldFormChange(struct Pokemon *mon) { - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_ITEM_HOLD, 0); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { PlayCry_NormalNoDucking(targetSpecies, 0, CRY_VOLUME_RS, CRY_VOLUME_RS); diff --git a/src/pokemon.c b/src/pokemon.c index 1a748fb24a..b60e5a30ee 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8363,12 +8363,12 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 { switch (method) { - case FORM_ITEM_HOLD: + case FORM_CHANGE_ITEM_HOLD: if ((heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) && (ability == formChanges[i].param2 || formChanges[i].param2 == ABILITY_NONE)) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_ITEM_USE: + case FORM_CHANGE_ITEM_USE: if (arg == formChanges[i].param1) { switch (formChanges[i].param2) @@ -8389,12 +8389,12 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 } } break; - case FORM_MOVE: + case FORM_CHANGE_MOVE: if (BoxMonKnowsMove(boxMon, formChanges[i].param1) != formChanges[i].param2) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_BATTLE_BEGIN: - case FORM_BATTLE_END: + case FORM_CHANGE_BATTLE_BEGIN: + case FORM_CHANGE_BATTLE_END: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; } @@ -8491,7 +8491,7 @@ void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); const struct FormChange *formChanges = gFormChangeTablePointers[species]; - if (formChanges == NULL || (method != FORM_BATTLE_BEGIN && method != FORM_BATTLE_END)) + if (formChanges == NULL || (method != FORM_CHANGE_BATTLE_BEGIN && method != FORM_CHANGE_BATTLE_END)) return; for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 3f58daa861..4cce36a932 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -6900,7 +6900,7 @@ static void ReshowDisplayMon(void) void SetMonFormPSS(struct BoxPokemon *boxMon) { - u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_ITEM_HOLD, 0); + u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { SetBoxMonData(boxMon, MON_DATA_SPECIES, &targetSpecies); diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index e33c8ffcad..d95079b4d0 100755 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -72,7 +72,7 @@ u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 u SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem); // In case a mon with a form changing item is given. Eg: SPECIES_ARCEUS with ITEM_SPLASH_PLATE will transform into SPECIES_ARCEUS_WATER upon gifted. - targetSpecies = GetFormChangeTargetSpecies(&mon, FORM_ITEM_HOLD, 0); + targetSpecies = GetFormChangeTargetSpecies(&mon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { SetMonData(&mon, MON_DATA_SPECIES, &targetSpecies); From d8cc7f7abe5e151ca0473585ec68e632e5979693 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 20 Oct 2022 17:56:56 -0300 Subject: [PATCH 004/131] Form change when switching out --- include/constants/pokemon.h | 3 +- src/battle_util.c | 2 +- src/data/pokemon/form_change_tables.h | 43 +++++++++++++++++++-------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index cacbdc55c0..01bc755cdd 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -323,7 +323,8 @@ #define FORM_CHANGE_MOVE 3 #define FORM_CHANGE_WITHDRAW 4 #define FORM_CHANGE_BATTLE_BEGIN 5 -#define FORM_CHANGE_BATTLE_END 6 +#define FORM_CHANGE_BATTLE_SWITCH 6 +#define FORM_CHANGE_BATTLE_END 7 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 diff --git a/src/battle_util.c b/src/battle_util.c index 92f79cd8d1..003b8b272e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -518,7 +518,7 @@ void HandleAction_Switch(void) if (gBattleResults.playerSwitchesCounter < 255) gBattleResults.playerSwitchesCounter++; - UndoFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), TRUE); + BattleFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), FORM_CHANGE_BATTLE_SWITCH); } void HandleAction_UseItem(void) diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 1f2e926bb3..e043fa4621 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -22,6 +22,10 @@ FORM_CHANGE_WITHDRAW: Form change activates when the Pokémon is withdrawn from the PC or Daycare. no parameters +FORM_CHANGE_SWITCH: + Form change activates when the Pokémon is switched out in battle. + no parameters + FORM_CHANGE_BATTLE_BEGIN: Form change activates when the Pokémon is sent out at the beginning of a battle param1 = item to hold, optional @@ -99,12 +103,14 @@ static const struct FormChange sArceusFormChangeTable[] = { #if P_GEN_5_POKEMON == TRUE static const struct FormChange sDarmanitanFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, {FORM_CHANGE_END}, }; static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_END}, }; @@ -154,7 +160,8 @@ static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { }; static const struct FormChange sAegislashFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_AEGISLASH}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH}, + {FORM_CHANGE_BATTLE_END, SPECIES_AEGISLASH}, {FORM_CHANGE_END}, }; @@ -180,7 +187,8 @@ static const struct FormChange sOricorioFormChangeTable[] = { {FORM_CHANGE_END}, }; static const struct FormChange sWishiwashiFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, + {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, {FORM_CHANGE_END}, }; @@ -212,31 +220,38 @@ static const struct FormChange sMimikyuFormChangeTable[] = { }; static const struct FormChange sMiniorRedFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorBlueFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorGreenFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorIndigoFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorOrangeFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorVioletFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorYellowFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_END}, }; @@ -244,12 +259,14 @@ static const struct FormChange sMiniorYellowFormChangeTable[] = { #if P_GEN_8_POKEMON == TRUE static const struct FormChange sCramorantFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, + {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, {FORM_CHANGE_END}, }; static const struct FormChange sMorpekoFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MORPEKO}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, + {FORM_CHANGE_BATTLE_END, SPECIES_MORPEKO}, {FORM_CHANGE_END}, }; From 861590f747b7f43022f257980c7abb0f29953cf9 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 20 Oct 2022 18:53:12 -0300 Subject: [PATCH 005/131] Form change when fainting. Goodbye UndoFormChange! --- include/battle_util.h | 1 - include/constants/pokemon.h | 3 ++- src/battle_main.c | 2 +- src/battle_util.c | 38 --------------------------- src/data/pokemon/form_change_tables.h | 22 +++++++++++++--- 5 files changed, 22 insertions(+), 44 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 59ddad9406..fb5090f348 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -149,7 +149,6 @@ u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId); u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); bool32 CanMegaEvolve(u8 battlerId); void UndoMegaEvolution(u32 monId); -void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut); void BattleFormChange(u32 monId, u32 side, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 01bc755cdd..bb77398dd5 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -324,7 +324,8 @@ #define FORM_CHANGE_WITHDRAW 4 #define FORM_CHANGE_BATTLE_BEGIN 5 #define FORM_CHANGE_BATTLE_SWITCH 6 -#define FORM_CHANGE_BATTLE_END 7 +#define FORM_CHANGE_BATTLE_FAINT 7 +#define FORM_CHANGE_BATTLE_END 8 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 diff --git a/src/battle_main.c b/src/battle_main.c index 8a3cbcfcdb..71d263860e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3247,7 +3247,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; Ai_UpdateFaintData(gActiveBattler); - UndoFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FALSE); + BattleFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_BATTLE_FAINT); if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); diff --git a/src/battle_util.c b/src/battle_util.c index 003b8b272e..f39d2a03e5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9690,44 +9690,6 @@ void UndoMegaEvolution(u32 monId) } } -void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) -{ - u32 i, currSpecies, targetSpecies; - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - static const u16 species[][3] = - { - // Changed Form ID Default Form ID Should change on switch - {SPECIES_MIMIKYU_BUSTED, SPECIES_MIMIKYU, FALSE}, - {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND, FALSE}, - {SPECIES_MELOETTA_PIROUETTE, SPECIES_MELOETTA, FALSE}, - {SPECIES_AEGISLASH_BLADE, SPECIES_AEGISLASH, TRUE}, - {SPECIES_DARMANITAN_ZEN_MODE, SPECIES_DARMANITAN, TRUE}, - {SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, TRUE}, - {SPECIES_MINIOR_METEOR_BLUE, SPECIES_MINIOR_CORE_BLUE, TRUE}, - {SPECIES_MINIOR_METEOR_GREEN, SPECIES_MINIOR_CORE_GREEN, TRUE}, - {SPECIES_MINIOR_METEOR_INDIGO, SPECIES_MINIOR_CORE_INDIGO, TRUE}, - {SPECIES_MINIOR_METEOR_ORANGE, SPECIES_MINIOR_CORE_ORANGE, TRUE}, - {SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, TRUE}, - {SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, TRUE}, - {SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, TRUE}, - {SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT, TRUE}, - {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT, TRUE}, - {SPECIES_MORPEKO_HANGRY, SPECIES_MORPEKO, TRUE}, - {SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, SPECIES_DARMANITAN_GALARIAN, TRUE}, - }; - - currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - for (i = 0; i < ARRAY_COUNT(species); i++) - { - if (currSpecies == species[i][0] && (!isSwitchingOut || species[i][2] == TRUE)) - { - SetMonData(&party[monId], MON_DATA_SPECIES, &species[i][1]); - CalculateMonStats(&party[monId]); - break; - } - } -} - void BattleFormChange(u32 monId, u32 side, u16 method) { u32 targetSpecies; diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index e043fa4621..0586c8ac88 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -104,18 +104,21 @@ static const struct FormChange sArceusFormChangeTable[] = { static const struct FormChange sDarmanitanFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_DARMANITAN}, {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, {FORM_CHANGE_END}, }; static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_END}, }; static const struct FormChange sMeloettaFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MELOETTA}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MELOETTA}, + {FORM_CHANGE_BATTLE_END, SPECIES_MELOETTA}, {FORM_CHANGE_END}, }; @@ -155,12 +158,14 @@ static const struct FormChange sGenesectFormChangeTable[] = { #if P_GEN_6_POKEMON == TRUE static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, {FORM_CHANGE_END}, }; static const struct FormChange sAegislashFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_AEGISLASH}, {FORM_CHANGE_BATTLE_END, SPECIES_AEGISLASH}, {FORM_CHANGE_END}, }; @@ -188,6 +193,7 @@ static const struct FormChange sOricorioFormChangeTable[] = { }; static const struct FormChange sWishiwashiFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_WISHIWASHI}, {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, {FORM_CHANGE_END}, }; @@ -215,42 +221,50 @@ static const struct FormChange sSilvallyFormChangeTable[] = { }; static const struct FormChange sMimikyuFormChangeTable[] = { - {FORM_CHANGE_BATTLE_END, SPECIES_MIMIKYU}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MIMIKYU}, + {FORM_CHANGE_BATTLE_END, SPECIES_MIMIKYU}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorRedFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorBlueFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorGreenFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorIndigoFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorOrangeFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorVioletFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorYellowFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_END}, }; @@ -260,12 +274,14 @@ static const struct FormChange sMiniorYellowFormChangeTable[] = { #if P_GEN_8_POKEMON == TRUE static const struct FormChange sCramorantFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_CRAMORANT}, {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, {FORM_CHANGE_END}, }; static const struct FormChange sMorpekoFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, + {FORM_CHANGE_BATTLE_FAINT, SPECIES_MORPEKO}, {FORM_CHANGE_BATTLE_END, SPECIES_MORPEKO}, {FORM_CHANGE_END}, }; From 0a79390ec00e982240edb8513b59b440e7218a45 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 21 Oct 2022 02:08:37 -0300 Subject: [PATCH 006/131] Primal Reversion in Form Change tables --- include/battle.h | 3 - include/battle_util.h | 6 +- include/constants/pokemon.h | 37 ++++++------ include/pokemon.h | 2 + src/battle_interface.c | 16 +++--- src/battle_main.c | 31 +++++----- src/battle_script_commands.c | 43 ++------------ src/battle_util.c | 56 +++++++++++++------ src/data/pokemon/base_stats.h | 4 +- src/data/pokemon/evolution.h | 2 - src/data/pokemon/form_change_table_pointers.h | 4 ++ src/data/pokemon/form_change_tables.h | 14 ++++- src/pokemon.c | 27 ++++++++- 13 files changed, 136 insertions(+), 109 deletions(-) diff --git a/include/battle.h b/include/battle.h index b328b46bb2..ff5d698abf 100644 --- a/include/battle.h +++ b/include/battle.h @@ -472,9 +472,6 @@ struct MegaEvolutionData bool8 alreadyEvolved[4]; // Array id is used for mon position. u16 evolvedSpecies[MAX_BATTLERS_COUNT]; u16 playerEvolvedSpecies; - u8 primalRevertedPartyIds[2]; // As flags using gBitTable; - u16 primalRevertedSpecies[MAX_BATTLERS_COUNT]; - u16 playerPrimalRevertedSpecies; u8 battlerId; bool8 playerSelect; u8 triggerSpriteId; diff --git a/include/battle_util.h b/include/battle_util.h index fb5090f348..5a09909509 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -145,11 +145,12 @@ u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilit u16 GetTypeModifier(u8 atkType, u8 defType); s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId); u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId); -u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId); +u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId); u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); bool32 CanMegaEvolve(u8 battlerId); void UndoMegaEvolution(u32 monId); -void BattleFormChange(u32 monId, u32 side, u16 method); +bool32 IsBattlerPrimalReverted(u8 battlerId); +void TryBattleFormChange(u8 battlerId, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); struct Pokemon *GetIllusionMonPtr(u32 battlerId); @@ -186,6 +187,7 @@ void TryToRevertMimicry(void); void RestoreBattlerOriginalTypes(u8 battlerId); u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); +void RecalcBattlerStats(u32 battler, struct Pokemon *mon); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability); diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index bb77398dd5..7dc250834e 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -266,7 +266,6 @@ // Evolution types #define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle. #define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item. -#define EVO_PRIMAL_REVERSION 0xfffd // Not an actual evolution, used to undergo primal reversion in battle. #define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220 #define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220 #define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220 @@ -317,15 +316,16 @@ #define EVO_MODE_OVERWORLD_SPECIAL 5 // Form change types -#define FORM_CHANGE_END 0 -#define FORM_CHANGE_ITEM_HOLD 1 -#define FORM_CHANGE_ITEM_USE 2 -#define FORM_CHANGE_MOVE 3 -#define FORM_CHANGE_WITHDRAW 4 -#define FORM_CHANGE_BATTLE_BEGIN 5 -#define FORM_CHANGE_BATTLE_SWITCH 6 -#define FORM_CHANGE_BATTLE_FAINT 7 -#define FORM_CHANGE_BATTLE_END 8 +#define FORM_CHANGE_END 0 // Form table terminator +#define FORM_CHANGE_ITEM_HOLD 1 +#define FORM_CHANGE_ITEM_USE 2 +#define FORM_CHANGE_MOVE 3 // Todo +#define FORM_CHANGE_WITHDRAW 4 // +#define FORM_CHANGE_BATTLE_BEGIN 5 +#define FORM_CHANGE_BATTLE_END 6 +#define FORM_CHANGE_BATTLE_SWITCH 7 +#define FORM_CHANGE_BATTLE_FAINT 8 +#define FORM_CHANGE_PRIMAL_REVERSION 9 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 @@ -345,14 +345,15 @@ #define SPECIES_FLAG_LEGENDARY (1 << 0) #define SPECIES_FLAG_MYTHICAL (1 << 1) #define SPECIES_FLAG_MEGA_EVOLUTION (1 << 2) -#define SPECIES_FLAG_ULTRA_BEAST (1 << 3) -#define SPECIES_FLAG_ALOLAN_FORM (1 << 4) -#define SPECIES_FLAG_GALARIAN_FORM (1 << 5) -#define SPECIES_FLAG_HISUIAN_FORM (1 << 6) -#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 7) -#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 8) -#define SPECIES_FLAG_SHINY_LOCKED (1 << 9) -#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 10) +#define SPECIES_FLAG_PRIMAL_REVERSION (1 << 3) +#define SPECIES_FLAG_ULTRA_BEAST (1 << 4) +#define SPECIES_FLAG_ALOLAN_FORM (1 << 5) +#define SPECIES_FLAG_GALARIAN_FORM (1 << 6) +#define SPECIES_FLAG_HISUIAN_FORM (1 << 7) +#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 8) +#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 9) +#define SPECIES_FLAG_SHINY_LOCKED (1 << 10) +#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 11) #define LEGENDARY_PERFECT_IV_COUNT 3 diff --git a/include/pokemon.h b/include/pokemon.h index fa5bfc663e..134991b953 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -409,6 +409,7 @@ extern const u16 gUnionRoomFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; extern const s8 gNatureStatTable[][5]; extern const u16 *const gFormSpeciesIdTables[NUM_SPECIES]; +extern const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES]; extern const u32 sExpCandyExperienceTable[]; void ZeroBoxMonData(struct BoxPokemon *boxMon); @@ -564,6 +565,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); bool32 ShouldShowFemaleDifferences(u16 species, u32 personality); +void TryFormChange(u32 monId, u32 side, u16 method); void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); u32 GetMonFriendshipScore(struct Pokemon *pokemon); diff --git a/src/battle_interface.c b/src/battle_interface.c index 3039c65b67..ed756592f8 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -871,8 +871,8 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId) healthBarSpritePtr->invisible = TRUE; // Create mega indicator sprite if is a mega evolved or a primal reverted mon. - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]] - || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + || IsBattlerPrimalReverted(battlerId)) { megaIndicatorSpriteId = CreateMegaIndicatorSprite(battlerId, 0); gSprites[megaIndicatorSpriteId].invisible = TRUE; @@ -979,8 +979,8 @@ void SetHealthboxSpriteVisible(u8 healthboxSpriteId) gSprites[healthboxSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE; - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]] - || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + || IsBattlerPrimalReverted(battlerId)) { u8 spriteId = GetMegaIndicatorSpriteId(healthboxSpriteId); if (spriteId != 0xFF) @@ -1104,8 +1104,8 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) u8 battler = gSprites[healthboxSpriteId].hMain_Battler; // Don't print Lv char if mon is mega evolved or primal reverted. - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]] - || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) + if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) + || IsBattlerPrimalReverted(battler)) { objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); xPos = 5 * (3 - (objVram - (text + 2))) - 1; @@ -1561,7 +1561,7 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) LoadSpritePalette(&sSpritePalette_MegaIndicator); LoadSpriteSheet(&sSpriteSheet_MegaIndicator); } - else if (gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + else if (IsBattlerPrimalReverted(battlerId)) { if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON) { @@ -1590,7 +1590,7 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) { spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0); } - else if (gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + else if (IsBattlerPrimalReverted(battlerId)) { if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON) spriteId = CreateSpriteAtEnd(&sSpriteTemplate_OmegaIndicator, x, y, 0); diff --git a/src/battle_main.c b/src/battle_main.c index 71d263860e..f58c0d43bb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -602,9 +602,9 @@ static void CB2_InitBattleInternal(void) for (i = 0; i < PARTY_SIZE; i++) { // Player's side - BattleFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_BEGIN); + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_BEGIN); // Opponent's side - BattleFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BATTLE_BEGIN); + TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BATTLE_BEGIN); } gBattleCommunication[MULTIUSE_STATE] = 0; @@ -3247,7 +3247,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; Ai_UpdateFaintData(gActiveBattler); - BattleFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_BATTLE_FAINT); + TryFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_BATTLE_FAINT); if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); @@ -3682,18 +3682,12 @@ static void TryDoEventsBeforeFirstTurn(void) // Primal Reversion for (i = 0; i < gBattlersCount; i++) { - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB) + if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB + && GetPrimalReversionSpecies(gBattleMons[i].species, gBattleMons[i].item) != SPECIES_NONE) { - for (j = 0; j < EVOS_PER_MON; j++) - { - if (gEvolutionTable[gBattleMons[i].species][j].targetSpecies != SPECIES_NONE - && gEvolutionTable[gBattleMons[i].species][j].method == EVO_PRIMAL_REVERSION) - { - gBattlerAttacker = i; - BattleScriptExecute(BattleScript_PrimalReversion); - return; - } - } + gBattlerAttacker = i; + BattleScriptExecute(BattleScript_PrimalReversion); + return; } } @@ -5207,7 +5201,7 @@ static void HandleEndTurn_FinishBattle(void) for (i = 0; i < PARTY_SIZE; i++) { UndoMegaEvolution(i); - BattleFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); DoBurmyFormChange(i); } #if B_RECALCULATE_STATS >= GEN_5 @@ -5221,6 +5215,13 @@ static void HandleEndTurn_FinishBattle(void) } } #endif + // Clear battle mon species to avoid a bug on the next battle that causes + // healthboxes loading incorrectly due to it trying to create a Mega Indicator + // if the previous battler would've had. + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + gBattleMons[i].species = SPECIES_NONE; + } gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions; gCB2_AfterEvolution = BattleMainCB2; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 060a9e7170..51d3cfbe16 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7914,22 +7914,6 @@ u32 IsAbilityStatusProtected(u32 battler) || IsShieldsDownProtected(battler); } -static void RecalcBattlerStats(u32 battler, struct Pokemon *mon) -{ - CalculateMonStats(mon); - gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); - gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); - gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); - gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK); - gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF); - gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); - gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); - gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); - gBattleMons[battler].ability = GetMonAbility(mon); - gBattleMons[battler].type1 = gBaseStats[gBattleMons[battler].species].type1; - gBattleMons[battler].type2 = gBaseStats[gBattleMons[battler].species].type2; -} - static u32 GetHighestStatId(u32 battlerId) { u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battlerId].attack; @@ -8870,17 +8854,7 @@ static void Cmd_various(void) // Change species. if (gBattlescriptCurrInstr[3] == 0) { - u16 primalSpecies; - gBattleStruct->mega.primalRevertedSpecies[gActiveBattler] = gBattleMons[gActiveBattler].species; - if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT - || (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)))) - { - gBattleStruct->mega.playerPrimalRevertedSpecies = gBattleStruct->mega.primalRevertedSpecies[gActiveBattler]; - } - // Checks Primal Reversion - primalSpecies = GetPrimalReversionSpecies(gBattleStruct->mega.primalRevertedSpecies[gActiveBattler], gBattleMons[gActiveBattler].item); - - gBattleMons[gActiveBattler].species = primalSpecies; + gBattleMons[gActiveBattler].species = GetPrimalReversionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item); PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], sizeof(gBattleMons[gActiveBattler].species), &gBattleMons[gActiveBattler].species); @@ -8890,7 +8864,6 @@ static void Cmd_various(void) else if (gBattlescriptCurrInstr[3] == 1) { RecalcBattlerStats(gActiveBattler, mon); - gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(gActiveBattler)] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]]; } // Update healthbox and elevation. else @@ -9606,15 +9579,7 @@ static void Cmd_various(void) return; case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: { - bool8 canDoPrimalReversion = FALSE; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[gBattleMons[gActiveBattler].species][i].method == EVO_PRIMAL_REVERSION - && gEvolutionTable[gBattleMons[gActiveBattler].species][i].param == gBattleMons[gActiveBattler].item) - canDoPrimalReversion = TRUE; - } - if (!canDoPrimalReversion) + if (GetPrimalReversionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item) == SPECIES_NONE) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else gBattlescriptCurrInstr += 7; @@ -14109,7 +14074,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), + TryFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -14163,7 +14128,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), + TryFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); diff --git a/src/battle_util.c b/src/battle_util.c index f39d2a03e5..729728ec0e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -518,7 +518,7 @@ void HandleAction_Switch(void) if (gBattleResults.playerSwitchesCounter < 255) gBattleResults.playerSwitchesCounter++; - BattleFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), FORM_CHANGE_BATTLE_SWITCH); + TryFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), FORM_CHANGE_BATTLE_SWITCH); } void HandleAction_UseItem(void) @@ -8955,8 +8955,7 @@ static bool32 CanEvolve(u32 species) { if (gEvolutionTable[species][i].method && gEvolutionTable[species][i].method != EVO_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_PRIMAL_REVERSION) + && gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION) return TRUE; } return FALSE; @@ -9565,15 +9564,20 @@ u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId) return SPECIES_NONE; } -u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId) +u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId) { u32 i; + const struct FormChange *formChanges = gFormChangeTablePointers[preSpecies]; - for (i = 0; i < EVOS_PER_MON; i++) + if (formChanges != NULL) { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_PRIMAL_REVERSION - && gEvolutionTable[preEvoSpecies][i].param == heldItemId) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; + for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + { + if (formChanges[i].method == FORM_CHANGE_PRIMAL_REVERSION + && formChanges[i].param1 == heldItemId + && formChanges[i].targetSpecies != preSpecies) + return formChanges[i].targetSpecies; + } } return SPECIES_NONE; } @@ -9675,12 +9679,6 @@ void UndoMegaEvolution(u32 monId) SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->mega.playerEvolvedSpecies); CalculateMonStats(&gPlayerParty[monId]); } - else if (gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] & gBitTable[monId]) - { - gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]); - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies); - CalculateMonStats(&gPlayerParty[monId]); - } // While not exactly a mega evolution, Zygarde follows the same rules. else if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE) { @@ -9690,17 +9688,23 @@ void UndoMegaEvolution(u32 monId) } } -void BattleFormChange(u32 monId, u32 side, u16 method) +bool32 IsBattlerPrimalReverted(u8 battlerId) { - u32 targetSpecies; + return (gBaseStats[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION); +} + +void TryBattleFormChange(u8 battlerId, u16 method) +{ + u16 targetSpecies; + u8 monId = gBattlerPartyIndexes[battlerId]; + u8 side = GET_BATTLER_SIDE(battlerId); struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); if (targetSpecies != SPECIES_NONE) { - TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&party[monId]); + RecalcBattlerStats(battlerId, &party[monId]); } } @@ -10362,3 +10366,19 @@ bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move) return FALSE; // Pokémon affected by Heal Block cannot target allies with Pollen Puff return TRUE; } + +void RecalcBattlerStats(u32 battler, struct Pokemon *mon) +{ + CalculateMonStats(mon); + gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); + gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); + gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); + gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK); + gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF); + gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); + gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); + gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); + gBattleMons[battler].ability = GetMonAbility(mon); + gBattleMons[battler].type1 = gBaseStats[gBattleMons[battler].species].type1; + gBattleMons[battler].type2 = gBaseStats[gBattleMons[battler].species].type2; +} diff --git a/src/data/pokemon/base_stats.h b/src/data/pokemon/base_stats.h index a161fbf908..a13ea59391 100644 --- a/src/data/pokemon/base_stats.h +++ b/src/data/pokemon/base_stats.h @@ -24117,7 +24117,7 @@ const struct BaseStats gBaseStats[] = .abilities = {ABILITY_PRIMORDIAL_SEA, ABILITY_PRIMORDIAL_SEA}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_LEGENDARY, + .flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION, }, [SPECIES_GROUDON_PRIMAL] = @@ -24142,7 +24142,7 @@ const struct BaseStats gBaseStats[] = .abilities = {ABILITY_DESOLATE_LAND, ABILITY_DESOLATE_LAND}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_LEGENDARY, + .flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION, }, [SPECIES_RATTATA_ALOLAN] = diff --git a/src/data/pokemon/evolution.h b/src/data/pokemon/evolution.h index 4f09867a6c..0aaf8f90c7 100644 --- a/src/data/pokemon/evolution.h +++ b/src/data/pokemon/evolution.h @@ -293,8 +293,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_METAGROSS] = {{EVO_MEGA_EVOLUTION, ITEM_METAGROSSITE, SPECIES_METAGROSS_MEGA}}, [SPECIES_LATIAS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIASITE, SPECIES_LATIAS_MEGA}}, [SPECIES_LATIOS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIOSITE, SPECIES_LATIOS_MEGA}}, - [SPECIES_KYOGRE] = {{EVO_PRIMAL_REVERSION, ITEM_BLUE_ORB, SPECIES_KYOGRE_PRIMAL}}, - [SPECIES_GROUDON] = {{EVO_PRIMAL_REVERSION, ITEM_RED_ORB, SPECIES_GROUDON_PRIMAL}}, [SPECIES_RAYQUAZA] = {{EVO_MOVE_MEGA_EVOLUTION, MOVE_DRAGON_ASCENT, SPECIES_RAYQUAZA_MEGA}}, #if P_GEN_4_POKEMON == TRUE diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 63971f1325..a0cc805e9a 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -1,5 +1,9 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = { + [SPECIES_KYOGRE] = sKyogreFormChangeTable, + [SPECIES_KYOGRE_PRIMAL] = sKyogreFormChangeTable, + [SPECIES_GROUDON] = sGroudonFormChangeTable, + [SPECIES_GROUDON_PRIMAL] = sGroudonFormChangeTable, #if P_GEN_4_POKEMON == TRUE [SPECIES_GIRATINA] = sGiratinaFormChangeTable, [SPECIES_GIRATINA_ORIGIN] = sGiratinaFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 0586c8ac88..7342256ecd 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -47,6 +47,18 @@ FORM_CHANGE_BATTLE_END: #define DAY 1 #define NIGHT 2 +static const struct FormChange sKyogreFormChangeTable[] = { + {FORM_CHANGE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, + {FORM_CHANGE_BATTLE_END, SPECIES_KYOGRE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGroudonFormChangeTable[] = { + {FORM_CHANGE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, + {FORM_CHANGE_BATTLE_END, SPECIES_GROUDON}, + {FORM_CHANGE_END}, +}; + #if P_GEN_4_POKEMON == TRUE static const struct FormChange sGiratinaFormChangeTable[] = { {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, @@ -178,7 +190,7 @@ static const struct FormChange sXerneasFormChangeTable[] = { static const struct FormChange sHoopaFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, - // {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, + {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, {FORM_CHANGE_END}, }; #endif diff --git a/src/pokemon.c b/src/pokemon.c index b60e5a30ee..ced0f67b9d 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8397,6 +8397,16 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 case FORM_CHANGE_BATTLE_END: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_PRIMAL_REVERSION: + if (arg == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_WITHDRAW: + case FORM_CHANGE_BATTLE_SWITCH: + case FORM_CHANGE_BATTLE_FAINT: + targetSpecies = formChanges[i].targetSpecies; + break; } } } @@ -8485,13 +8495,28 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gBaseStats[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } +void TryFormChange(u32 monId, u32 side, u16 method) +{ + u32 targetSpecies; + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + if (targetSpecies != SPECIES_NONE) + { + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + CalculateMonStats(&party[monId]); + } +} + void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) { int i, j; u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); const struct FormChange *formChanges = gFormChangeTablePointers[species]; - if (formChanges == NULL || (method != FORM_CHANGE_BATTLE_BEGIN && method != FORM_CHANGE_BATTLE_END)) + if (formChanges == NULL + || (method != FORM_CHANGE_BATTLE_BEGIN && method != FORM_CHANGE_BATTLE_END)) return; for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) From a57f6d184b9c0aa9f6d3af6a81aead19ea9e3552 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 1 Nov 2022 12:24:04 -0300 Subject: [PATCH 007/131] Fainting by poison in the overworld reverts forms --- include/constants/pokemon.h | 10 ++++----- src/battle_main.c | 2 +- src/data/pokemon/form_change_tables.h | 32 +++++++++++++-------------- src/field_poison.c | 3 +++ src/pokemon.c | 2 +- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 7dc250834e..06e4be4f34 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -320,11 +320,11 @@ #define FORM_CHANGE_ITEM_HOLD 1 #define FORM_CHANGE_ITEM_USE 2 #define FORM_CHANGE_MOVE 3 // Todo -#define FORM_CHANGE_WITHDRAW 4 // -#define FORM_CHANGE_BATTLE_BEGIN 5 -#define FORM_CHANGE_BATTLE_END 6 -#define FORM_CHANGE_BATTLE_SWITCH 7 -#define FORM_CHANGE_BATTLE_FAINT 8 +#define FORM_CHANGE_WITHDRAW 4 // Daycare done, Todo PC +#define FORM_CHANGE_FAINT 5 +#define FORM_CHANGE_BATTLE_BEGIN 6 +#define FORM_CHANGE_BATTLE_END 7 +#define FORM_CHANGE_BATTLE_SWITCH 8 #define FORM_CHANGE_PRIMAL_REVERSION 9 #define MON_PIC_WIDTH 64 diff --git a/src/battle_main.c b/src/battle_main.c index f58c0d43bb..9d08a4e8c0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3247,7 +3247,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; Ai_UpdateFaintData(gActiveBattler); - TryFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_BATTLE_FAINT); + TryFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_FAINT); if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 7342256ecd..b936808b6a 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -116,20 +116,20 @@ static const struct FormChange sArceusFormChangeTable[] = { static const struct FormChange sDarmanitanFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_DARMANITAN}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN}, {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, {FORM_CHANGE_END}, }; static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN_GALARIAN}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_END}, }; static const struct FormChange sMeloettaFormChangeTable[] = { - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MELOETTA}, + {FORM_CHANGE_FAINT, SPECIES_MELOETTA}, {FORM_CHANGE_BATTLE_END, SPECIES_MELOETTA}, {FORM_CHANGE_END}, }; @@ -170,14 +170,14 @@ static const struct FormChange sGenesectFormChangeTable[] = { #if P_GEN_6_POKEMON == TRUE static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { - {FORM_CHANGE_BATTLE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, {FORM_CHANGE_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, {FORM_CHANGE_END}, }; static const struct FormChange sAegislashFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_AEGISLASH}, + {FORM_CHANGE_FAINT, SPECIES_AEGISLASH}, {FORM_CHANGE_BATTLE_END, SPECIES_AEGISLASH}, {FORM_CHANGE_END}, }; @@ -205,7 +205,7 @@ static const struct FormChange sOricorioFormChangeTable[] = { }; static const struct FormChange sWishiwashiFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_WISHIWASHI}, + {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI}, {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, {FORM_CHANGE_END}, }; @@ -233,50 +233,50 @@ static const struct FormChange sSilvallyFormChangeTable[] = { }; static const struct FormChange sMimikyuFormChangeTable[] = { - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MIMIKYU}, + {FORM_CHANGE_FAINT, SPECIES_MIMIKYU}, {FORM_CHANGE_BATTLE_END, SPECIES_MIMIKYU}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorRedFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorBlueFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorGreenFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorIndigoFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorOrangeFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorVioletFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorYellowFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_END}, }; @@ -286,14 +286,14 @@ static const struct FormChange sMiniorYellowFormChangeTable[] = { #if P_GEN_8_POKEMON == TRUE static const struct FormChange sCramorantFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_CRAMORANT}, + {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, {FORM_CHANGE_END}, }; static const struct FormChange sMorpekoFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, - {FORM_CHANGE_BATTLE_FAINT, SPECIES_MORPEKO}, + {FORM_CHANGE_FAINT, SPECIES_MORPEKO}, {FORM_CHANGE_BATTLE_END, SPECIES_MORPEKO}, {FORM_CHANGE_END}, }; diff --git a/src/field_poison.c b/src/field_poison.c index fcb47acdb8..68a345919b 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -128,7 +128,10 @@ s32 DoPoisonFieldEffect(void) // Apply poison damage hp = GetMonData(pokemon, MON_DATA_HP); if (hp == 0 || --hp == 0) + { + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_FAINT); numFainted++; + } SetMonData(pokemon, MON_DATA_HP, &hp); numPoisoned++; diff --git a/src/pokemon.c b/src/pokemon.c index ced0f67b9d..c296e14136 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8404,7 +8404,7 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 break; case FORM_CHANGE_WITHDRAW: case FORM_CHANGE_BATTLE_SWITCH: - case FORM_CHANGE_BATTLE_FAINT: + case FORM_CHANGE_FAINT: targetSpecies = formChanges[i].targetSpecies; break; } From f5b900e2ef23713aa83096eb843c8fe33785e9b4 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 1 Nov 2022 15:02:22 -0300 Subject: [PATCH 008/131] Defaults Primal Reversion indicator to Alpha when item not Red Orb. --- src/battle_interface.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index ed756592f8..48882bb266 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1563,12 +1563,12 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) } else if (IsBattlerPrimalReverted(battlerId)) { - if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON) + if (gBattleMons[battlerId].item == ITEM_RED_ORB) { LoadSpritePalette(&sSpritePalette_OmegaIndicator); LoadSpriteSheet(&sSpriteSheet_OmegaIndicator); } - else if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_KYOGRE) + else // ITEM_BLUE_ORB { LoadSpritePalette(&sSpritePalette_AlphaIndicator); LoadSpriteSheet(&sSpriteSheet_AlphaIndicator); @@ -1592,9 +1592,9 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) } else if (IsBattlerPrimalReverted(battlerId)) { - if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON) + if (gBattleMons[battlerId].item == ITEM_RED_ORB) spriteId = CreateSpriteAtEnd(&sSpriteTemplate_OmegaIndicator, x, y, 0); - else if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_KYOGRE) + else // ITEM_BLUE_ORB spriteId = CreateSpriteAtEnd(&sSpriteTemplate_AlphaIndicator, x, y, 0); } From fa8b1b9c053fb5360ff0ba2c702acdaad4acc066 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 1 Nov 2022 15:02:45 -0300 Subject: [PATCH 009/131] Updated descriptions of form change constants --- src/data/pokemon/form_change_tables.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index b936808b6a..1f0dc85da1 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -20,11 +20,11 @@ FORM_CHANGE_MOVE: FORM_CHANGE_WITHDRAW: Form change activates when the Pokémon is withdrawn from the PC or Daycare. - no parameters + No parameters. -FORM_CHANGE_SWITCH: - Form change activates when the Pokémon is switched out in battle. - no parameters +FORM_CHANGE_FAINT: + Form change activates when the Pokémon faints, either in battle or in the overworld by poison. + No parameters. FORM_CHANGE_BATTLE_BEGIN: Form change activates when the Pokémon is sent out at the beginning of a battle @@ -37,6 +37,15 @@ FORM_CHANGE_BATTLE_END: param1 = item to hold, optional param2 = a move that will be replaced, optional param3 = a new move to replace it with, optional + +FORM_CHANGE_BATTLE_SWITCH: + Form change activates when the Pokémon is switched out in battle. + No parameters. + +FORM_CHANGE_PRIMAL_REVERSION: + Form change activates when entering battle with the specified item. If the item is a Red Orb, + it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to Alpha. + param1 = item to hold, required. */ // FORM_CHANGE_MOVE param2 Arguments From 797c5514d3a39332f8df1eaba967dc7959bc2eb6 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 1 Nov 2022 18:37:23 -0300 Subject: [PATCH 010/131] Mega Evolution in form change tables --- include/battle.h | 3 - include/battle_util.h | 1 + include/constants/pokemon.h | 6 +- src/battle_interface.c | 13 +- src/battle_script_commands.c | 14 +- src/battle_util.c | 47 +-- src/data/pokemon/evolution.h | 49 --- src/data/pokemon/form_change_table_pointers.h | 94 +++++ src/data/pokemon/form_change_tables.h | 323 ++++++++++++++++++ 9 files changed, 453 insertions(+), 97 deletions(-) diff --git a/include/battle.h b/include/battle.h index ff5d698abf..0ff70ee707 100644 --- a/include/battle.h +++ b/include/battle.h @@ -468,10 +468,7 @@ struct LinkBattlerHeader struct MegaEvolutionData { u8 toEvolve; // As flags using gBitTable. - u8 evolvedPartyIds[2]; // As flags using gBitTable; bool8 alreadyEvolved[4]; // Array id is used for mon position. - u16 evolvedSpecies[MAX_BATTLERS_COUNT]; - u16 playerEvolvedSpecies; u8 battlerId; bool8 playerSelect; u8 triggerSpriteId; diff --git a/include/battle_util.h b/include/battle_util.h index 5a09909509..e1b890ebfe 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -149,6 +149,7 @@ u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId); u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); bool32 CanMegaEvolve(u8 battlerId); void UndoMegaEvolution(u32 monId); +bool32 IsBattlerMegaEvolved(u8 battlerId); bool32 IsBattlerPrimalReverted(u8 battlerId); void TryBattleFormChange(u8 battlerId, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 06e4be4f34..f31fa8d6cc 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -264,8 +264,6 @@ #define F_SUMMARY_SCREEN_FLIP_SPRITE 0x80 // Evolution types -#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle. -#define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item. #define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220 #define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220 #define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220 @@ -325,7 +323,9 @@ #define FORM_CHANGE_BATTLE_BEGIN 6 #define FORM_CHANGE_BATTLE_END 7 #define FORM_CHANGE_BATTLE_SWITCH 8 -#define FORM_CHANGE_PRIMAL_REVERSION 9 +#define FORM_CHANGE_MEGA_EVOLUTION_ITEM 9 +#define FORM_CHANGE_MEGA_EVOLUTION_MOVE 10 +#define FORM_CHANGE_PRIMAL_REVERSION 11 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 diff --git a/src/battle_interface.c b/src/battle_interface.c index 48882bb266..c3d97f1379 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -871,8 +871,7 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId) healthBarSpritePtr->invisible = TRUE; // Create mega indicator sprite if is a mega evolved or a primal reverted mon. - if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) - || IsBattlerPrimalReverted(battlerId)) + if (IsBattlerMegaEvolved(battlerId) || IsBattlerPrimalReverted(battlerId)) { megaIndicatorSpriteId = CreateMegaIndicatorSprite(battlerId, 0); gSprites[megaIndicatorSpriteId].invisible = TRUE; @@ -979,8 +978,7 @@ void SetHealthboxSpriteVisible(u8 healthboxSpriteId) gSprites[healthboxSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE; - if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) - || IsBattlerPrimalReverted(battlerId)) + if (IsBattlerMegaEvolved(battlerId) || IsBattlerPrimalReverted(battlerId)) { u8 spriteId = GetMegaIndicatorSpriteId(healthboxSpriteId); if (spriteId != 0xFF) @@ -1104,8 +1102,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) u8 battler = gSprites[healthboxSpriteId].hMain_Battler; // Don't print Lv char if mon is mega evolved or primal reverted. - if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) - || IsBattlerPrimalReverted(battler)) + if (IsBattlerMegaEvolved(battler) || IsBattlerPrimalReverted(battler)) { objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); xPos = 5 * (3 - (objVram - (text + 2))) - 1; @@ -1556,7 +1553,7 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) u32 spriteId, position; s16 x, y; - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if (IsBattlerMegaEvolved(battlerId)) { LoadSpritePalette(&sSpritePalette_MegaIndicator); LoadSpriteSheet(&sSpriteSheet_MegaIndicator); @@ -1586,7 +1583,7 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) else if (gBattleMons[battlerId].level < 10) x += 5; - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if (IsBattlerMegaEvolved(battlerId)) { spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0); } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 51d3cfbe16..6cc2bc323a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8807,20 +8807,11 @@ static void Cmd_various(void) // Change species. if (gBattlescriptCurrInstr[3] == 0) { - u16 megaSpecies; - gBattleStruct->mega.evolvedSpecies[gActiveBattler] = gBattleMons[gActiveBattler].species; - if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT - || (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)))) - { - gBattleStruct->mega.playerEvolvedSpecies = gBattleStruct->mega.evolvedSpecies[gActiveBattler]; - } //Checks regular Mega Evolution - megaSpecies = GetMegaEvolutionSpecies(gBattleStruct->mega.evolvedSpecies[gActiveBattler], gBattleMons[gActiveBattler].item); + u16 megaSpecies = GetMegaEvolutionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item); //Checks Wish Mega Evolution if (megaSpecies == SPECIES_NONE) - { - megaSpecies = GetWishMegaEvolutionSpecies(gBattleStruct->mega.evolvedSpecies[gActiveBattler], gBattleMons[gActiveBattler].moves[0], gBattleMons[gActiveBattler].moves[1], gBattleMons[gActiveBattler].moves[2], gBattleMons[gActiveBattler].moves[3]); - } + megaSpecies = GetWishMegaEvolutionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].moves[0], gBattleMons[gActiveBattler].moves[1], gBattleMons[gActiveBattler].moves[2], gBattleMons[gActiveBattler].moves[3]); gBattleMons[gActiveBattler].species = megaSpecies; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); @@ -8833,7 +8824,6 @@ static void Cmd_various(void) { RecalcBattlerStats(gActiveBattler, mon); gBattleStruct->mega.alreadyEvolved[GetBattlerPosition(gActiveBattler)] = TRUE; - gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(gActiveBattler)] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]]; } // Update healthbox and elevation. else diff --git a/src/battle_util.c b/src/battle_util.c index 729728ec0e..d4efdb8988 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8953,9 +8953,7 @@ static bool32 CanEvolve(u32 species) for (i = 0; i < EVOS_PER_MON; i++) { - if (gEvolutionTable[species][i].method - && gEvolutionTable[species][i].method != EVO_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION) + if (gEvolutionTable[species][i].method) return TRUE; } return FALSE; @@ -9554,12 +9552,17 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId) u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId) { u32 i; + const struct FormChange *formChanges = gFormChangeTablePointers[preEvoSpecies]; - for (i = 0; i < EVOS_PER_MON; i++) + if (formChanges != NULL) { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_MEGA_EVOLUTION - && gEvolutionTable[preEvoSpecies][i].param == heldItemId) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; + for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + { + if ((formChanges[i].method == FORM_CHANGE_MEGA_EVOLUTION_ITEM + && formChanges[i].param1 == heldItemId) + && formChanges[i].targetSpecies != preEvoSpecies) + return formChanges[i].targetSpecies; + } } return SPECIES_NONE; } @@ -9584,15 +9587,18 @@ u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId) u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4) { - u32 i, par; + u32 i, param; + const struct FormChange *formChanges = gFormChangeTablePointers[preEvoSpecies]; - for (i = 0; i < EVOS_PER_MON; i++) + if (formChanges != NULL) { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_MOVE_MEGA_EVOLUTION) + for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) { - par = gEvolutionTable[preEvoSpecies][i].param; - if (par == moveId1 || par == moveId2 || par == moveId3 || par == moveId4) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; + param = formChanges[i].param1; + if ((formChanges[i].method == FORM_CHANGE_MEGA_EVOLUTION_MOVE + && (param == moveId1 || param == moveId2 || param == moveId3 || param == moveId4)) + && formChanges[i].targetSpecies != preEvoSpecies) + return formChanges[i].targetSpecies; } } return SPECIES_NONE; @@ -9671,16 +9677,8 @@ bool32 CanMegaEvolve(u8 battlerId) void UndoMegaEvolution(u32 monId) { - u16 baseSpecies = GET_BASE_SPECIES_ID(GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES)); - - if (gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] & gBitTable[monId]) - { - gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]); - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->mega.playerEvolvedSpecies); - CalculateMonStats(&gPlayerParty[monId]); - } // While not exactly a mega evolution, Zygarde follows the same rules. - else if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE) + if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE) { SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); gBattleStruct->changedSpecies[monId] = 0; @@ -9688,6 +9686,11 @@ void UndoMegaEvolution(u32 monId) } } +bool32 IsBattlerMegaEvolved(u8 battlerId) +{ + return (gBaseStats[gBattleMons[battlerId].species].flags & SPECIES_FLAG_MEGA_EVOLUTION); +} + bool32 IsBattlerPrimalReverted(u8 battlerId) { return (gBaseStats[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION); diff --git a/src/data/pokemon/evolution.h b/src/data/pokemon/evolution.h index 0aaf8f90c7..20279043fe 100644 --- a/src/data/pokemon/evolution.h +++ b/src/data/pokemon/evolution.h @@ -2,22 +2,16 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = { [SPECIES_BULBASAUR] = {{EVO_LEVEL, 16, SPECIES_IVYSAUR}}, [SPECIES_IVYSAUR] = {{EVO_LEVEL, 32, SPECIES_VENUSAUR}}, - [SPECIES_VENUSAUR] = {{EVO_MEGA_EVOLUTION, ITEM_VENUSAURITE, SPECIES_VENUSAUR_MEGA}}, [SPECIES_CHARMANDER] = {{EVO_LEVEL, 16, SPECIES_CHARMELEON}}, [SPECIES_CHARMELEON] = {{EVO_LEVEL, 36, SPECIES_CHARIZARD}}, - [SPECIES_CHARIZARD] = {{EVO_MEGA_EVOLUTION, ITEM_CHARIZARDITE_X, SPECIES_CHARIZARD_MEGA_X}, - {EVO_MEGA_EVOLUTION, ITEM_CHARIZARDITE_Y, SPECIES_CHARIZARD_MEGA_Y}}, [SPECIES_SQUIRTLE] = {{EVO_LEVEL, 16, SPECIES_WARTORTLE}}, [SPECIES_WARTORTLE] = {{EVO_LEVEL, 36, SPECIES_BLASTOISE}}, - [SPECIES_BLASTOISE] = {{EVO_MEGA_EVOLUTION, ITEM_BLASTOISINITE, SPECIES_BLASTOISE_MEGA}}, [SPECIES_CATERPIE] = {{EVO_LEVEL, 7, SPECIES_METAPOD}}, [SPECIES_METAPOD] = {{EVO_LEVEL, 10, SPECIES_BUTTERFREE}}, [SPECIES_WEEDLE] = {{EVO_LEVEL, 7, SPECIES_KAKUNA}}, [SPECIES_KAKUNA] = {{EVO_LEVEL, 10, SPECIES_BEEDRILL}}, - [SPECIES_BEEDRILL] = {{EVO_MEGA_EVOLUTION, ITEM_BEEDRILLITE, SPECIES_BEEDRILL_MEGA}}, [SPECIES_PIDGEY] = {{EVO_LEVEL, 18, SPECIES_PIDGEOTTO}}, [SPECIES_PIDGEOTTO] = {{EVO_LEVEL, 36, SPECIES_PIDGEOT}}, - [SPECIES_PIDGEOT] = {{EVO_MEGA_EVOLUTION, ITEM_PIDGEOTITE, SPECIES_PIDGEOT_MEGA}}, [SPECIES_RATTATA] = {{EVO_LEVEL, 20, SPECIES_RATICATE}}, [SPECIES_SPEAROW] = {{EVO_LEVEL, 20, SPECIES_FEAROW}}, [SPECIES_EKANS] = {{EVO_LEVEL, 22, SPECIES_ARBOK}}, @@ -48,7 +42,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_TRADE_ITEM, ITEM_KINGS_ROCK, SPECIES_POLITOED}}, [SPECIES_ABRA] = {{EVO_LEVEL, 16, SPECIES_KADABRA}}, [SPECIES_KADABRA] = {{EVO_TRADE, 0, SPECIES_ALAKAZAM}}, - [SPECIES_ALAKAZAM] = {{EVO_MEGA_EVOLUTION, ITEM_ALAKAZITE, SPECIES_ALAKAZAM_MEGA}}, [SPECIES_MACHOP] = {{EVO_LEVEL, 28, SPECIES_MACHOKE}}, [SPECIES_MACHOKE] = {{EVO_TRADE, 0, SPECIES_MACHAMP}}, [SPECIES_BELLSPROUT] = {{EVO_LEVEL, 21, SPECIES_WEEPINBELL}}, @@ -59,7 +52,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_PONYTA] = {{EVO_LEVEL, 40, SPECIES_RAPIDASH}}, [SPECIES_SLOWPOKE] = {{EVO_LEVEL, 37, SPECIES_SLOWBRO}, {EVO_TRADE_ITEM, ITEM_KINGS_ROCK, SPECIES_SLOWKING}}, - [SPECIES_SLOWBRO] = {{EVO_MEGA_EVOLUTION, ITEM_SLOWBRONITE, SPECIES_SLOWBRO_MEGA}}, [SPECIES_MAGNEMITE] = {{EVO_LEVEL, 30, SPECIES_MAGNETON}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_MAGNETON] = {{EVO_MAPSEC, MAPSEC_NEW_MAUVILLE, SPECIES_MAGNEZONE}, @@ -71,7 +63,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_SHELLDER] = {{EVO_ITEM, ITEM_WATER_STONE, SPECIES_CLOYSTER}}, [SPECIES_GASTLY] = {{EVO_LEVEL, 25, SPECIES_HAUNTER}}, [SPECIES_HAUNTER] = {{EVO_TRADE, 0, SPECIES_GENGAR}}, - [SPECIES_GENGAR] = {{EVO_MEGA_EVOLUTION, ITEM_GENGARITE, SPECIES_GENGAR_MEGA}}, [SPECIES_ONIX] = {{EVO_TRADE_ITEM, ITEM_METAL_COAT, SPECIES_STEELIX}}, [SPECIES_DROWZEE] = {{EVO_LEVEL, 26, SPECIES_HYPNO}}, [SPECIES_KRABBY] = {{EVO_LEVEL, 28, SPECIES_KINGLER}}, @@ -92,7 +83,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_TANGELA] = {{EVO_MOVE, MOVE_ANCIENT_POWER, SPECIES_TANGROWTH}}, #endif - [SPECIES_KANGASKHAN] = {{EVO_MEGA_EVOLUTION, ITEM_KANGASKHANITE, SPECIES_KANGASKHAN_MEGA}}, [SPECIES_HORSEA] = {{EVO_LEVEL, 32, SPECIES_SEADRA}}, [SPECIES_SEADRA] = {{EVO_TRADE_ITEM, ITEM_DRAGON_SCALE, SPECIES_KINGDRA}}, [SPECIES_GOLDEEN] = {{EVO_LEVEL, 33, SPECIES_SEAKING}}, @@ -102,9 +92,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_ELECTABUZZ] = {{EVO_TRADE_ITEM, ITEM_ELECTIRIZER, SPECIES_ELECTIVIRE}}, [SPECIES_MAGMAR] = {{EVO_TRADE_ITEM, ITEM_MAGMARIZER, SPECIES_MAGMORTAR}}, #endif - [SPECIES_PINSIR] = {{EVO_MEGA_EVOLUTION, ITEM_PINSIRITE, SPECIES_PINSIR_MEGA}}, [SPECIES_MAGIKARP] = {{EVO_LEVEL, 20, SPECIES_GYARADOS}}, - [SPECIES_GYARADOS] = {{EVO_MEGA_EVOLUTION, ITEM_GYARADOSITE, SPECIES_GYARADOS_MEGA}}, [SPECIES_EEVEE] = {{EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_JOLTEON}, {EVO_ITEM, ITEM_WATER_STONE, SPECIES_VAPOREON}, {EVO_ITEM, ITEM_FIRE_STONE, SPECIES_FLAREON}, @@ -123,11 +111,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_PORYGON] = {{EVO_TRADE_ITEM, ITEM_UPGRADE, SPECIES_PORYGON2}}, [SPECIES_OMANYTE] = {{EVO_LEVEL, 40, SPECIES_OMASTAR}}, [SPECIES_KABUTO] = {{EVO_LEVEL, 40, SPECIES_KABUTOPS}}, - [SPECIES_AERODACTYL] = {{EVO_MEGA_EVOLUTION, ITEM_AERODACTYLITE, SPECIES_AERODACTYL_MEGA}}, [SPECIES_DRATINI] = {{EVO_LEVEL, 30, SPECIES_DRAGONAIR}}, [SPECIES_DRAGONAIR] = {{EVO_LEVEL, 55, SPECIES_DRAGONITE}}, - [SPECIES_MEWTWO] = {{EVO_MEGA_EVOLUTION, ITEM_MEWTWONITE_X, SPECIES_MEWTWO_MEGA_X}, - {EVO_MEGA_EVOLUTION, ITEM_MEWTWONITE_Y, SPECIES_MEWTWO_MEGA_Y}}, [SPECIES_CHIKORITA] = {{EVO_LEVEL, 16, SPECIES_BAYLEEF}}, [SPECIES_BAYLEEF] = {{EVO_LEVEL, 32, SPECIES_MEGANIUM}}, [SPECIES_CYNDAQUIL] = {{EVO_LEVEL, 14, SPECIES_QUILAVA}}, @@ -149,7 +134,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_NATU] = {{EVO_LEVEL, 25, SPECIES_XATU}}, [SPECIES_MAREEP] = {{EVO_LEVEL, 15, SPECIES_FLAAFFY}}, [SPECIES_FLAAFFY] = {{EVO_LEVEL, 30, SPECIES_AMPHAROS}}, - [SPECIES_AMPHAROS] = {{EVO_MEGA_EVOLUTION, ITEM_AMPHAROSITE, SPECIES_AMPHAROS_MEGA}}, [SPECIES_MARILL] = {{EVO_LEVEL, 18, SPECIES_AZUMARILL}}, [SPECIES_HOPPIP] = {{EVO_LEVEL, 18, SPECIES_SKIPLOOM}}, [SPECIES_SKIPLOOM] = {{EVO_LEVEL, 27, SPECIES_JUMPLUFF}}, @@ -167,10 +151,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_GLIGAR] = {{EVO_ITEM_HOLD_NIGHT, ITEM_RAZOR_FANG, SPECIES_GLISCOR}}, #endif - [SPECIES_STEELIX] = {{EVO_MEGA_EVOLUTION, ITEM_STEELIXITE, SPECIES_STEELIX_MEGA}}, [SPECIES_SNUBBULL] = {{EVO_LEVEL, 23, SPECIES_GRANBULL}}, - [SPECIES_SCIZOR] = {{EVO_MEGA_EVOLUTION, ITEM_SCIZORITE, SPECIES_SCIZOR_MEGA}}, - [SPECIES_HERACROSS] = {{EVO_MEGA_EVOLUTION, ITEM_HERACRONITE, SPECIES_HERACROSS_MEGA}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_SNEASEL] = {{EVO_ITEM_HOLD_NIGHT, ITEM_RAZOR_CLAW, SPECIES_WEAVILE}}, #endif @@ -182,7 +163,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #endif [SPECIES_REMORAID] = {{EVO_LEVEL, 25, SPECIES_OCTILLERY}}, [SPECIES_HOUNDOUR] = {{EVO_LEVEL, 24, SPECIES_HOUNDOOM}}, - [SPECIES_HOUNDOOM] = {{EVO_MEGA_EVOLUTION, ITEM_HOUNDOOMINITE, SPECIES_HOUNDOOM_MEGA}}, [SPECIES_PHANPY] = {{EVO_LEVEL, 25, SPECIES_DONPHAN}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_PORYGON2] = {{EVO_TRADE_ITEM, ITEM_DUBIOUS_DISC, SPECIES_PORYGON_Z}}, @@ -195,16 +175,12 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_MAGBY] = {{EVO_LEVEL, 30, SPECIES_MAGMAR}}, [SPECIES_LARVITAR] = {{EVO_LEVEL, 30, SPECIES_PUPITAR}}, [SPECIES_PUPITAR] = {{EVO_LEVEL, 55, SPECIES_TYRANITAR}}, - [SPECIES_TYRANITAR] = {{EVO_MEGA_EVOLUTION, ITEM_TYRANITARITE, SPECIES_TYRANITAR_MEGA}}, [SPECIES_TREECKO] = {{EVO_LEVEL, 16, SPECIES_GROVYLE}}, [SPECIES_GROVYLE] = {{EVO_LEVEL, 36, SPECIES_SCEPTILE}}, - [SPECIES_SCEPTILE] = {{EVO_MEGA_EVOLUTION, ITEM_SCEPTILITE, SPECIES_SCEPTILE_MEGA}}, [SPECIES_TORCHIC] = {{EVO_LEVEL, 16, SPECIES_COMBUSKEN}}, [SPECIES_COMBUSKEN] = {{EVO_LEVEL, 36, SPECIES_BLAZIKEN}}, - [SPECIES_BLAZIKEN] = {{EVO_MEGA_EVOLUTION, ITEM_BLAZIKENITE, SPECIES_BLAZIKEN_MEGA}}, [SPECIES_MUDKIP] = {{EVO_LEVEL, 16, SPECIES_MARSHTOMP}}, [SPECIES_MARSHTOMP] = {{EVO_LEVEL, 36, SPECIES_SWAMPERT}}, - [SPECIES_SWAMPERT] = {{EVO_MEGA_EVOLUTION, ITEM_SWAMPERTITE, SPECIES_SWAMPERT_MEGA}}, [SPECIES_POOCHYENA] = {{EVO_LEVEL, 18, SPECIES_MIGHTYENA}}, [SPECIES_ZIGZAGOON] = {{EVO_LEVEL, 20, SPECIES_LINOONE}}, [SPECIES_WURMPLE] = {{EVO_LEVEL_SILCOON, 7, SPECIES_SILCOON}, @@ -227,20 +203,16 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_NOSEPASS] = {{EVO_MAPSEC, MAPSEC_NEW_MAUVILLE, SPECIES_PROBOPASS}}, #endif - [SPECIES_SABLEYE] = {{EVO_MEGA_EVOLUTION, ITEM_SABLENITE, SPECIES_SABLEYE_MEGA}}, [SPECIES_BARBOACH] = {{EVO_LEVEL, 30, SPECIES_WHISCASH}}, [SPECIES_CORPHISH] = {{EVO_LEVEL, 30, SPECIES_CRAWDAUNT}}, [SPECIES_FEEBAS] = {{EVO_BEAUTY, 170, SPECIES_MILOTIC}, {EVO_TRADE_ITEM, ITEM_PRISM_SCALE, SPECIES_MILOTIC}}, [SPECIES_CARVANHA] = {{EVO_LEVEL, 30, SPECIES_SHARPEDO}}, - [SPECIES_SHARPEDO] = {{EVO_MEGA_EVOLUTION, ITEM_SHARPEDONITE, SPECIES_SHARPEDO_MEGA}}, [SPECIES_TRAPINCH] = {{EVO_LEVEL, 35, SPECIES_VIBRAVA}}, [SPECIES_VIBRAVA] = {{EVO_LEVEL, 45, SPECIES_FLYGON}}, [SPECIES_MAKUHITA] = {{EVO_LEVEL, 24, SPECIES_HARIYAMA}}, [SPECIES_ELECTRIKE] = {{EVO_LEVEL, 26, SPECIES_MANECTRIC}}, - [SPECIES_MANECTRIC] = {{EVO_MEGA_EVOLUTION, ITEM_MANECTITE, SPECIES_MANECTRIC_MEGA}}, [SPECIES_NUMEL] = {{EVO_LEVEL, 33, SPECIES_CAMERUPT}}, - [SPECIES_CAMERUPT] = {{EVO_MEGA_EVOLUTION, ITEM_CAMERUPTITE, SPECIES_CAMERUPT_MEGA}}, [SPECIES_SPHEAL] = {{EVO_LEVEL, 32, SPECIES_SEALEO}}, [SPECIES_SEALEO] = {{EVO_LEVEL, 44, SPECIES_WALREIN}}, [SPECIES_CACNEA] = {{EVO_LEVEL, 32, SPECIES_CACTURNE}}, @@ -249,14 +221,10 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM_FEMALE, ITEM_DAWN_STONE, SPECIES_FROSLASS} #endif }, - [SPECIES_GLALIE] = {{EVO_MEGA_EVOLUTION, ITEM_GLALITITE, SPECIES_GLALIE_MEGA}}, [SPECIES_AZURILL] = {{EVO_FRIENDSHIP, 0, SPECIES_MARILL}}, [SPECIES_SPOINK] = {{EVO_LEVEL, 32, SPECIES_GRUMPIG}}, - [SPECIES_MAWILE] = {{EVO_MEGA_EVOLUTION, ITEM_MAWILITE, SPECIES_MAWILE_MEGA}}, [SPECIES_MEDITITE] = {{EVO_LEVEL, 37, SPECIES_MEDICHAM}}, - [SPECIES_MEDICHAM] = {{EVO_MEGA_EVOLUTION, ITEM_MEDICHAMITE, SPECIES_MEDICHAM_MEGA}}, [SPECIES_SWABLU] = {{EVO_LEVEL, 35, SPECIES_ALTARIA}}, - [SPECIES_ALTARIA] = {{EVO_MEGA_EVOLUTION, ITEM_ALTARIANITE, SPECIES_ALTARIA_MEGA}}, [SPECIES_WYNAUT] = {{EVO_LEVEL, 15, SPECIES_WOBBUFFET}}, [SPECIES_DUSKULL] = {{EVO_LEVEL, 37, SPECIES_DUSCLOPS}}, #if P_GEN_4_POKEMON == TRUE @@ -270,12 +238,9 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_LOUDRED] = {{EVO_LEVEL, 40, SPECIES_EXPLOUD}}, [SPECIES_CLAMPERL] = {{EVO_TRADE_ITEM, ITEM_DEEP_SEA_TOOTH, SPECIES_HUNTAIL}, {EVO_TRADE_ITEM, ITEM_DEEP_SEA_SCALE, SPECIES_GOREBYSS}}, - [SPECIES_ABSOL] = {{EVO_MEGA_EVOLUTION, ITEM_ABSOLITE, SPECIES_ABSOL_MEGA}}, [SPECIES_SHUPPET] = {{EVO_LEVEL, 37, SPECIES_BANETTE}}, - [SPECIES_BANETTE] = {{EVO_MEGA_EVOLUTION, ITEM_BANETTITE, SPECIES_BANETTE_MEGA}}, [SPECIES_ARON] = {{EVO_LEVEL, 32, SPECIES_LAIRON}}, [SPECIES_LAIRON] = {{EVO_LEVEL, 42, SPECIES_AGGRON}}, - [SPECIES_AGGRON] = {{EVO_MEGA_EVOLUTION, ITEM_AGGRONITE, SPECIES_AGGRON_MEGA}}, [SPECIES_LILEEP] = {{EVO_LEVEL, 40, SPECIES_CRADILY}}, [SPECIES_ANORITH] = {{EVO_LEVEL, 40, SPECIES_ARMALDO}}, [SPECIES_RALTS] = {{EVO_LEVEL, 20, SPECIES_KIRLIA}}, @@ -284,17 +249,10 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM_MALE, ITEM_DAWN_STONE, SPECIES_GALLADE} #endif }, - [SPECIES_GARDEVOIR] = {{EVO_MEGA_EVOLUTION, ITEM_GARDEVOIRITE, SPECIES_GARDEVOIR_MEGA}}, [SPECIES_BAGON] = {{EVO_LEVEL, 30, SPECIES_SHELGON}}, [SPECIES_SHELGON] = {{EVO_LEVEL, 50, SPECIES_SALAMENCE}}, - [SPECIES_SALAMENCE] = {{EVO_MEGA_EVOLUTION, ITEM_SALAMENCITE, SPECIES_SALAMENCE_MEGA}}, [SPECIES_BELDUM] = {{EVO_LEVEL, 20, SPECIES_METANG}}, [SPECIES_METANG] = {{EVO_LEVEL, 45, SPECIES_METAGROSS}}, - [SPECIES_METAGROSS] = {{EVO_MEGA_EVOLUTION, ITEM_METAGROSSITE, SPECIES_METAGROSS_MEGA}}, - [SPECIES_LATIAS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIASITE, SPECIES_LATIAS_MEGA}}, - [SPECIES_LATIOS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIOSITE, SPECIES_LATIOS_MEGA}}, - [SPECIES_RAYQUAZA] = {{EVO_MOVE_MEGA_EVOLUTION, MOVE_DRAGON_ASCENT, SPECIES_RAYQUAZA_MEGA}}, - #if P_GEN_4_POKEMON == TRUE // Gens 4-7 [SPECIES_TURTWIG] = {{EVO_LEVEL, 18, SPECIES_GROTLE}}, @@ -320,7 +278,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_SHELLOS] = {{EVO_LEVEL, 30, SPECIES_GASTRODON}}, [SPECIES_DRIFLOON] = {{EVO_LEVEL, 28, SPECIES_DRIFBLIM}}, [SPECIES_BUNEARY] = {{EVO_FRIENDSHIP, 0, SPECIES_LOPUNNY}}, - [SPECIES_LOPUNNY] = {{EVO_MEGA_EVOLUTION, ITEM_LOPUNNITE, SPECIES_LOPUNNY_MEGA}}, [SPECIES_GLAMEOW] = {{EVO_LEVEL, 38, SPECIES_PURUGLY}}, [SPECIES_CHINGLING] = {{EVO_FRIENDSHIP_NIGHT, 0, SPECIES_CHIMECHO}}, [SPECIES_STUNKY] = {{EVO_LEVEL, 34, SPECIES_SKUNTANK}}, @@ -330,18 +287,14 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_HAPPINY] = {{EVO_ITEM_HOLD_DAY, ITEM_OVAL_STONE, SPECIES_CHANSEY}}, [SPECIES_GIBLE] = {{EVO_LEVEL, 24, SPECIES_GABITE}}, [SPECIES_GABITE] = {{EVO_LEVEL, 48, SPECIES_GARCHOMP}}, - [SPECIES_GARCHOMP] = {{EVO_MEGA_EVOLUTION, ITEM_GARCHOMPITE, SPECIES_GARCHOMP_MEGA}}, [SPECIES_MUNCHLAX] = {{EVO_FRIENDSHIP, 0, SPECIES_SNORLAX}}, [SPECIES_RIOLU] = {{EVO_FRIENDSHIP_DAY, 0, SPECIES_LUCARIO}}, - [SPECIES_LUCARIO] = {{EVO_MEGA_EVOLUTION, ITEM_LUCARIONITE, SPECIES_LUCARIO_MEGA}}, [SPECIES_HIPPOPOTAS] = {{EVO_LEVEL, 34, SPECIES_HIPPOWDON}}, [SPECIES_SKORUPI] = {{EVO_LEVEL, 40, SPECIES_DRAPION}}, [SPECIES_CROAGUNK] = {{EVO_LEVEL, 37, SPECIES_TOXICROAK}}, [SPECIES_FINNEON] = {{EVO_LEVEL, 31, SPECIES_LUMINEON}}, [SPECIES_MANTYKE] = {{EVO_SPECIFIC_MON_IN_PARTY, SPECIES_REMORAID, SPECIES_MANTINE}}, [SPECIES_SNOVER] = {{EVO_LEVEL, 40, SPECIES_ABOMASNOW}}, - [SPECIES_ABOMASNOW] = {{EVO_MEGA_EVOLUTION, ITEM_ABOMASITE, SPECIES_ABOMASNOW_MEGA}}, - [SPECIES_GALLADE] = {{EVO_MEGA_EVOLUTION, ITEM_GALLADITE, SPECIES_GALLADE_MEGA}}, #endif #if P_GEN_5_POKEMON == TRUE [SPECIES_SNIVY] = {{EVO_LEVEL, 17, SPECIES_SERVINE}}, @@ -365,7 +318,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_BOLDORE] = {{EVO_TRADE, 0, SPECIES_GIGALITH}}, [SPECIES_WOOBAT] = {{EVO_FRIENDSHIP, 0, SPECIES_SWOOBAT}}, [SPECIES_DRILBUR] = {{EVO_LEVEL, 31, SPECIES_EXCADRILL}}, - [SPECIES_AUDINO] = {{EVO_MEGA_EVOLUTION, ITEM_AUDINITE, SPECIES_AUDINO_MEGA}}, [SPECIES_TIMBURR] = {{EVO_LEVEL, 25, SPECIES_GURDURR}}, [SPECIES_GURDURR] = {{EVO_TRADE, 0, SPECIES_CONKELDURR}}, [SPECIES_TYMPOLE] = {{EVO_LEVEL, 25, SPECIES_PALPITOAD}}, @@ -456,7 +408,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_PUMPKABOO] = {{EVO_TRADE, 0, SPECIES_GOURGEIST}}, [SPECIES_BERGMITE] = {{EVO_LEVEL, 37, SPECIES_AVALUGG}}, [SPECIES_NOIBAT] = {{EVO_LEVEL, 48, SPECIES_NOIVERN}}, - [SPECIES_DIANCIE] = {{EVO_MEGA_EVOLUTION, ITEM_DIANCITE, SPECIES_DIANCIE_MEGA}}, #endif #if P_GEN_7_POKEMON == TRUE [SPECIES_ROWLET] = {{EVO_LEVEL, 17, SPECIES_DARTRIX}}, diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index a0cc805e9a..d69ced5bf2 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -1,10 +1,100 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = { + [SPECIES_VENUSAUR] = sVenusaurFormChangeTable, + [SPECIES_VENUSAUR_MEGA] = sVenusaurFormChangeTable, + [SPECIES_CHARIZARD] = sCharizardFormChangeTable, + [SPECIES_CHARIZARD_MEGA_X] = sCharizardFormChangeTable, + [SPECIES_CHARIZARD_MEGA_Y] = sCharizardFormChangeTable, + [SPECIES_BLASTOISE] = sBlastoiseFormChangeTable, + [SPECIES_BLASTOISE_MEGA] = sBlastoiseFormChangeTable, + [SPECIES_BEEDRILL] = sBeedrillFormChangeTable, + [SPECIES_BEEDRILL_MEGA] = sBeedrillFormChangeTable, + [SPECIES_PIDGEOT] = sPidgeotFormChangeTable, + [SPECIES_PIDGEOT_MEGA] = sPidgeotFormChangeTable, + [SPECIES_ALAKAZAM] = sAlakazamFormChangeTable, + [SPECIES_ALAKAZAM_MEGA] = sAlakazamFormChangeTable, + [SPECIES_SLOWBRO] = sSlowbroFormChangeTable, + [SPECIES_SLOWBRO_MEGA] = sSlowbroFormChangeTable, + [SPECIES_GENGAR] = sGengarFormChangeTable, + [SPECIES_GENGAR_MEGA] = sGengarFormChangeTable, + [SPECIES_KANGASKHAN] = sKangaskhanFormChangeTable, + [SPECIES_KANGASKHAN_MEGA] = sKangaskhanFormChangeTable, + [SPECIES_PINSIR] = sPinsirFormChangeTable, + [SPECIES_PINSIR_MEGA] = sPinsirFormChangeTable, + [SPECIES_GYARADOS] = sGyaradosFormChangeTable, + [SPECIES_GYARADOS_MEGA] = sGyaradosFormChangeTable, + [SPECIES_AERODACTYL] = sAerodactylFormChangeTable, + [SPECIES_AERODACTYL_MEGA] = sAerodactylFormChangeTable, + [SPECIES_MEWTWO] = sMewtwoFormChangeTable, + [SPECIES_MEWTWO_MEGA_X] = sMewtwoFormChangeTable, + [SPECIES_MEWTWO_MEGA_Y] = sMewtwoFormChangeTable, + [SPECIES_AMPHAROS] = sAmpharosFormChangeTable, + [SPECIES_AMPHAROS_MEGA] = sAmpharosFormChangeTable, + [SPECIES_STEELIX] = sSteelixFormChangeTable, + [SPECIES_STEELIX_MEGA] = sSteelixFormChangeTable, + [SPECIES_SCIZOR] = sScizorFormChangeTable, + [SPECIES_SCIZOR_MEGA] = sScizorFormChangeTable, + [SPECIES_HERACROSS] = sHeracrossFormChangeTable, + [SPECIES_HERACROSS_MEGA] = sHeracrossFormChangeTable, + [SPECIES_HOUNDOOM] = sHoundoomFormChangeTable, + [SPECIES_HOUNDOOM_MEGA] = sHoundoomFormChangeTable, + [SPECIES_TYRANITAR] = sTyranitarFormChangeTable, + [SPECIES_TYRANITAR_MEGA] = sTyranitarFormChangeTable, + [SPECIES_SCEPTILE] = sSceptileFormChangeTable, + [SPECIES_SCEPTILE_MEGA] = sSceptileFormChangeTable, + [SPECIES_BLAZIKEN] = sBlazikenFormChangeTable, + [SPECIES_BLAZIKEN_MEGA] = sBlazikenFormChangeTable, + [SPECIES_SWAMPERT] = sSwampertFormChangeTable, + [SPECIES_SWAMPERT_MEGA] = sSwampertFormChangeTable, + [SPECIES_SABLEYE] = sSableyeFormChangeTable, + [SPECIES_SABLEYE_MEGA] = sSableyeFormChangeTable, + [SPECIES_SHARPEDO] = sSharpedoFormChangeTable, + [SPECIES_SHARPEDO_MEGA] = sSharpedoFormChangeTable, + [SPECIES_MANECTRIC] = sManectricFormChangeTable, + [SPECIES_MANECTRIC_MEGA] = sManectricFormChangeTable, + [SPECIES_CAMERUPT] = sCameruptFormChangeTable, + [SPECIES_CAMERUPT_MEGA] = sCameruptFormChangeTable, + [SPECIES_GLALIE] = sGlalieFormChangeTable, + [SPECIES_GLALIE_MEGA] = sGlalieFormChangeTable, + [SPECIES_MAWILE] = sMawileFormChangeTable, + [SPECIES_MAWILE_MEGA] = sMawileFormChangeTable, + [SPECIES_MEDICHAM] = sMedichamFormChangeTable, + [SPECIES_MEDICHAM_MEGA] = sMedichamFormChangeTable, + [SPECIES_ALTARIA] = sAltariaFormChangeTable, + [SPECIES_ALTARIA_MEGA] = sAltariaFormChangeTable, + [SPECIES_ABSOL] = sAbsolFormChangeTable, + [SPECIES_ABSOL_MEGA] = sAbsolFormChangeTable, + [SPECIES_BANETTE] = sBanetteFormChangeTable, + [SPECIES_BANETTE_MEGA] = sBanetteFormChangeTable, + [SPECIES_AGGRON] = sAggronFormChangeTable, + [SPECIES_AGGRON_MEGA] = sAggronFormChangeTable, + [SPECIES_GARDEVOIR] = sGardevoirFormChangeTable, + [SPECIES_GARDEVOIR_MEGA] = sGardevoirFormChangeTable, + [SPECIES_SALAMENCE] = sSalamenceFormChangeTable, + [SPECIES_SALAMENCE_MEGA] = sSalamenceFormChangeTable, + [SPECIES_METAGROSS] = sMetagrossFormChangeTable, + [SPECIES_METAGROSS_MEGA] = sMetagrossFormChangeTable, + [SPECIES_LATIAS] = sLatiasFormChangeTable, + [SPECIES_LATIAS_MEGA] = sLatiasFormChangeTable, + [SPECIES_LATIOS] = sLatiosFormChangeTable, + [SPECIES_LATIOS_MEGA] = sLatiosFormChangeTable, [SPECIES_KYOGRE] = sKyogreFormChangeTable, [SPECIES_KYOGRE_PRIMAL] = sKyogreFormChangeTable, [SPECIES_GROUDON] = sGroudonFormChangeTable, [SPECIES_GROUDON_PRIMAL] = sGroudonFormChangeTable, + [SPECIES_RAYQUAZA] = sRayquazaFormChangeTable, + [SPECIES_RAYQUAZA_MEGA] = sRayquazaFormChangeTable, #if P_GEN_4_POKEMON == TRUE + [SPECIES_LOPUNNY] = sLopunnyFormChangeTable, + [SPECIES_LOPUNNY_MEGA] = sLopunnyFormChangeTable, + [SPECIES_GARCHOMP] = sGarchompFormChangeTable, + [SPECIES_GARCHOMP_MEGA] = sGarchompFormChangeTable, + [SPECIES_LUCARIO] = sLucarioFormChangeTable, + [SPECIES_LUCARIO_MEGA] = sLucarioFormChangeTable, + [SPECIES_ABOMASNOW] = sAbomasnowFormChangeTable, + [SPECIES_ABOMASNOW_MEGA] = sAbomasnowFormChangeTable, + [SPECIES_GALLADE] = sGalladeFormChangeTable, + [SPECIES_GALLADE_MEGA] = sGalladeFormChangeTable, [SPECIES_GIRATINA] = sGiratinaFormChangeTable, [SPECIES_GIRATINA_ORIGIN] = sGiratinaFormChangeTable, [SPECIES_SHAYMIN] = sShayminFormChangeTable, @@ -29,6 +119,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ARCEUS_FAIRY] = sArceusFormChangeTable, #endif #if P_GEN_5_POKEMON == TRUE + [SPECIES_AUDINO] = sAudinoFormChangeTable, + [SPECIES_AUDINO_MEGA] = sAudinoFormChangeTable, [SPECIES_DARMANITAN] = sDarmanitanFormChangeTable, [SPECIES_DARMANITAN_ZEN_MODE] = sDarmanitanFormChangeTable, [SPECIES_DARMANITAN_GALARIAN] = sDarmanitanGalarianFormChangeTable, @@ -56,6 +148,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_AEGISLASH_BLADE] = sAegislashFormChangeTable, [SPECIES_XERNEAS] = sXerneasFormChangeTable, [SPECIES_XERNEAS_ACTIVE] = sXerneasFormChangeTable, + [SPECIES_DIANCIE] = sDiancieFormChangeTable, + [SPECIES_DIANCIE_MEGA] = sDiancieFormChangeTable, [SPECIES_HOOPA] = sHoopaFormChangeTable, [SPECIES_HOOPA_UNBOUND] = sHoopaFormChangeTable, #endif diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 1f0dc85da1..9c0b2d8666 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -56,6 +56,274 @@ FORM_CHANGE_PRIMAL_REVERSION: #define DAY 1 #define NIGHT 2 +static const struct FormChange sVenusaurFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, + {FORM_CHANGE_FAINT, SPECIES_VENUSAUR}, + {FORM_CHANGE_BATTLE_END, SPECIES_VENUSAUR}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sCharizardFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_X, ITEM_CHARIZARDITE_X}, + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_Y, ITEM_CHARIZARDITE_Y}, + {FORM_CHANGE_FAINT, SPECIES_CHARIZARD}, + {FORM_CHANGE_BATTLE_END, SPECIES_CHARIZARD}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sBlastoiseFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, + {FORM_CHANGE_FAINT, SPECIES_BLASTOISE}, + {FORM_CHANGE_BATTLE_END, SPECIES_BLASTOISE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sBeedrillFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, + {FORM_CHANGE_FAINT, SPECIES_BEEDRILL}, + {FORM_CHANGE_BATTLE_END, SPECIES_BEEDRILL}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sPidgeotFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, + {FORM_CHANGE_FAINT, SPECIES_PIDGEOT}, + {FORM_CHANGE_BATTLE_END, SPECIES_PIDGEOT}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAlakazamFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, + {FORM_CHANGE_FAINT, SPECIES_ALAKAZAM}, + {FORM_CHANGE_BATTLE_END, SPECIES_ALAKAZAM}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSlowbroFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, + {FORM_CHANGE_FAINT, SPECIES_SLOWBRO}, + {FORM_CHANGE_BATTLE_END, SPECIES_SLOWBRO}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGengarFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, + {FORM_CHANGE_FAINT, SPECIES_GENGAR}, + {FORM_CHANGE_BATTLE_END, SPECIES_GENGAR}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sKangaskhanFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, + {FORM_CHANGE_FAINT, SPECIES_KANGASKHAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_KANGASKHAN}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sPinsirFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, + {FORM_CHANGE_FAINT, SPECIES_PINSIR}, + {FORM_CHANGE_BATTLE_END, SPECIES_PINSIR}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGyaradosFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, + {FORM_CHANGE_FAINT, SPECIES_GYARADOS}, + {FORM_CHANGE_BATTLE_END, SPECIES_GYARADOS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAerodactylFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, + {FORM_CHANGE_FAINT, SPECIES_AERODACTYL}, + {FORM_CHANGE_BATTLE_END, SPECIES_AERODACTYL}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMewtwoFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_X, ITEM_MEWTWONITE_X}, + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_Y, ITEM_MEWTWONITE_Y}, + {FORM_CHANGE_FAINT, SPECIES_MEWTWO}, + {FORM_CHANGE_BATTLE_END, SPECIES_MEWTWO}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAmpharosFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, + {FORM_CHANGE_FAINT, SPECIES_AMPHAROS}, + {FORM_CHANGE_BATTLE_END, SPECIES_AMPHAROS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSteelixFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, + {FORM_CHANGE_FAINT, SPECIES_STEELIX}, + {FORM_CHANGE_BATTLE_END, SPECIES_STEELIX}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sScizorFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, + {FORM_CHANGE_FAINT, SPECIES_SCIZOR}, + {FORM_CHANGE_BATTLE_END, SPECIES_SCIZOR}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sHeracrossFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, + {FORM_CHANGE_FAINT, SPECIES_HERACROSS}, + {FORM_CHANGE_BATTLE_END, SPECIES_HERACROSS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sHoundoomFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, + {FORM_CHANGE_FAINT, SPECIES_HOUNDOOM}, + {FORM_CHANGE_BATTLE_END, SPECIES_HOUNDOOM}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sTyranitarFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, + {FORM_CHANGE_FAINT, SPECIES_TYRANITAR}, + {FORM_CHANGE_BATTLE_END, SPECIES_TYRANITAR}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSceptileFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, + {FORM_CHANGE_FAINT, SPECIES_SCEPTILE}, + {FORM_CHANGE_BATTLE_END, SPECIES_SCEPTILE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sBlazikenFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, + {FORM_CHANGE_FAINT, SPECIES_BLAZIKEN}, + {FORM_CHANGE_BATTLE_END, SPECIES_BLAZIKEN}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSwampertFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, + {FORM_CHANGE_FAINT, SPECIES_SWAMPERT}, + {FORM_CHANGE_BATTLE_END, SPECIES_SWAMPERT}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSableyeFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, + {FORM_CHANGE_FAINT, SPECIES_SABLEYE}, + {FORM_CHANGE_BATTLE_END, SPECIES_SABLEYE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSharpedoFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, + {FORM_CHANGE_FAINT, SPECIES_SHARPEDO}, + {FORM_CHANGE_BATTLE_END, SPECIES_SHARPEDO}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sManectricFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, + {FORM_CHANGE_FAINT, SPECIES_MANECTRIC}, + {FORM_CHANGE_BATTLE_END, SPECIES_MANECTRIC}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sCameruptFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, + {FORM_CHANGE_FAINT, SPECIES_CAMERUPT}, + {FORM_CHANGE_BATTLE_END, SPECIES_CAMERUPT}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGlalieFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, + {FORM_CHANGE_FAINT, SPECIES_GLALIE}, + {FORM_CHANGE_BATTLE_END, SPECIES_GLALIE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMawileFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, + {FORM_CHANGE_FAINT, SPECIES_MAWILE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MAWILE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMedichamFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, + {FORM_CHANGE_FAINT, SPECIES_MEDICHAM}, + {FORM_CHANGE_BATTLE_END, SPECIES_MEDICHAM}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAltariaFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, + {FORM_CHANGE_FAINT, SPECIES_ALTARIA}, + {FORM_CHANGE_BATTLE_END, SPECIES_ALTARIA}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAbsolFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, + {FORM_CHANGE_FAINT, SPECIES_ABSOL}, + {FORM_CHANGE_BATTLE_END, SPECIES_ABSOL}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sBanetteFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, + {FORM_CHANGE_FAINT, SPECIES_BANETTE}, + {FORM_CHANGE_BATTLE_END, SPECIES_BANETTE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAggronFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, + {FORM_CHANGE_FAINT, SPECIES_AGGRON}, + {FORM_CHANGE_BATTLE_END, SPECIES_AGGRON}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGardevoirFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, + {FORM_CHANGE_FAINT, SPECIES_GARDEVOIR}, + {FORM_CHANGE_BATTLE_END, SPECIES_GARDEVOIR}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sSalamenceFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, + {FORM_CHANGE_FAINT, SPECIES_SALAMENCE}, + {FORM_CHANGE_BATTLE_END, SPECIES_SALAMENCE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sMetagrossFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, + {FORM_CHANGE_FAINT, SPECIES_METAGROSS}, + {FORM_CHANGE_BATTLE_END, SPECIES_METAGROSS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sLatiasFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, + {FORM_CHANGE_FAINT, SPECIES_LATIAS}, + {FORM_CHANGE_BATTLE_END, SPECIES_LATIAS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sLatiosFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, + {FORM_CHANGE_FAINT, SPECIES_LATIOS}, + {FORM_CHANGE_BATTLE_END, SPECIES_LATIOS}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sKyogreFormChangeTable[] = { {FORM_CHANGE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, {FORM_CHANGE_BATTLE_END, SPECIES_KYOGRE}, @@ -68,7 +336,49 @@ static const struct FormChange sGroudonFormChangeTable[] = { {FORM_CHANGE_END}, }; +static const struct FormChange sRayquazaFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, + {FORM_CHANGE_FAINT, SPECIES_RAYQUAZA}, + {FORM_CHANGE_BATTLE_END, SPECIES_RAYQUAZA}, + {FORM_CHANGE_END}, +}; + #if P_GEN_4_POKEMON == TRUE +static const struct FormChange sLopunnyFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, + {FORM_CHANGE_FAINT, SPECIES_LOPUNNY}, + {FORM_CHANGE_BATTLE_END, SPECIES_LOPUNNY}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGarchompFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, + {FORM_CHANGE_FAINT, SPECIES_GARCHOMP}, + {FORM_CHANGE_BATTLE_END, SPECIES_GARCHOMP}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sLucarioFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, + {FORM_CHANGE_FAINT, SPECIES_LUCARIO}, + {FORM_CHANGE_BATTLE_END, SPECIES_LUCARIO}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sAbomasnowFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, + {FORM_CHANGE_FAINT, SPECIES_ABOMASNOW}, + {FORM_CHANGE_BATTLE_END, SPECIES_ABOMASNOW}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sGalladeFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, + {FORM_CHANGE_FAINT, SPECIES_GALLADE}, + {FORM_CHANGE_BATTLE_END, SPECIES_GALLADE}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sGiratinaFormChangeTable[] = { {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, @@ -122,6 +432,12 @@ static const struct FormChange sArceusFormChangeTable[] = { #endif #if P_GEN_5_POKEMON == TRUE +static const struct FormChange sAudinoFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, + {FORM_CHANGE_FAINT, SPECIES_AUDINO}, + {FORM_CHANGE_BATTLE_END, SPECIES_AUDINO}, + {FORM_CHANGE_END}, +}; static const struct FormChange sDarmanitanFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN}, @@ -197,6 +513,13 @@ static const struct FormChange sXerneasFormChangeTable[] = { {FORM_CHANGE_END}, }; +static const struct FormChange sDiancieFormChangeTable[] = { + {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, + {FORM_CHANGE_FAINT, SPECIES_DIANCIE}, + {FORM_CHANGE_BATTLE_END, SPECIES_DIANCIE}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sHoopaFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, From 15c12af2cf9d51731e8ca9b9cce3f2d3adf7e97f Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 1 Nov 2022 23:50:26 -0300 Subject: [PATCH 011/131] Using TryBattleFormChange in place of certain TryFormChange --- include/battle_util.h | 2 ++ include/pokemon.h | 2 +- src/battle_main.c | 2 +- src/battle_script_commands.c | 14 +++----------- src/battle_util.c | 25 +++++++++++++++++-------- src/pokemon.c | 4 +++- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index e1b890ebfe..120c0b7e91 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -188,6 +188,8 @@ void TryToRevertMimicry(void); void RestoreBattlerOriginalTypes(u8 battlerId); u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); +void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon); +void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon); void RecalcBattlerStats(u32 battler, struct Pokemon *mon); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/include/pokemon.h b/include/pokemon.h index 134991b953..10b132f48a 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -565,7 +565,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); bool32 ShouldShowFemaleDifferences(u16 species, u32 personality); -void TryFormChange(u32 monId, u32 side, u16 method); +bool32 TryFormChange(u32 monId, u32 side, u16 method); void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); u32 GetMonFriendshipScore(struct Pokemon *pokemon); diff --git a/src/battle_main.c b/src/battle_main.c index 9d08a4e8c0..6afae7d9c3 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3247,7 +3247,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; Ai_UpdateFaintData(gActiveBattler); - TryFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_FAINT); + TryBattleFormChange(gActiveBattler, FORM_CHANGE_FAINT); if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6cc2bc323a..d2de985a75 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4213,15 +4213,7 @@ static void Cmd_getexp(void) if (battlerId != 0xFF) { - gBattleMons[battlerId].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); - gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP); - gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); - gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); - gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); - gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); - gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); - gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPDEF); - + CopyMonLevelAndBaseStatsToBattleMon(battlerId, &gPlayerParty[gBattleStruct->expGetterMonId]); if (gStatuses3[battlerId] & STATUS3_POWER_TRICK) SWAP(gBattleMons[battlerId].attack, gBattleMons[battlerId].defense, temp); } @@ -14064,7 +14056,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - TryFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_END); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -14118,7 +14110,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - TryFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END), + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_END); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); diff --git a/src/battle_util.c b/src/battle_util.c index d4efdb8988..7709fa59ec 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -518,7 +518,7 @@ void HandleAction_Switch(void) if (gBattleResults.playerSwitchesCounter < 255) gBattleResults.playerSwitchesCounter++; - TryFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), FORM_CHANGE_BATTLE_SWITCH); + TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_SWITCH); } void HandleAction_UseItem(void) @@ -9698,16 +9698,14 @@ bool32 IsBattlerPrimalReverted(u8 battlerId) void TryBattleFormChange(u8 battlerId, u16 method) { - u16 targetSpecies; u8 monId = gBattlerPartyIndexes[battlerId]; u8 side = GET_BATTLER_SIDE(battlerId); struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies != SPECIES_NONE) + if (TryFormChange(monId, side, method)) { - SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); - RecalcBattlerStats(battlerId, &party[monId]); + CopyMonLevelAndBaseStatsToBattleMon(battlerId, &party[monId]); + CopyMonAbilityAndTypesToBattleMon(battlerId, &party[monId]); } } @@ -10370,9 +10368,8 @@ bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move) return TRUE; } -void RecalcBattlerStats(u32 battler, struct Pokemon *mon) +void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon) { - CalculateMonStats(mon); gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); @@ -10381,7 +10378,19 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon) gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); +} + +void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon) +{ gBattleMons[battler].ability = GetMonAbility(mon); gBattleMons[battler].type1 = gBaseStats[gBattleMons[battler].species].type1; gBattleMons[battler].type2 = gBaseStats[gBattleMons[battler].species].type2; + gBattleMons[battler].type3 = TYPE_MYSTERY; +} + +void RecalcBattlerStats(u32 battler, struct Pokemon *mon) +{ + CalculateMonStats(mon); + CopyMonLevelAndBaseStatsToBattleMon(battler, mon); + CopyMonAbilityAndTypesToBattleMon(battler, mon); } diff --git a/src/pokemon.c b/src/pokemon.c index c296e14136..d4f14b5b9b 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8495,7 +8495,7 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gBaseStats[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } -void TryFormChange(u32 monId, u32 side, u16 method) +bool32 TryFormChange(u32 monId, u32 side, u16 method) { u32 targetSpecies; struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; @@ -8506,7 +8506,9 @@ void TryFormChange(u32 monId, u32 side, u16 method) TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); CalculateMonStats(&party[monId]); + return TRUE; } + return FALSE; } void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) From 8b0a8484247f09a809fc97c0b966b1b154880a62 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 1 Nov 2022 23:53:04 -0300 Subject: [PATCH 012/131] Zen Mode triggers at the beginning of a battle --- src/battle_util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 7709fa59ec..544eef1fd2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4735,6 +4735,8 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; + // Fallthrough + case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: if (ShouldChangeFormHpBased(battler)) { @@ -4954,6 +4956,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; + // Fallthrough case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: if ((effect = ShouldChangeFormHpBased(battler))) From 271bff5675f69781dcae95c3696347806df9e746 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 2 Nov 2022 10:06:02 -0300 Subject: [PATCH 013/131] Gen 5+ stat recalculate in the same party loop at the end of battle that changes forms. --- src/battle_main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 6afae7d9c3..df8e245510 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5203,18 +5203,15 @@ static void HandleEndTurn_FinishBattle(void) UndoMegaEvolution(i); TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); DoBurmyFormChange(i); - } - #if B_RECALCULATE_STATS >= GEN_5 - // Recalculate the stats of every party member before the end - for (i = 0; i < PARTY_SIZE; i++) - { + #if B_RECALCULATE_STATS >= GEN_5 + // Recalculate the stats of every party member before the end if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) != SPECIES_NONE && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) != SPECIES_EGG) { CalculateMonStats(&gPlayerParty[i]); } + #endif } - #endif // Clear battle mon species to avoid a bug on the next battle that causes // healthboxes loading incorrectly due to it trying to create a Mega Indicator // if the previous battler would've had. From 42f8e8c11461cc09830c143c14f953e42d23b79e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 5 Nov 2022 20:00:12 -0300 Subject: [PATCH 014/131] Multiple refactors - Added a general GetBattleFormChangeTargetSpecies instead of getting specific ones for Mega Evolution and Primal Reversion. - Added FORM_CHANGE_BATTLE_HP_PERCENT, to replace ShouldChangeFormHpBased. - Cleaned ifdefs for hold effects. - Finally removed UndoMegaEvolution. - FORM_CHANGE_FAINT and FORM_CHANGE_BATTLE_END restore to the first form before a battle form change if species isn't specified. - When changing from a form with more HP to one with less, now current HP is kept to fix Zygarde edge case. (Will likely need to be reworked for Dynamax, as it behaves differently) - Uses DoesSpeciesUseHoldItemToChangeForm in CanBattlerGetOrLoseItem. --- include/battle_util.h | 8 +- include/constants/pokemon.h | 11 +- include/pokemon.h | 3 +- src/battle_ai_main.c | 4 - src/battle_main.c | 15 +- src/battle_script_commands.c | 8 +- src/battle_util.c | 258 +++++++++--------- src/data/pokemon/form_change_table_pointers.h | 3 + src/data/pokemon/form_change_tables.h | 120 +++++--- src/daycare.c | 3 +- src/pokemon.c | 47 +++- 11 files changed, 272 insertions(+), 208 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 120c0b7e91..4f263e8da9 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -144,14 +144,12 @@ u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 bat u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); u16 GetTypeModifier(u8 atkType, u8 defType); s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId); -u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId); -u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId); -u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); +bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId); bool32 CanMegaEvolve(u8 battlerId); -void UndoMegaEvolution(u32 monId); bool32 IsBattlerMegaEvolved(u8 battlerId); bool32 IsBattlerPrimalReverted(u8 battlerId); -void TryBattleFormChange(u8 battlerId, u16 method); +u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method); +bool32 TryBattleFormChange(u8 battlerId, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); struct Pokemon *GetIllusionMonPtr(u32 battlerId); diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index f31fa8d6cc..31b7e72fbe 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -323,9 +323,14 @@ #define FORM_CHANGE_BATTLE_BEGIN 6 #define FORM_CHANGE_BATTLE_END 7 #define FORM_CHANGE_BATTLE_SWITCH 8 -#define FORM_CHANGE_MEGA_EVOLUTION_ITEM 9 -#define FORM_CHANGE_MEGA_EVOLUTION_MOVE 10 -#define FORM_CHANGE_PRIMAL_REVERSION 11 +#define FORM_CHANGE_BATTLE_HP_PERCENT 9 +#define FORM_CHANGE_MEGA_EVOLUTION_ITEM 10 +#define FORM_CHANGE_MEGA_EVOLUTION_MOVE 11 +#define FORM_CHANGE_PRIMAL_REVERSION 12 + +// FORM_CHANGE_BATTLE_HP_PERCENT param2 arguments +#define HP_HIGHER_THAN 1 +#define HP_LOWER_EQ_THAN 2 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 diff --git a/include/pokemon.h b/include/pokemon.h index 10b132f48a..f7f5ea6deb 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -562,7 +562,8 @@ u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum); u16 GetFormSpeciesId(u16 speciesId, u8 formId); u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId); u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); -u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg); +u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg); +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); bool32 ShouldShowFemaleDifferences(u16 species, u32 personality); bool32 TryFormChange(u32 monId, u32 side, u16 method); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index b1154e7934..0998d0a485 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3043,12 +3043,8 @@ static bool32 IsPinchBerryItemEffect(u16 holdEffect) case HOLD_EFFECT_SP_DEFENSE_UP: case HOLD_EFFECT_CRITICAL_UP: case HOLD_EFFECT_RANDOM_STAT_UP: - #ifdef HOLD_EFFECT_CUSTAP_BERRY case HOLD_EFFECT_CUSTAP_BERRY: - #endif - #ifdef HOLD_EFFECT_MICLE_BERRY case HOLD_EFFECT_MICLE_BERRY: - #endif return TRUE; } diff --git a/src/battle_main.c b/src/battle_main.c index df8e245510..907fb1aa40 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3248,8 +3248,6 @@ void FaintClearSetData(void) Ai_UpdateFaintData(gActiveBattler); TryBattleFormChange(gActiveBattler, FORM_CHANGE_FAINT); - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) - UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); gBattleStruct->overwrittenAbilities[gActiveBattler] = ABILITY_NONE; @@ -3683,7 +3681,7 @@ static void TryDoEventsBeforeFirstTurn(void) for (i = 0; i < gBattlersCount; i++) { if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB - && GetPrimalReversionSpecies(gBattleMons[i].species, gBattleMons[i].item) != SPECIES_NONE) + && GetBattleFormChangeTargetSpecies(i, FORM_CHANGE_PRIMAL_REVERSION) != SPECIES_NONE) { gBattlerAttacker = i; BattleScriptExecute(BattleScript_PrimalReversion); @@ -5200,16 +5198,15 @@ static void HandleEndTurn_FinishBattle(void) #endif for (i = 0; i < PARTY_SIZE; i++) { - UndoMegaEvolution(i); - TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); + bool32 changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); DoBurmyFormChange(i); + // Clear original species field + gBattleStruct->changedSpecies[i] = SPECIES_NONE; + #if B_RECALCULATE_STATS >= GEN_5 // Recalculate the stats of every party member before the end - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) != SPECIES_EGG) - { + if (!changedForm) CalculateMonStats(&gPlayerParty[i]); - } #endif } // Clear battle mon species to avoid a bug on the next battle that causes diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d2de985a75..5ea145c057 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8800,10 +8800,10 @@ static void Cmd_various(void) if (gBattlescriptCurrInstr[3] == 0) { //Checks regular Mega Evolution - u16 megaSpecies = GetMegaEvolutionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item); + u16 megaSpecies = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_MEGA_EVOLUTION_ITEM); //Checks Wish Mega Evolution if (megaSpecies == SPECIES_NONE) - megaSpecies = GetWishMegaEvolutionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].moves[0], gBattleMons[gActiveBattler].moves[1], gBattleMons[gActiveBattler].moves[2], gBattleMons[gActiveBattler].moves[3]); + megaSpecies = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_MEGA_EVOLUTION_MOVE); gBattleMons[gActiveBattler].species = megaSpecies; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); @@ -8836,7 +8836,7 @@ static void Cmd_various(void) // Change species. if (gBattlescriptCurrInstr[3] == 0) { - gBattleMons[gActiveBattler].species = GetPrimalReversionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item); + gBattleMons[gActiveBattler].species = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_PRIMAL_REVERSION); PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], sizeof(gBattleMons[gActiveBattler].species), &gBattleMons[gActiveBattler].species); @@ -9561,7 +9561,7 @@ static void Cmd_various(void) return; case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: { - if (GetPrimalReversionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item) == SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_PRIMAL_REVERSION) == SPECIES_NONE) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else gBattlescriptCurrInstr += 7; diff --git a/src/battle_util.c b/src/battle_util.c index 544eef1fd2..27b8cf945e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4170,51 +4170,6 @@ static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer) return FALSE; } -static bool32 ShouldChangeFormHpBased(u32 battler) -{ - // Ability, form >, form <=, hp divided - static const u16 forms[][4] = - { - {ABILITY_ZEN_MODE, SPECIES_DARMANITAN, SPECIES_DARMANITAN_ZEN_MODE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_BLUE, SPECIES_MINIOR_CORE_BLUE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_GREEN, SPECIES_MINIOR_CORE_GREEN, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_INDIGO, SPECIES_MINIOR_CORE_INDIGO, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_ORANGE, SPECIES_MINIOR_CORE_ORANGE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, 2}, - {ABILITY_SCHOOLING, SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, 4}, - {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GORGING, 2}, - {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GULPING, 1}, - {ABILITY_ZEN_MODE, SPECIES_DARMANITAN_GALARIAN, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, 2}, - }; - u32 i; - u16 battlerAbility = GetBattlerAbility(battler); - - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - return FALSE; - - for (i = 0; i < ARRAY_COUNT(forms); i++) - { - if (battlerAbility == forms[i][0]) - { - if (gBattleMons[battler].species == forms[i][2] - && gBattleMons[battler].hp > gBattleMons[battler].maxHP / forms[i][3]) - { - gBattleMons[battler].species = forms[i][1]; - return TRUE; - } - if (gBattleMons[battler].species == forms[i][1] - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / forms[i][3]) - { - gBattleMons[battler].species = forms[i][2]; - return TRUE; - } - } - } - return FALSE; -} - static u8 ForewarnChooseMove(u32 battler) { struct Forewarn { @@ -4738,7 +4693,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move // Fallthrough case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - if (ShouldChangeFormHpBased(battler)) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); effect++; @@ -4959,15 +4914,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move // Fallthrough case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - if ((effect = ShouldChangeFormHpBased(battler))) - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); - break; case ABILITY_POWER_CONSTRUCT: - if ((gBattleMons[battler].species == SPECIES_ZYGARDE || gBattleMons[battler].species == SPECIES_ZYGARDE_10) - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; - gBattleMons[battler].species = SPECIES_ZYGARDE_COMPLETE; BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); effect++; } @@ -5614,7 +5563,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move { if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -5628,7 +5576,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -5681,7 +5628,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move break; case ABILITY_GULP_MISSILE: if (((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) - && (effect = ShouldChangeFormHpBased(gBattlerAttacker))) + && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerFormChange; @@ -9552,59 +9499,27 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId) return TRUE; } -u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId) +bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) { u32 i; - const struct FormChange *formChanges = gFormChangeTablePointers[preEvoSpecies]; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; if (formChanges != NULL) { for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) { - if ((formChanges[i].method == FORM_CHANGE_MEGA_EVOLUTION_ITEM - && formChanges[i].param1 == heldItemId) - && formChanges[i].targetSpecies != preEvoSpecies) - return formChanges[i].targetSpecies; + switch (formChanges[i].method) + { + case FORM_CHANGE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_PRIMAL_REVERSION: + case FORM_CHANGE_ITEM_HOLD: + if (formChanges[i].param1 == heldItemId) + return TRUE; + break; + } } } - return SPECIES_NONE; -} - -u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId) -{ - u32 i; - const struct FormChange *formChanges = gFormChangeTablePointers[preSpecies]; - - if (formChanges != NULL) - { - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) - { - if (formChanges[i].method == FORM_CHANGE_PRIMAL_REVERSION - && formChanges[i].param1 == heldItemId - && formChanges[i].targetSpecies != preSpecies) - return formChanges[i].targetSpecies; - } - } - return SPECIES_NONE; -} - -u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4) -{ - u32 i, param; - const struct FormChange *formChanges = gFormChangeTablePointers[preEvoSpecies]; - - if (formChanges != NULL) - { - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) - { - param = formChanges[i].param1; - if ((formChanges[i].method == FORM_CHANGE_MEGA_EVOLUTION_MOVE - && (param == moveId1 || param == moveId2 || param == moveId3 || param == moveId4)) - && formChanges[i].targetSpecies != preEvoSpecies) - return formChanges[i].targetSpecies; - } - } - return SPECIES_NONE; + return FALSE; } bool32 CanMegaEvolve(u8 battlerId) @@ -9647,7 +9562,7 @@ bool32 CanMegaEvolve(u8 battlerId) itemId = GetMonData(mon, MON_DATA_HELD_ITEM); // Check if there is an entry in the evolution table for regular Mega Evolution. - if (GetMegaEvolutionSpecies(species, itemId) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) { #if B_ENABLE_DEBUG == TRUE if (B_ENABLE_DEBUG && gBattleStruct->debugHoldEffects[battlerId]) @@ -9668,7 +9583,7 @@ bool32 CanMegaEvolve(u8 battlerId) } // Check if there is an entry in the evolution table for Wish Mega Evolution. - if (GetWishMegaEvolutionSpecies(species, GetMonData(mon, MON_DATA_MOVE1), GetMonData(mon, MON_DATA_MOVE2), GetMonData(mon, MON_DATA_MOVE3), GetMonData(mon, MON_DATA_MOVE4))) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) { gBattleStruct->mega.isWishMegaEvo = TRUE; return TRUE; @@ -9678,17 +9593,6 @@ bool32 CanMegaEvolve(u8 battlerId) return FALSE; } -void UndoMegaEvolution(u32 monId) -{ - // While not exactly a mega evolution, Zygarde follows the same rules. - if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE) - { - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); - gBattleStruct->changedSpecies[monId] = 0; - CalculateMonStats(&gPlayerParty[monId]); - } -} - bool32 IsBattlerMegaEvolved(u8 battlerId) { return (gBaseStats[gBattleMons[battlerId].species].flags & SPECIES_FLAG_MEGA_EVOLUTION); @@ -9699,17 +9603,121 @@ bool32 IsBattlerPrimalReverted(u8 battlerId) return (gBaseStats[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION); } -void TryBattleFormChange(u8 battlerId, u16 method) +// Returns SPECIES_NONE if no form change is possible +u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) +{ + u32 i, j; + u16 targetSpecies = SPECIES_NONE; + u16 species = gBattleMons[battlerId].species; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; + u16 heldItem; + u32 ability; + + if (formChanges != NULL) + { + heldItem = gBattleMons[battlerId].item; + ability = GetBattlerAbility(battlerId); + + for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + { + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + { + switch (method) + { + case FORM_CHANGE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_PRIMAL_REVERSION: + if (heldItem == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_MEGA_EVOLUTION_MOVE: + if (gBattleMons[battlerId].moves[0] == formChanges[i].param1 + || gBattleMons[battlerId].moves[1] == formChanges[i].param1 + || gBattleMons[battlerId].moves[2] == formChanges[i].param1 + || gBattleMons[battlerId].moves[3] == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_SWITCH: + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_HP_PERCENT: + { + if (formChanges[i].param1 == GetBattlerAbility(battlerId)) + { + // We multiply by 100 to make sure that integer division doesn't mess with the health check. + u32 hpCheck = gBattleMons[battlerId].hp * 100 * 100 / gBattleMons[battlerId].maxHP; + switch(formChanges[i].param2) + { + case HP_HIGHER_THAN: + if (hpCheck > formChanges[i].param3 * 100) + targetSpecies = formChanges[i].targetSpecies; + break; + case HP_LOWER_EQ_THAN: + if (hpCheck <= formChanges[i].param3 * 100) + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + break; + } + } + } + } + } + + return targetSpecies; +} + +bool32 TryBattleFormChange(u8 battlerId, u16 method) { u8 monId = gBattlerPartyIndexes[battlerId]; u8 side = GET_BATTLER_SIDE(battlerId); struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + u16 targetSpecies; - if (TryFormChange(monId, side, method)) + // Can't change form if transformed. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; + + if (!DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method)) + return FALSE; + + targetSpecies = GetBattleFormChangeTargetSpecies(battlerId, method); + if (targetSpecies != SPECIES_NONE) { - CopyMonLevelAndBaseStatsToBattleMon(battlerId, &party[monId]); - CopyMonAbilityAndTypesToBattleMon(battlerId, &party[monId]); + // Saves the original species on the first form change. + if (gBattleStruct->changedSpecies[monId] == SPECIES_NONE) + gBattleStruct->changedSpecies[monId] = gBattleMons[battlerId].species; + + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + gBattleMons[battlerId].species = targetSpecies; + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; } + + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + if (targetSpecies != SPECIES_NONE) + { + // Saves the original species on the first form change. + if (gBattleStruct->changedSpecies[monId] == SPECIES_NONE) + gBattleStruct->changedSpecies[monId] = targetSpecies; + + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + gBattleMons[battlerId].species = targetSpecies; + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; + } + else if ((method == FORM_CHANGE_BATTLE_END || method == FORM_CHANGE_FAINT) + && gBattleStruct->changedSpecies[monId] != SPECIES_NONE) + { + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; + } + + return FALSE; } bool32 DoBattlersShareType(u32 battler1, u32 battler2) @@ -9740,24 +9748,10 @@ bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId) // Mail can be stolen now if (itemId == ITEM_ENIGMA_BERRY_E_READER) return FALSE; - // Primal Reversion inducing items cannot be lost if pokemon's base species can undergo primal reversion with it. - else if (holdEffect == HOLD_EFFECT_PRIMAL_ORB && (GetPrimalReversionSpecies(GET_BASE_SPECIES_ID(species), itemId) != SPECIES_NONE)) + else if (DoesSpeciesUseHoldItemToChangeForm(species, itemId)) return FALSE; - // Mega stone cannot be lost if pokemon's base species can mega evolve with it. - else if (holdEffect == HOLD_EFFECT_MEGA_STONE && (GetMegaEvolutionSpecies(GET_BASE_SPECIES_ID(species), itemId) != SPECIES_NONE)) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_GIRATINA && itemId == ITEM_GRISEOUS_ORB) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_GENESECT && holdEffect == HOLD_EFFECT_DRIVE) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_SILVALLY && holdEffect == HOLD_EFFECT_MEMORY) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_ARCEUS && holdEffect == HOLD_EFFECT_PLATE) - return FALSE; -#ifdef HOLD_EFFECT_Z_CRYSTAL else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) return FALSE; -#endif else return TRUE; } diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index d69ced5bf2..06d5825a2d 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -148,6 +148,9 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_AEGISLASH_BLADE] = sAegislashFormChangeTable, [SPECIES_XERNEAS] = sXerneasFormChangeTable, [SPECIES_XERNEAS_ACTIVE] = sXerneasFormChangeTable, + [SPECIES_ZYGARDE_10_POWER_CONSTRUCT] = sZygardePowerConstructFormChangeTable, + [SPECIES_ZYGARDE_50_POWER_CONSTRUCT] = sZygardePowerConstructFormChangeTable, + [SPECIES_ZYGARDE_COMPLETE] = sZygardePowerConstructFormChangeTable, [SPECIES_DIANCIE] = sDiancieFormChangeTable, [SPECIES_DIANCIE_MEGA] = sDiancieFormChangeTable, [SPECIES_HOOPA] = sHoopaFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 9c0b2d8666..1df1d7581d 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -24,6 +24,8 @@ FORM_CHANGE_WITHDRAW: FORM_CHANGE_FAINT: Form change activates when the Pokémon faints, either in battle or in the overworld by poison. + If species is not specified and it's on the player's side, it will try to use the value + saved in gBattleStruct->changedSpecies from a previous form change. No parameters. FORM_CHANGE_BATTLE_BEGIN: @@ -33,7 +35,8 @@ FORM_CHANGE_BATTLE_BEGIN: param3 = a new move to replace it with, optional FORM_CHANGE_BATTLE_END: - Form change activates at the end of a battle + Form change activates at the end of a battle. If species is not specified and it's on the player's side, + it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. param1 = item to hold, optional param2 = a move that will be replaced, optional param3 = a new move to replace it with, optional @@ -42,10 +45,27 @@ FORM_CHANGE_BATTLE_SWITCH: Form change activates when the Pokémon is switched out in battle. No parameters. +FORM_CHANGE_BATTLE_HP_PERCENT: + Form change activates when the Pokémon's HP % passes a certain threshold. + param1 = Ability to check. + param2 = HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. + HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. + param3 = HP percentage threshold. + +FORM_CHANGE_MEGA_EVOLUTION_ITEM: + Form change activates when the mon has the defined item. If it's on the player's side, it also requires + ITEM_MEGA_RING in the user's bag and for the player to choose to enable it. + param1 = item to hold. + +FORM_CHANGE_MEGA_EVOLUTION_MOVE: + Form change activates when the mon has the defined move. If it's on the player's side, it also requires + ITEM_MEGA_RING in the user's bag and for the player to choose to enable it. + param1 = move to have. + FORM_CHANGE_PRIMAL_REVERSION: - Form change activates when entering battle with the specified item. If the item is a Red Orb, + Form change activates automatically when entering battle with the specified item. If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to Alpha. - param1 = item to hold, required. + param1 = item to hold. */ // FORM_CHANGE_MOVE param2 Arguments @@ -440,16 +460,18 @@ static const struct FormChange sAudinoFormChangeTable[] = { }; static const struct FormChange sDarmanitanFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN}, - {FORM_CHANGE_FAINT, SPECIES_DARMANITAN}, - {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, {FORM_CHANGE_END}, }; static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_DARMANITAN_GALARIAN}, - {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN}, - {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_GALARIAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, {FORM_CHANGE_END}, }; @@ -513,6 +535,13 @@ static const struct FormChange sXerneasFormChangeTable[] = { {FORM_CHANGE_END}, }; +static const struct FormChange sZygardePowerConstructFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_ZYGARDE_COMPLETE, ABILITY_POWER_CONSTRUCT, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT}, + {FORM_CHANGE_BATTLE_END}, + {FORM_CHANGE_END}, +}; + static const struct FormChange sDiancieFormChangeTable[] = { {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, {FORM_CHANGE_FAINT, SPECIES_DIANCIE}, @@ -536,9 +565,11 @@ static const struct FormChange sOricorioFormChangeTable[] = { {FORM_CHANGE_END}, }; static const struct FormChange sWishiwashiFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, - {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI}, - {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI_SCHOOL, ABILITY_SCHOOLING, HP_HIGHER_THAN, 25}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI, ABILITY_SCHOOLING, HP_LOWER_EQ_THAN, 25}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, + {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI}, + {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, {FORM_CHANGE_END}, }; @@ -571,55 +602,70 @@ static const struct FormChange sMimikyuFormChangeTable[] = { }; static const struct FormChange sMiniorRedFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_RED}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_RED, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorBlueFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_BLUE}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_BLUE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_BLUE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorGreenFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_GREEN}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_GREEN, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_GREEN, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorIndigoFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_INDIGO, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_INDIGO, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorOrangeFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_ORANGE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_ORANGE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorVioletFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_VIOLET, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_VIOLET, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_END}, }; static const struct FormChange sMiniorYellowFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, - {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_YELLOW, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_YELLOW, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_END}, }; - #endif #if P_GEN_8_POKEMON == TRUE static const struct FormChange sCramorantFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, - {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, - {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GULPING, ABILITY_GULP_MISSILE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GORGING, ABILITY_GULP_MISSILE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, + {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, + {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, {FORM_CHANGE_END}, }; diff --git a/src/daycare.c b/src/daycare.c index fc44e200e6..82280077bd 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -256,7 +256,8 @@ static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) BoxMonToMon(&daycareMon->mon, &pokemon); newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_CHANGE_WITHDRAW, 0); - if (newSpecies != SPECIES_NONE) { + if (newSpecies != SPECIES_NONE) + { SetMonData(&pokemon, MON_DATA_SPECIES, &newSpecies); CalculateMonStats(&pokemon); species = newSpecies; diff --git a/src/pokemon.c b/src/pokemon.c index d4f14b5b9b..0fc69a35f2 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3999,13 +3999,14 @@ void CalculateMonStats(struct Pokemon *mon) { if (currentHP == 0 && oldMaxHP == 0) currentHP = newMaxHP; - else if (currentHP != 0) { - // BUG: currentHP is unintentionally able to become <= 0 after the instruction below. This causes the pomeg berry glitch. - currentHP += newMaxHP - oldMaxHP; - #ifdef BUGFIX + else if (currentHP != 0) + { + if (newMaxHP > oldMaxHP) + currentHP += newMaxHP - oldMaxHP; if (currentHP <= 0) currentHP = 1; - #endif + if (currentHP > newMaxHP) + currentHP = newMaxHP; } else return; @@ -8397,13 +8398,8 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 case FORM_CHANGE_BATTLE_END: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; - break; - case FORM_CHANGE_PRIMAL_REVERSION: - if (arg == formChanges[i].param1) - targetSpecies = formChanges[i].targetSpecies; - break; + break; case FORM_CHANGE_WITHDRAW: - case FORM_CHANGE_BATTLE_SWITCH: case FORM_CHANGE_FAINT: targetSpecies = formChanges[i].targetSpecies; break; @@ -8415,6 +8411,23 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 return targetSpecies; } +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method) +{ + u32 i, j; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; + + if (formChanges != NULL) + { + for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + { + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + return TRUE; + } + } + + return FALSE; +} + u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); @@ -8495,12 +8508,21 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gBaseStats[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } +// Returns species that it transformed into. If it didn't, returns SPECIES_NONE. bool32 TryFormChange(u32 monId, u32 side, u16 method) { - u32 targetSpecies; struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + u16 targetSpecies; + + if (GetMonData(&party[monId], MON_DATA_SPECIES2, 0) == SPECIES_NONE + || GetMonData(&party[monId], MON_DATA_SPECIES2, 0) == SPECIES_EGG) + return FALSE; targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + + if (targetSpecies == SPECIES_NONE) + targetSpecies = gBattleStruct->changedSpecies[monId]; + if (targetSpecies != SPECIES_NONE) { TryToSetBattleFormChangeMoves(&party[monId], method); @@ -8508,6 +8530,7 @@ bool32 TryFormChange(u32 monId, u32 side, u16 method) CalculateMonStats(&party[monId]); return TRUE; } + return FALSE; } From 8f289714b2037c2d01bc7d6826aa6e527b630632 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 5 Nov 2022 20:57:55 -0300 Subject: [PATCH 015/131] Moved form change defines and descriptions to their own header --- include/battle.h | 1 + include/constants/form_change_types.h | 81 +++++++++++++++++++++++++++ include/constants/pokemon.h | 19 ------- src/data/pokemon/form_change_tables.h | 78 -------------------------- src/daycare.c | 1 + src/field_poison.c | 1 + src/party_menu.c | 1 + src/pokemon.c | 1 + src/pokemon_storage_system.c | 1 + 9 files changed, 87 insertions(+), 97 deletions(-) create mode 100644 include/constants/form_change_types.h diff --git a/include/battle.h b/include/battle.h index 544514f137..e0baf88955 100644 --- a/include/battle.h +++ b/include/battle.h @@ -3,6 +3,7 @@ // should they be included here or included individually by every file? #include "constants/battle.h" +#include "constants/form_change_types.h" #include "battle_main.h" #include "battle_message.h" #include "battle_util.h" diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h new file mode 100644 index 0000000000..1eb2af30a9 --- /dev/null +++ b/include/constants/form_change_types.h @@ -0,0 +1,81 @@ + +// FORM_CHANGE_BATTLE_HP_PERCENT param2 arguments +#define HP_HIGHER_THAN 1 +#define HP_LOWER_EQ_THAN 2 +// FORM_CHANGE_MOVE param2 Arguments +#define WHEN_LEARNED 0 +#define WHEN_FORGOTTEN 1 +// FORM_CHANGE_ITEM_USE param2 Arguments +#define DAY 1 +#define NIGHT 2 + +#define FORM_CHANGE_END 0 // Form table terminator + +// Form change that activates when the specified item is given to or taken from the selected Pokémon. +// param1: item to hold. +// param2: ability to check for, optional. +#define FORM_CHANGE_ITEM_HOLD 1 + +// Form change that activates when the item is used on the selected Pokémon. +// param1: item to use +// param2: time of day to check, optional. +// - DAY if Form change that activates in the daytime. +// - NIGHT if Form change that activates at nighttime. +#define FORM_CHANGE_ITEM_USE 2 + +// TODO: Form change that activates when the Pokémon learns or forgets the move. +// param1: move to check for +// param2: +// - WHEN_LEARNED if Form change that activates when move is forgotten +// - WHEN_FORGOTTEN if Form change that activates when move is learned +#define FORM_CHANGE_MOVE 3 + +// Form change that activates when the Pokémon is withdrawn from the PC or Daycare. +// Daycare withdraw done, PC withdraw TODO. +// - No parameters. +#define FORM_CHANGE_WITHDRAW 4 + +// Form change that activates when the Pokémon faints, either in battle or in the overworld by poison. +// If species is not specified and it's on the player's side, it will try to use the value +// saved in gBattleStruct->changedSpecies from a previous form change. +// - No parameters. +#define FORM_CHANGE_FAINT 5 + +// Form change that activates when the Pokémon is sent out at the beginning of a battle +// param1: item to hold, optional +// param2: a move that will be replaced, optional +// param3: a new move to replace it with, optional +#define FORM_CHANGE_BATTLE_BEGIN 6 + +// Form change that activates at the end of a battle. If species is not specified and it's on the player's side, it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. +// param1: item to hold, optional +// param2: a move that will be replaced, optional +// param3: a new move to replace it with, optional +#define FORM_CHANGE_BATTLE_END 7 + +// Form change that activates when the Pokémon is switched out in battle. +// - No parameters. +#define FORM_CHANGE_BATTLE_SWITCH 8 + +// Form change that activates when the Pokémon's HP % passes a certain threshold. +// param1: Ability to check. +// param2: HP comparer +// - HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. +// - HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. +// param3: HP percentage threshold. +#define FORM_CHANGE_BATTLE_HP_PERCENT 9 + +// Form change that activates when the mon has the defined item. +// If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. +// param1: item to hold. +#define FORM_CHANGE_MEGA_EVOLUTION_ITEM 10 + +// Form change that activates when the mon has the defined move. +// If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. +// param1: move to have. +#define FORM_CHANGE_MEGA_EVOLUTION_MOVE 11 + +// Form change that activates automatically when entering battle with the specified item. +// If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to the Alpha symbol. +// param1: item to hold. +#define FORM_CHANGE_PRIMAL_REVERSION 12 diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 088015d066..7ba16fc57e 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -313,25 +313,6 @@ #define EVO_MODE_BATTLE_SPECIAL 4 #define EVO_MODE_OVERWORLD_SPECIAL 5 -// Form change types -#define FORM_CHANGE_END 0 // Form table terminator -#define FORM_CHANGE_ITEM_HOLD 1 -#define FORM_CHANGE_ITEM_USE 2 -#define FORM_CHANGE_MOVE 3 // Todo -#define FORM_CHANGE_WITHDRAW 4 // Daycare done, Todo PC -#define FORM_CHANGE_FAINT 5 -#define FORM_CHANGE_BATTLE_BEGIN 6 -#define FORM_CHANGE_BATTLE_END 7 -#define FORM_CHANGE_BATTLE_SWITCH 8 -#define FORM_CHANGE_BATTLE_HP_PERCENT 9 -#define FORM_CHANGE_MEGA_EVOLUTION_ITEM 10 -#define FORM_CHANGE_MEGA_EVOLUTION_MOVE 11 -#define FORM_CHANGE_PRIMAL_REVERSION 12 - -// FORM_CHANGE_BATTLE_HP_PERCENT param2 arguments -#define HP_HIGHER_THAN 1 -#define HP_LOWER_EQ_THAN 2 - #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 #define MON_PIC_SIZE (MON_PIC_WIDTH * MON_PIC_HEIGHT / 2) diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 1df1d7581d..4bb0c5780d 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,81 +1,3 @@ -/* -FORM_CHANGE_ITEM_HOLD: - Form change activates when the specified item is given to or taken from the selected Pokémon. - Alternatively, form change activates when the specified item is is given to or taken from - the selected Pokémon that has a particular ability. - param1 = item to hold - param2 = ability to check for, optional - -FORM_CHANGE_ITEM_USE: - Form change activates when the item is used on the selected Pokémon. - param1 = item to use - param2 = DAY if form change activates in the daytime, optional - NIGHT if form change activates at nighttime, optional - -FORM_CHANGE_MOVE: - Form change activates when the Pokémon learns or forgets the move. - param1 = move to check for - param2 = WHEN_LEARNED if form change activates when move is forgotten - WHEN_FORGOTTEN if form change activates when move is learned - -FORM_CHANGE_WITHDRAW: - Form change activates when the Pokémon is withdrawn from the PC or Daycare. - No parameters. - -FORM_CHANGE_FAINT: - Form change activates when the Pokémon faints, either in battle or in the overworld by poison. - If species is not specified and it's on the player's side, it will try to use the value - saved in gBattleStruct->changedSpecies from a previous form change. - No parameters. - -FORM_CHANGE_BATTLE_BEGIN: - Form change activates when the Pokémon is sent out at the beginning of a battle - param1 = item to hold, optional - param2 = a move that will be replaced, optional - param3 = a new move to replace it with, optional - -FORM_CHANGE_BATTLE_END: - Form change activates at the end of a battle. If species is not specified and it's on the player's side, - it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. - param1 = item to hold, optional - param2 = a move that will be replaced, optional - param3 = a new move to replace it with, optional - -FORM_CHANGE_BATTLE_SWITCH: - Form change activates when the Pokémon is switched out in battle. - No parameters. - -FORM_CHANGE_BATTLE_HP_PERCENT: - Form change activates when the Pokémon's HP % passes a certain threshold. - param1 = Ability to check. - param2 = HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. - HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. - param3 = HP percentage threshold. - -FORM_CHANGE_MEGA_EVOLUTION_ITEM: - Form change activates when the mon has the defined item. If it's on the player's side, it also requires - ITEM_MEGA_RING in the user's bag and for the player to choose to enable it. - param1 = item to hold. - -FORM_CHANGE_MEGA_EVOLUTION_MOVE: - Form change activates when the mon has the defined move. If it's on the player's side, it also requires - ITEM_MEGA_RING in the user's bag and for the player to choose to enable it. - param1 = move to have. - -FORM_CHANGE_PRIMAL_REVERSION: - Form change activates automatically when entering battle with the specified item. If the item is a Red Orb, - it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to Alpha. - param1 = item to hold. -*/ - -// FORM_CHANGE_MOVE param2 Arguments -#define WHEN_LEARNED 0 -#define WHEN_FORGOTTEN 1 - -// FORM_CHANGE_ITEM_USE param2 Arguments -#define DAY 1 -#define NIGHT 2 - static const struct FormChange sVenusaurFormChangeTable[] = { {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, {FORM_CHANGE_FAINT, SPECIES_VENUSAUR}, diff --git a/src/daycare.c b/src/daycare.c index 82280077bd..f0eae449ec 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -20,6 +20,7 @@ #include "list_menu.h" #include "overworld.h" #include "item.h" +#include "constants/form_change_types.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/region_map_sections.h" diff --git a/src/field_poison.c b/src/field_poison.c index 68a345919b..d1bd381cdb 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -15,6 +15,7 @@ #include "task.h" #include "trainer_hill.h" #include "constants/field_poison.h" +#include "constants/form_change_types.h" #include "constants/party_menu.h" static bool32 IsMonValidSpecies(struct Pokemon *pokemon) diff --git a/src/party_menu.c b/src/party_menu.c index da87352b5a..a3b65fe365 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -66,6 +66,7 @@ #include "constants/battle.h" #include "constants/battle_frontier.h" #include "constants/field_effects.h" +#include "constants/form_change_types.h" #include "constants/item_effects.h" #include "constants/items.h" #include "constants/moves.h" diff --git a/src/pokemon.c b/src/pokemon.c index b5d9633765..9c13bd17e7 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -43,6 +43,7 @@ #include "constants/battle_frontier.h" #include "constants/battle_move_effects.h" #include "constants/battle_script_commands.h" +#include "constants/form_change_types.h" #include "constants/hold_effects.h" #include "constants/item_effects.h" #include "constants/items.h" diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 3ede591e8a..e1a38569b3 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -36,6 +36,7 @@ #include "trig.h" #include "walda_phrase.h" #include "window.h" +#include "constants/form_change_types.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/rgb.h" From 99536089cf7a051f4b86606075cbfad4c4e848bd Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 5 Nov 2022 22:02:25 -0300 Subject: [PATCH 016/131] Renamed form change defines to be consistant with which function calls which --- include/constants/form_change_types.h | 26 +- src/battle_main.c | 8 +- src/battle_script_commands.c | 12 +- src/battle_util.c | 20 +- src/data/pokemon/form_change_tables.h | 490 +++++++++++++------------- src/pokemon.c | 12 +- 6 files changed, 284 insertions(+), 284 deletions(-) diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index 1eb2af30a9..c6d4c6eae2 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -9,53 +9,53 @@ #define DAY 1 #define NIGHT 2 -#define FORM_CHANGE_END 0 // Form table terminator +#define FORM_CHANGE_TERMINATOR 0 // Form change that activates when the specified item is given to or taken from the selected Pokémon. // param1: item to hold. // param2: ability to check for, optional. -#define FORM_CHANGE_ITEM_HOLD 1 +#define FORM_CHANGE_ITEM_HOLD 1 // Form change that activates when the item is used on the selected Pokémon. // param1: item to use // param2: time of day to check, optional. // - DAY if Form change that activates in the daytime. // - NIGHT if Form change that activates at nighttime. -#define FORM_CHANGE_ITEM_USE 2 +#define FORM_CHANGE_ITEM_USE 2 // TODO: Form change that activates when the Pokémon learns or forgets the move. // param1: move to check for // param2: // - WHEN_LEARNED if Form change that activates when move is forgotten // - WHEN_FORGOTTEN if Form change that activates when move is learned -#define FORM_CHANGE_MOVE 3 +#define FORM_CHANGE_MOVE 3 // Form change that activates when the Pokémon is withdrawn from the PC or Daycare. // Daycare withdraw done, PC withdraw TODO. // - No parameters. -#define FORM_CHANGE_WITHDRAW 4 +#define FORM_CHANGE_WITHDRAW 4 // Form change that activates when the Pokémon faints, either in battle or in the overworld by poison. // If species is not specified and it's on the player's side, it will try to use the value // saved in gBattleStruct->changedSpecies from a previous form change. // - No parameters. -#define FORM_CHANGE_FAINT 5 +#define FORM_CHANGE_FAINT 5 // Form change that activates when the Pokémon is sent out at the beginning of a battle // param1: item to hold, optional // param2: a move that will be replaced, optional // param3: a new move to replace it with, optional -#define FORM_CHANGE_BATTLE_BEGIN 6 +#define FORM_CHANGE_BEGIN_BATTLE 6 // Form change that activates at the end of a battle. If species is not specified and it's on the player's side, it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. // param1: item to hold, optional // param2: a move that will be replaced, optional // param3: a new move to replace it with, optional -#define FORM_CHANGE_BATTLE_END 7 +#define FORM_CHANGE_END_BATTLE 7 // Form change that activates when the Pokémon is switched out in battle. // - No parameters. -#define FORM_CHANGE_BATTLE_SWITCH 8 +#define FORM_CHANGE_BATTLE_SWITCH 8 // Form change that activates when the Pokémon's HP % passes a certain threshold. // param1: Ability to check. @@ -63,19 +63,19 @@ // - HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. // - HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. // param3: HP percentage threshold. -#define FORM_CHANGE_BATTLE_HP_PERCENT 9 +#define FORM_CHANGE_BATTLE_HP_PERCENT 9 // Form change that activates when the mon has the defined item. // If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. // param1: item to hold. -#define FORM_CHANGE_MEGA_EVOLUTION_ITEM 10 +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM 10 // Form change that activates when the mon has the defined move. // If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. // param1: move to have. -#define FORM_CHANGE_MEGA_EVOLUTION_MOVE 11 +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE 11 // Form change that activates automatically when entering battle with the specified item. // If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to the Alpha symbol. // param1: item to hold. -#define FORM_CHANGE_PRIMAL_REVERSION 12 +#define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 12 diff --git a/src/battle_main.c b/src/battle_main.c index 5138a6e028..f396b9b0a6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -602,9 +602,9 @@ static void CB2_InitBattleInternal(void) for (i = 0; i < PARTY_SIZE; i++) { // Player's side - TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_BEGIN); + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BEGIN_BATTLE); // Opponent's side - TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BATTLE_BEGIN); + TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } gBattleCommunication[MULTIUSE_STATE] = 0; @@ -3682,7 +3682,7 @@ static void TryDoEventsBeforeFirstTurn(void) for (i = 0; i < gBattlersCount; i++) { if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB - && GetBattleFormChangeTargetSpecies(i, FORM_CHANGE_PRIMAL_REVERSION) != SPECIES_NONE) + && GetBattleFormChangeTargetSpecies(i, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) { gBattlerAttacker = i; BattleScriptExecute(BattleScript_PrimalReversion); @@ -5202,7 +5202,7 @@ static void HandleEndTurn_FinishBattle(void) #endif for (i = 0; i < PARTY_SIZE; i++) { - bool32 changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END); + bool32 changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); DoBurmyFormChange(i); // Clear original species field gBattleStruct->changedSpecies[i] = SPECIES_NONE; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e60f5a49e2..73604ce124 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8965,10 +8965,10 @@ static void Cmd_various(void) if (gBattlescriptCurrInstr[3] == 0) { //Checks regular Mega Evolution - u16 megaSpecies = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_MEGA_EVOLUTION_ITEM); + u16 megaSpecies = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM); //Checks Wish Mega Evolution if (megaSpecies == SPECIES_NONE) - megaSpecies = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_MEGA_EVOLUTION_MOVE); + megaSpecies = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE); gBattleMons[gActiveBattler].species = megaSpecies; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); @@ -9001,7 +9001,7 @@ static void Cmd_various(void) // Change species. if (gBattlescriptCurrInstr[3] == 0) { - gBattleMons[gActiveBattler].species = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_PRIMAL_REVERSION); + gBattleMons[gActiveBattler].species = GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION); PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], sizeof(gBattleMons[gActiveBattler].species), &gBattleMons[gActiveBattler].species); @@ -9720,7 +9720,7 @@ static void Cmd_various(void) return; case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: { - if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_PRIMAL_REVERSION) == SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == SPECIES_NONE) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else gBattlescriptCurrInstr += 7; @@ -14241,7 +14241,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_END); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -14295,7 +14295,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_END); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); diff --git a/src/battle_util.c b/src/battle_util.c index 634e30338e..eaf3f72e07 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9654,12 +9654,12 @@ bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) if (formChanges != NULL) { - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { switch (formChanges[i].method) { - case FORM_CHANGE_MEGA_EVOLUTION_ITEM: - case FORM_CHANGE_PRIMAL_REVERSION: + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: case FORM_CHANGE_ITEM_HOLD: if (formChanges[i].param1 == heldItemId) return TRUE; @@ -9710,7 +9710,7 @@ bool32 CanMegaEvolve(u8 battlerId) itemId = GetMonData(mon, MON_DATA_HELD_ITEM); // Check if there is an entry in the evolution table for regular Mega Evolution. - if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) { #if B_ENABLE_DEBUG == TRUE if (B_ENABLE_DEBUG && gBattleStruct->debugHoldEffects[battlerId]) @@ -9731,7 +9731,7 @@ bool32 CanMegaEvolve(u8 battlerId) } // Check if there is an entry in the evolution table for Wish Mega Evolution. - if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) { gBattleStruct->mega.isWishMegaEvo = TRUE; return TRUE; @@ -9766,18 +9766,18 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) heldItem = gBattleMons[battlerId].item; ability = GetBattlerAbility(battlerId); - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { if (method == formChanges[i].method && species != formChanges[i].targetSpecies) { switch (method) { - case FORM_CHANGE_MEGA_EVOLUTION_ITEM: - case FORM_CHANGE_PRIMAL_REVERSION: + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: if (heldItem == formChanges[i].param1) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_CHANGE_MEGA_EVOLUTION_MOVE: + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE: if (gBattleMons[battlerId].moves[0] == formChanges[i].param1 || gBattleMons[battlerId].moves[1] == formChanges[i].param1 || gBattleMons[battlerId].moves[2] == formChanges[i].param1 @@ -9856,7 +9856,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) RecalcBattlerStats(battlerId, &party[monId]); return TRUE; } - else if ((method == FORM_CHANGE_BATTLE_END || method == FORM_CHANGE_FAINT) + else if ((method == FORM_CHANGE_END_BATTLE || method == FORM_CHANGE_FAINT) && gBattleStruct->changedSpecies[monId] != SPECIES_NONE) { TryToSetBattleFormChangeMoves(&party[monId], method); diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 4bb0c5780d..6f963b599f 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,336 +1,336 @@ static const struct FormChange sVenusaurFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, - {FORM_CHANGE_FAINT, SPECIES_VENUSAUR}, - {FORM_CHANGE_BATTLE_END, SPECIES_VENUSAUR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, + {FORM_CHANGE_FAINT, SPECIES_VENUSAUR}, + {FORM_CHANGE_END_BATTLE, SPECIES_VENUSAUR}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sCharizardFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_X, ITEM_CHARIZARDITE_X}, - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_Y, ITEM_CHARIZARDITE_Y}, - {FORM_CHANGE_FAINT, SPECIES_CHARIZARD}, - {FORM_CHANGE_BATTLE_END, SPECIES_CHARIZARD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_X, ITEM_CHARIZARDITE_X}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_Y, ITEM_CHARIZARDITE_Y}, + {FORM_CHANGE_FAINT, SPECIES_CHARIZARD}, + {FORM_CHANGE_END_BATTLE, SPECIES_CHARIZARD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBlastoiseFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, - {FORM_CHANGE_FAINT, SPECIES_BLASTOISE}, - {FORM_CHANGE_BATTLE_END, SPECIES_BLASTOISE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, + {FORM_CHANGE_FAINT, SPECIES_BLASTOISE}, + {FORM_CHANGE_END_BATTLE, SPECIES_BLASTOISE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBeedrillFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, - {FORM_CHANGE_FAINT, SPECIES_BEEDRILL}, - {FORM_CHANGE_BATTLE_END, SPECIES_BEEDRILL}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, + {FORM_CHANGE_FAINT, SPECIES_BEEDRILL}, + {FORM_CHANGE_END_BATTLE, SPECIES_BEEDRILL}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sPidgeotFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, - {FORM_CHANGE_FAINT, SPECIES_PIDGEOT}, - {FORM_CHANGE_BATTLE_END, SPECIES_PIDGEOT}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, + {FORM_CHANGE_FAINT, SPECIES_PIDGEOT}, + {FORM_CHANGE_END_BATTLE, SPECIES_PIDGEOT}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAlakazamFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, - {FORM_CHANGE_FAINT, SPECIES_ALAKAZAM}, - {FORM_CHANGE_BATTLE_END, SPECIES_ALAKAZAM}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, + {FORM_CHANGE_FAINT, SPECIES_ALAKAZAM}, + {FORM_CHANGE_END_BATTLE, SPECIES_ALAKAZAM}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSlowbroFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, - {FORM_CHANGE_FAINT, SPECIES_SLOWBRO}, - {FORM_CHANGE_BATTLE_END, SPECIES_SLOWBRO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, + {FORM_CHANGE_FAINT, SPECIES_SLOWBRO}, + {FORM_CHANGE_END_BATTLE, SPECIES_SLOWBRO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGengarFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, - {FORM_CHANGE_FAINT, SPECIES_GENGAR}, - {FORM_CHANGE_BATTLE_END, SPECIES_GENGAR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, + {FORM_CHANGE_FAINT, SPECIES_GENGAR}, + {FORM_CHANGE_END_BATTLE, SPECIES_GENGAR}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKangaskhanFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, - {FORM_CHANGE_FAINT, SPECIES_KANGASKHAN}, - {FORM_CHANGE_BATTLE_END, SPECIES_KANGASKHAN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, + {FORM_CHANGE_FAINT, SPECIES_KANGASKHAN}, + {FORM_CHANGE_END_BATTLE, SPECIES_KANGASKHAN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sPinsirFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, - {FORM_CHANGE_FAINT, SPECIES_PINSIR}, - {FORM_CHANGE_BATTLE_END, SPECIES_PINSIR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, + {FORM_CHANGE_FAINT, SPECIES_PINSIR}, + {FORM_CHANGE_END_BATTLE, SPECIES_PINSIR}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGyaradosFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, - {FORM_CHANGE_FAINT, SPECIES_GYARADOS}, - {FORM_CHANGE_BATTLE_END, SPECIES_GYARADOS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, + {FORM_CHANGE_FAINT, SPECIES_GYARADOS}, + {FORM_CHANGE_END_BATTLE, SPECIES_GYARADOS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAerodactylFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, - {FORM_CHANGE_FAINT, SPECIES_AERODACTYL}, - {FORM_CHANGE_BATTLE_END, SPECIES_AERODACTYL}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, + {FORM_CHANGE_FAINT, SPECIES_AERODACTYL}, + {FORM_CHANGE_END_BATTLE, SPECIES_AERODACTYL}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMewtwoFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_X, ITEM_MEWTWONITE_X}, - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_Y, ITEM_MEWTWONITE_Y}, - {FORM_CHANGE_FAINT, SPECIES_MEWTWO}, - {FORM_CHANGE_BATTLE_END, SPECIES_MEWTWO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_X, ITEM_MEWTWONITE_X}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_Y, ITEM_MEWTWONITE_Y}, + {FORM_CHANGE_FAINT, SPECIES_MEWTWO}, + {FORM_CHANGE_END_BATTLE, SPECIES_MEWTWO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAmpharosFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, - {FORM_CHANGE_FAINT, SPECIES_AMPHAROS}, - {FORM_CHANGE_BATTLE_END, SPECIES_AMPHAROS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, + {FORM_CHANGE_FAINT, SPECIES_AMPHAROS}, + {FORM_CHANGE_END_BATTLE, SPECIES_AMPHAROS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSteelixFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, - {FORM_CHANGE_FAINT, SPECIES_STEELIX}, - {FORM_CHANGE_BATTLE_END, SPECIES_STEELIX}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, + {FORM_CHANGE_FAINT, SPECIES_STEELIX}, + {FORM_CHANGE_END_BATTLE, SPECIES_STEELIX}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sScizorFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, - {FORM_CHANGE_FAINT, SPECIES_SCIZOR}, - {FORM_CHANGE_BATTLE_END, SPECIES_SCIZOR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, + {FORM_CHANGE_FAINT, SPECIES_SCIZOR}, + {FORM_CHANGE_END_BATTLE, SPECIES_SCIZOR}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHeracrossFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, - {FORM_CHANGE_FAINT, SPECIES_HERACROSS}, - {FORM_CHANGE_BATTLE_END, SPECIES_HERACROSS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, + {FORM_CHANGE_FAINT, SPECIES_HERACROSS}, + {FORM_CHANGE_END_BATTLE, SPECIES_HERACROSS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHoundoomFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, - {FORM_CHANGE_FAINT, SPECIES_HOUNDOOM}, - {FORM_CHANGE_BATTLE_END, SPECIES_HOUNDOOM}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, + {FORM_CHANGE_FAINT, SPECIES_HOUNDOOM}, + {FORM_CHANGE_END_BATTLE, SPECIES_HOUNDOOM}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sTyranitarFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, - {FORM_CHANGE_FAINT, SPECIES_TYRANITAR}, - {FORM_CHANGE_BATTLE_END, SPECIES_TYRANITAR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, + {FORM_CHANGE_FAINT, SPECIES_TYRANITAR}, + {FORM_CHANGE_END_BATTLE, SPECIES_TYRANITAR}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSceptileFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, - {FORM_CHANGE_FAINT, SPECIES_SCEPTILE}, - {FORM_CHANGE_BATTLE_END, SPECIES_SCEPTILE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, + {FORM_CHANGE_FAINT, SPECIES_SCEPTILE}, + {FORM_CHANGE_END_BATTLE, SPECIES_SCEPTILE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBlazikenFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, - {FORM_CHANGE_FAINT, SPECIES_BLAZIKEN}, - {FORM_CHANGE_BATTLE_END, SPECIES_BLAZIKEN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, + {FORM_CHANGE_FAINT, SPECIES_BLAZIKEN}, + {FORM_CHANGE_END_BATTLE, SPECIES_BLAZIKEN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSwampertFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, - {FORM_CHANGE_FAINT, SPECIES_SWAMPERT}, - {FORM_CHANGE_BATTLE_END, SPECIES_SWAMPERT}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, + {FORM_CHANGE_FAINT, SPECIES_SWAMPERT}, + {FORM_CHANGE_END_BATTLE, SPECIES_SWAMPERT}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSableyeFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, - {FORM_CHANGE_FAINT, SPECIES_SABLEYE}, - {FORM_CHANGE_BATTLE_END, SPECIES_SABLEYE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, + {FORM_CHANGE_FAINT, SPECIES_SABLEYE}, + {FORM_CHANGE_END_BATTLE, SPECIES_SABLEYE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSharpedoFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, - {FORM_CHANGE_FAINT, SPECIES_SHARPEDO}, - {FORM_CHANGE_BATTLE_END, SPECIES_SHARPEDO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, + {FORM_CHANGE_FAINT, SPECIES_SHARPEDO}, + {FORM_CHANGE_END_BATTLE, SPECIES_SHARPEDO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sManectricFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, - {FORM_CHANGE_FAINT, SPECIES_MANECTRIC}, - {FORM_CHANGE_BATTLE_END, SPECIES_MANECTRIC}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, + {FORM_CHANGE_FAINT, SPECIES_MANECTRIC}, + {FORM_CHANGE_END_BATTLE, SPECIES_MANECTRIC}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sCameruptFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, {FORM_CHANGE_FAINT, SPECIES_CAMERUPT}, - {FORM_CHANGE_BATTLE_END, SPECIES_CAMERUPT}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_CAMERUPT}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGlalieFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, - {FORM_CHANGE_FAINT, SPECIES_GLALIE}, - {FORM_CHANGE_BATTLE_END, SPECIES_GLALIE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, + {FORM_CHANGE_FAINT, SPECIES_GLALIE}, + {FORM_CHANGE_END_BATTLE, SPECIES_GLALIE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMawileFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, - {FORM_CHANGE_FAINT, SPECIES_MAWILE}, - {FORM_CHANGE_BATTLE_END, SPECIES_MAWILE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, + {FORM_CHANGE_FAINT, SPECIES_MAWILE}, + {FORM_CHANGE_END_BATTLE, SPECIES_MAWILE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMedichamFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, - {FORM_CHANGE_FAINT, SPECIES_MEDICHAM}, - {FORM_CHANGE_BATTLE_END, SPECIES_MEDICHAM}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, + {FORM_CHANGE_FAINT, SPECIES_MEDICHAM}, + {FORM_CHANGE_END_BATTLE, SPECIES_MEDICHAM}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAltariaFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, - {FORM_CHANGE_FAINT, SPECIES_ALTARIA}, - {FORM_CHANGE_BATTLE_END, SPECIES_ALTARIA}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, + {FORM_CHANGE_FAINT, SPECIES_ALTARIA}, + {FORM_CHANGE_END_BATTLE, SPECIES_ALTARIA}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAbsolFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, - {FORM_CHANGE_FAINT, SPECIES_ABSOL}, - {FORM_CHANGE_BATTLE_END, SPECIES_ABSOL}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, + {FORM_CHANGE_FAINT, SPECIES_ABSOL}, + {FORM_CHANGE_END_BATTLE, SPECIES_ABSOL}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBanetteFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, - {FORM_CHANGE_FAINT, SPECIES_BANETTE}, - {FORM_CHANGE_BATTLE_END, SPECIES_BANETTE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, + {FORM_CHANGE_FAINT, SPECIES_BANETTE}, + {FORM_CHANGE_END_BATTLE, SPECIES_BANETTE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAggronFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, - {FORM_CHANGE_FAINT, SPECIES_AGGRON}, - {FORM_CHANGE_BATTLE_END, SPECIES_AGGRON}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, + {FORM_CHANGE_FAINT, SPECIES_AGGRON}, + {FORM_CHANGE_END_BATTLE, SPECIES_AGGRON}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGardevoirFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, - {FORM_CHANGE_FAINT, SPECIES_GARDEVOIR}, - {FORM_CHANGE_BATTLE_END, SPECIES_GARDEVOIR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, + {FORM_CHANGE_FAINT, SPECIES_GARDEVOIR}, + {FORM_CHANGE_END_BATTLE, SPECIES_GARDEVOIR}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSalamenceFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, - {FORM_CHANGE_FAINT, SPECIES_SALAMENCE}, - {FORM_CHANGE_BATTLE_END, SPECIES_SALAMENCE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, + {FORM_CHANGE_FAINT, SPECIES_SALAMENCE}, + {FORM_CHANGE_END_BATTLE, SPECIES_SALAMENCE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMetagrossFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, - {FORM_CHANGE_FAINT, SPECIES_METAGROSS}, - {FORM_CHANGE_BATTLE_END, SPECIES_METAGROSS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, + {FORM_CHANGE_FAINT, SPECIES_METAGROSS}, + {FORM_CHANGE_END_BATTLE, SPECIES_METAGROSS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLatiasFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, - {FORM_CHANGE_FAINT, SPECIES_LATIAS}, - {FORM_CHANGE_BATTLE_END, SPECIES_LATIAS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, + {FORM_CHANGE_FAINT, SPECIES_LATIAS}, + {FORM_CHANGE_END_BATTLE, SPECIES_LATIAS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLatiosFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, - {FORM_CHANGE_FAINT, SPECIES_LATIOS}, - {FORM_CHANGE_BATTLE_END, SPECIES_LATIOS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, + {FORM_CHANGE_FAINT, SPECIES_LATIOS}, + {FORM_CHANGE_END_BATTLE, SPECIES_LATIOS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKyogreFormChangeTable[] = { - {FORM_CHANGE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, - {FORM_CHANGE_BATTLE_END, SPECIES_KYOGRE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, + {FORM_CHANGE_END_BATTLE, SPECIES_KYOGRE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGroudonFormChangeTable[] = { - {FORM_CHANGE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, - {FORM_CHANGE_BATTLE_END, SPECIES_GROUDON}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, + {FORM_CHANGE_END_BATTLE, SPECIES_GROUDON}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sRayquazaFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, {FORM_CHANGE_FAINT, SPECIES_RAYQUAZA}, - {FORM_CHANGE_BATTLE_END, SPECIES_RAYQUAZA}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_RAYQUAZA}, + {FORM_CHANGE_TERMINATOR}, }; #if P_GEN_4_POKEMON == TRUE static const struct FormChange sLopunnyFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, - {FORM_CHANGE_FAINT, SPECIES_LOPUNNY}, - {FORM_CHANGE_BATTLE_END, SPECIES_LOPUNNY}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, + {FORM_CHANGE_FAINT, SPECIES_LOPUNNY}, + {FORM_CHANGE_END_BATTLE, SPECIES_LOPUNNY}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGarchompFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, - {FORM_CHANGE_FAINT, SPECIES_GARCHOMP}, - {FORM_CHANGE_BATTLE_END, SPECIES_GARCHOMP}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, + {FORM_CHANGE_FAINT, SPECIES_GARCHOMP}, + {FORM_CHANGE_END_BATTLE, SPECIES_GARCHOMP}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLucarioFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, - {FORM_CHANGE_FAINT, SPECIES_LUCARIO}, - {FORM_CHANGE_BATTLE_END, SPECIES_LUCARIO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, + {FORM_CHANGE_FAINT, SPECIES_LUCARIO}, + {FORM_CHANGE_END_BATTLE, SPECIES_LUCARIO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAbomasnowFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, - {FORM_CHANGE_FAINT, SPECIES_ABOMASNOW}, - {FORM_CHANGE_BATTLE_END, SPECIES_ABOMASNOW}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, + {FORM_CHANGE_FAINT, SPECIES_ABOMASNOW}, + {FORM_CHANGE_END_BATTLE, SPECIES_ABOMASNOW}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGalladeFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, - {FORM_CHANGE_FAINT, SPECIES_GALLADE}, - {FORM_CHANGE_BATTLE_END, SPECIES_GALLADE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, + {FORM_CHANGE_FAINT, SPECIES_GALLADE}, + {FORM_CHANGE_END_BATTLE, SPECIES_GALLADE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGiratinaFormChangeTable[] = { {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sShayminFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, // {FORM_CHANGE_WITHDRAW, SPECIES_SHAYMIN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sArceusFormChangeTable[] = { @@ -369,62 +369,62 @@ static const struct FormChange sArceusFormChangeTable[] = { {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_5_POKEMON == TRUE static const struct FormChange sAudinoFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, - {FORM_CHANGE_FAINT, SPECIES_AUDINO}, - {FORM_CHANGE_BATTLE_END, SPECIES_AUDINO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, + {FORM_CHANGE_FAINT, SPECIES_AUDINO}, + {FORM_CHANGE_END_BATTLE, SPECIES_AUDINO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sDarmanitanFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_FAINT, SPECIES_DARMANITAN}, - {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_GALARIAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN}, - {FORM_CHANGE_BATTLE_END, SPECIES_DARMANITAN_GALARIAN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMeloettaFormChangeTable[] = { {FORM_CHANGE_FAINT, SPECIES_MELOETTA}, - {FORM_CHANGE_BATTLE_END, SPECIES_MELOETTA}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MELOETTA}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sTornadusFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sThundurusFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLandorusFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKeldeoFormChangeTable[] = { // {FORM_CHANGE_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, // {FORM_CHANGE_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGenesectFormChangeTable[] = { @@ -433,48 +433,48 @@ static const struct FormChange sGenesectFormChangeTable[] = { {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_6_POKEMON == TRUE static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { {FORM_CHANGE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, - {FORM_CHANGE_BATTLE_END, SPECIES_GRENINJA_BATTLE_BOND}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAegislashFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH}, {FORM_CHANGE_FAINT, SPECIES_AEGISLASH}, - {FORM_CHANGE_BATTLE_END, SPECIES_AEGISLASH}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_AEGISLASH}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sXerneasFormChangeTable[] = { - {FORM_CHANGE_BATTLE_BEGIN, SPECIES_XERNEAS_ACTIVE}, - {FORM_CHANGE_BATTLE_END, SPECIES_XERNEAS, }, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_XERNEAS_ACTIVE}, + {FORM_CHANGE_END_BATTLE, SPECIES_XERNEAS, }, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZygardePowerConstructFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_ZYGARDE_COMPLETE, ABILITY_POWER_CONSTRUCT, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_FAINT}, - {FORM_CHANGE_BATTLE_END}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sDiancieFormChangeTable[] = { - {FORM_CHANGE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, - {FORM_CHANGE_FAINT, SPECIES_DIANCIE}, - {FORM_CHANGE_BATTLE_END, SPECIES_DIANCIE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, + {FORM_CHANGE_FAINT, SPECIES_DIANCIE}, + {FORM_CHANGE_END_BATTLE, SPECIES_DIANCIE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHoopaFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; #endif @@ -484,15 +484,15 @@ static const struct FormChange sOricorioFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sWishiwashiFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI_SCHOOL, ABILITY_SCHOOLING, HP_HIGHER_THAN, 25}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI, ABILITY_SCHOOLING, HP_LOWER_EQ_THAN, 25}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI}, - {FORM_CHANGE_BATTLE_END, SPECIES_WISHIWASHI}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_WISHIWASHI}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSilvallyFormChangeTable[] = { @@ -514,13 +514,13 @@ static const struct FormChange sSilvallyFormChangeTable[] = { {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMimikyuFormChangeTable[] = { {FORM_CHANGE_FAINT, SPECIES_MIMIKYU}, - {FORM_CHANGE_BATTLE_END, SPECIES_MIMIKYU}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MIMIKYU}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorRedFormChangeTable[] = { @@ -528,56 +528,56 @@ static const struct FormChange sMiniorRedFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_RED, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_RED}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_RED}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorBlueFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_BLUE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_BLUE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_BLUE}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_BLUE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorGreenFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_GREEN, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_GREEN, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_GREEN}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_GREEN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorIndigoFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_INDIGO, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_INDIGO, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_INDIGO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorOrangeFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_ORANGE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_ORANGE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_ORANGE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorVioletFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_VIOLET, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_VIOLET, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_VIOLET}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMiniorYellowFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_YELLOW, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_YELLOW, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, - {FORM_CHANGE_BATTLE_END, SPECIES_MINIOR_CORE_YELLOW}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_TERMINATOR}, }; #endif @@ -587,33 +587,33 @@ static const struct FormChange sCramorantFormChangeTable[] = { {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GORGING, ABILITY_GULP_MISSILE, HP_LOWER_EQ_THAN, 50}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, - {FORM_CHANGE_BATTLE_END, SPECIES_CRAMORANT}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_CRAMORANT}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMorpekoFormChangeTable[] = { {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, {FORM_CHANGE_FAINT, SPECIES_MORPEKO}, - {FORM_CHANGE_BATTLE_END, SPECIES_MORPEKO}, - {FORM_CHANGE_END}, + {FORM_CHANGE_END_BATTLE, SPECIES_MORPEKO}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZacianFormChangeTable[] = { - {FORM_CHANGE_BATTLE_BEGIN, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, - {FORM_CHANGE_BATTLE_END, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZamazentaFormChangeTable[] = { - {FORM_CHANGE_BATTLE_BEGIN, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, - {FORM_CHANGE_BATTLE_END, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sEnamorusFormChangeTable[] = { {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_TERMINATOR}, }; #endif diff --git a/src/pokemon.c b/src/pokemon.c index 9c13bd17e7..1b41d666dc 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8498,7 +8498,7 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 heldItem = GetBoxMonData(boxMon, MON_DATA_HELD_ITEM, NULL); ability = GetAbilityBySpecies(species, GetBoxMonData(boxMon, MON_DATA_ABILITY_NUM, NULL)); - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { if (method == formChanges[i].method && species != formChanges[i].targetSpecies) { @@ -8534,8 +8534,8 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 if (BoxMonKnowsMove(boxMon, formChanges[i].param1) != formChanges[i].param2) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_CHANGE_BATTLE_BEGIN: - case FORM_CHANGE_BATTLE_END: + case FORM_CHANGE_BEGIN_BATTLE: + case FORM_CHANGE_END_BATTLE: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; break; @@ -8558,7 +8558,7 @@ bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method) if (formChanges != NULL) { - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { if (method == formChanges[i].method && species != formChanges[i].targetSpecies) return TRUE; @@ -8681,10 +8681,10 @@ void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) const struct FormChange *formChanges = gFormChangeTablePointers[species]; if (formChanges == NULL - || (method != FORM_CHANGE_BATTLE_BEGIN && method != FORM_CHANGE_BATTLE_END)) + || (method != FORM_CHANGE_BEGIN_BATTLE && method != FORM_CHANGE_END_BATTLE)) return; - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { if (formChanges[i].method == method && formChanges[i].param2 From 57bdb683ece950a473b30230ccd9d4cafc86fed5 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 5 Nov 2022 23:27:40 -0300 Subject: [PATCH 017/131] DoBurmyFormChange handled by FORM_CHANGE_END_BATTLE_TERRAIN --- include/battle_util.h | 1 - include/constants/form_change_types.h | 14 ++++--- src/battle_main.c | 13 ++++-- src/battle_util.c | 40 ------------------- src/data/pokemon/form_change_table_pointers.h | 3 ++ src/data/pokemon/form_change_tables.h | 18 +++++++-- src/pokemon.c | 6 ++- 7 files changed, 42 insertions(+), 53 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 18b31957bb..ae5263b7fe 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -177,7 +177,6 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); bool32 TryRoomService(u8 battlerId); void BufferStatChange(u8 battlerId, u8 statId, u8 stringId); -void DoBurmyFormChange(u32 monId); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u8 battler); bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index c6d4c6eae2..8701a9497c 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -53,9 +53,13 @@ // param3: a new move to replace it with, optional #define FORM_CHANGE_END_BATTLE 7 +// Form change that activates at the end of a battle based on the terrain if it participated in the battle and hasn't fainted. Takes priority over FORM_CHANGE_END_BATTLE. +// param1: battle terrain to check. +#define FORM_CHANGE_END_BATTLE_TERRAIN 8 + // Form change that activates when the Pokémon is switched out in battle. // - No parameters. -#define FORM_CHANGE_BATTLE_SWITCH 8 +#define FORM_CHANGE_BATTLE_SWITCH 9 // Form change that activates when the Pokémon's HP % passes a certain threshold. // param1: Ability to check. @@ -63,19 +67,19 @@ // - HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. // - HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. // param3: HP percentage threshold. -#define FORM_CHANGE_BATTLE_HP_PERCENT 9 +#define FORM_CHANGE_BATTLE_HP_PERCENT 10 // Form change that activates when the mon has the defined item. // If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. // param1: item to hold. -#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM 10 +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM 11 // Form change that activates when the mon has the defined move. // If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. // param1: move to have. -#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE 11 +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE 12 // Form change that activates automatically when entering battle with the specified item. // If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to the Alpha symbol. // param1: item to hold. -#define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 12 +#define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 13 diff --git a/src/battle_main.c b/src/battle_main.c index f396b9b0a6..1aefd71b0f 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5202,8 +5202,15 @@ static void HandleEndTurn_FinishBattle(void) #endif for (i = 0; i < PARTY_SIZE; i++) { - bool32 changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); - DoBurmyFormChange(i); + bool32 changedForm = FALSE; + + // Appeared in battle and didn't faint + if ((gBattleStruct->appearedInBattle & gBitTable[i]) && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) + changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_TERRAIN); + + if (!changedForm) + changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); + // Clear original species field gBattleStruct->changedSpecies[i] = SPECIES_NONE; @@ -5215,7 +5222,7 @@ static void HandleEndTurn_FinishBattle(void) } // Clear battle mon species to avoid a bug on the next battle that causes // healthboxes loading incorrectly due to it trying to create a Mega Indicator - // if the previous battler would've had. + // if the previous battler would've had it. for (i = 0; i < MAX_BATTLERS_COUNT; i++) { gBattleMons[i].species = SPECIES_NONE; diff --git a/src/battle_util.c b/src/battle_util.c index eaf3f72e07..52a3202007 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10414,46 +10414,6 @@ bool32 TryRoomService(u8 battlerId) } } -void DoBurmyFormChange(u32 monId) -{ - u16 newSpecies, currSpecies; - struct Pokemon *party = gPlayerParty; - - currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - - if ((GET_BASE_SPECIES_ID(currSpecies) == SPECIES_BURMY) - && (gBattleStruct->appearedInBattle & gBitTable[monId]) // Burmy appeared in battle - && GetMonData(&party[monId], MON_DATA_HP, NULL) != 0) // Burmy isn't fainted - { - switch (gBattleTerrain) - { - case BATTLE_TERRAIN_GRASS: - case BATTLE_TERRAIN_LONG_GRASS: - case BATTLE_TERRAIN_POND: - case BATTLE_TERRAIN_MOUNTAIN: - case BATTLE_TERRAIN_PLAIN: - newSpecies = SPECIES_BURMY; - break; - case BATTLE_TERRAIN_CAVE: - case BATTLE_TERRAIN_SAND: - newSpecies = SPECIES_BURMY_SANDY_CLOAK; - break; - case BATTLE_TERRAIN_BUILDING: - newSpecies = SPECIES_BURMY_TRASH_CLOAK; - break; - default: // Don't change form if last battle was water-related - newSpecies = SPECIES_NONE; - break; - } - - if (newSpecies != SPECIES_NONE) - { - SetMonData(&party[monId], MON_DATA_SPECIES, &newSpecies); - CalculateMonStats(&party[monId]); - } - } -} - bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget) { #if B_PRANKSTER_DARK_TYPES >= GEN_7 diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 06d5825a2d..65e71b2cf9 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -85,6 +85,9 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_RAYQUAZA] = sRayquazaFormChangeTable, [SPECIES_RAYQUAZA_MEGA] = sRayquazaFormChangeTable, #if P_GEN_4_POKEMON == TRUE + [SPECIES_BURMY] = sBurmyFormChangeTable, + [SPECIES_BURMY_SANDY_CLOAK] = sBurmyFormChangeTable, + [SPECIES_BURMY_TRASH_CLOAK] = sBurmyFormChangeTable, [SPECIES_LOPUNNY] = sLopunnyFormChangeTable, [SPECIES_LOPUNNY_MEGA] = sLopunnyFormChangeTable, [SPECIES_GARCHOMP] = sGarchompFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 6f963b599f..7b8c4a6ce7 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -279,13 +279,25 @@ static const struct FormChange sGroudonFormChangeTable[] = { }; static const struct FormChange sRayquazaFormChangeTable[] = { - {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, - {FORM_CHANGE_FAINT, SPECIES_RAYQUAZA}, - {FORM_CHANGE_END_BATTLE, SPECIES_RAYQUAZA}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, + {FORM_CHANGE_FAINT, SPECIES_RAYQUAZA}, + {FORM_CHANGE_END_BATTLE, SPECIES_RAYQUAZA}, {FORM_CHANGE_TERMINATOR}, }; #if P_GEN_4_POKEMON == TRUE +static const struct FormChange sBurmyFormChangeTable[] = { + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_LONG_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_POND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_MOUNTAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_PLAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_SANDY_CLOAK, BATTLE_TERRAIN_CAVE}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_SANDY_CLOAK, BATTLE_TERRAIN_SAND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_TRASH_CLOAK, BATTLE_TERRAIN_BUILDING}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sLopunnyFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, {FORM_CHANGE_FAINT, SPECIES_LOPUNNY}, diff --git a/src/pokemon.c b/src/pokemon.c index 1b41d666dc..dc87126b94 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8538,7 +8538,11 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 case FORM_CHANGE_END_BATTLE: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; - break; + break; + case FORM_CHANGE_END_BATTLE_TERRAIN: + if (gBattleTerrain == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; case FORM_CHANGE_WITHDRAW: case FORM_CHANGE_FAINT: targetSpecies = formChanges[i].targetSpecies; From 0eccbdf980e09c4de4a11f63ea1cad2db7d9d9f7 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 6 Nov 2022 00:36:25 -0300 Subject: [PATCH 018/131] Primal Reversion at the beginning of a battle now happens in the switchin ability loop, making it happen by speed order. --- src/battle_main.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 1aefd71b0f..6abc19083b 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3678,18 +3678,6 @@ static void TryDoEventsBeforeFirstTurn(void) } memset(gTotemBoosts, 0, sizeof(gTotemBoosts)); // erase all totem boosts just to be safe - // Primal Reversion - for (i = 0; i < gBattlersCount; i++) - { - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB - && GetBattleFormChangeTargetSpecies(i, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) - { - gBattlerAttacker = i; - BattleScriptExecute(BattleScript_PrimalReversion); - return; - } - } - // Check neutralizing gas if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) return; @@ -3698,6 +3686,14 @@ static void TryDoEventsBeforeFirstTurn(void) while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount) { gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++]; + + // Primal Reversion + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_PRIMAL_ORB + && GetBattleFormChangeTargetSpecies(gBattlerAttacker, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) + { + BattleScriptExecute(BattleScript_PrimalReversion); + return; + } if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0) return; } From 62912f8caf852eb453fe07a1fb504123d1a50e2e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 6 Nov 2022 16:01:07 -0300 Subject: [PATCH 019/131] Battle indicator now depends on species instead of held item - This is to avoid a situation where a user would plop a Primal Groudon and its indicator would become Alpha if it doesn't have a Red Orb. --- include/constants/form_change_types.h | 1 + src/battle_interface.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index 8701a9497c..b9d6c89424 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -81,5 +81,6 @@ // Form change that activates automatically when entering battle with the specified item. // If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to the Alpha symbol. +// The battle indicator icon is based on the species, with Primal Groudon's as Omega and otherwise being Alpha. // param1: item to hold. #define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 13 diff --git a/src/battle_interface.c b/src/battle_interface.c index c3d97f1379..f7882c15bb 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1560,12 +1560,12 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) } else if (IsBattlerPrimalReverted(battlerId)) { - if (gBattleMons[battlerId].item == ITEM_RED_ORB) + if (gBattleMons[battlerId].species == SPECIES_GROUDON_PRIMAL) { LoadSpritePalette(&sSpritePalette_OmegaIndicator); LoadSpriteSheet(&sSpriteSheet_OmegaIndicator); } - else // ITEM_BLUE_ORB + else // SPECIES_KYOGRE_PRIMAL { LoadSpritePalette(&sSpritePalette_AlphaIndicator); LoadSpriteSheet(&sSpriteSheet_AlphaIndicator); @@ -1589,9 +1589,9 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) } else if (IsBattlerPrimalReverted(battlerId)) { - if (gBattleMons[battlerId].item == ITEM_RED_ORB) + if (gBattleMons[battlerId].species == SPECIES_GROUDON_PRIMAL) spriteId = CreateSpriteAtEnd(&sSpriteTemplate_OmegaIndicator, x, y, 0); - else // ITEM_BLUE_ORB + else // SPECIES_KYOGRE_PRIMAL spriteId = CreateSpriteAtEnd(&sSpriteTemplate_AlphaIndicator, x, y, 0); } From 2ef2134be1a04e79bc09dfb35dd0ceda59ff4f2b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 6 Nov 2022 17:12:34 -0300 Subject: [PATCH 020/131] Moved Hunger Switch to form change table. --- data/battle_scripts_1.s | 1 + include/constants/form_change_types.h | 4 ++++ src/battle_ai_main.c | 4 ---- src/battle_util.c | 19 ++++++------------- src/data/pokemon/form_change_tables.h | 8 +++++--- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 472b1c9d1d..34a1bead89 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7525,6 +7525,7 @@ BattleScript_AttackerFormChangeEnd3:: BattleScript_AttackerFormChangeEnd3NoPopup:: call BattleScript_AttackerFormChangeNoPopup + end3 BattleScript_AttackerFormChangeMoveEffect:: waitmessage 1 diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index b9d6c89424..f6a858f976 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -84,3 +84,7 @@ // The battle indicator icon is based on the species, with Primal Groudon's as Omega and otherwise being Alpha. // param1: item to hold. #define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 13 + +// Form change that activates automatically when the turn ends. +// param1: ability to check. +#define FORM_CHANGE_BATTLE_TURN_END 14 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 70818a29c3..25e06806bb 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3817,7 +3817,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_KINGS_SHIELD: - #if (defined SPECIES_AEGISLASH && defined SPECIES_AEGISLASH_BLADE) if (AI_DATA->abilities[battlerAtk] == ABILITY_STANCE_CHANGE //Special logic for Aegislash && gBattleMons[battlerAtk].species == SPECIES_AEGISLASH_BLADE && !IsBattlerIncapacitated(battlerDef, AI_DATA->abilities[battlerDef])) @@ -3825,7 +3824,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 3; break; } - #endif //fallthrough default: // protect ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); @@ -4484,7 +4482,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 3; break; case EFFECT_RELIC_SONG: - #if (defined SPECIES_MELOETTA && defined SPECIES_MELOETTA_PIROUETTE) if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) // Don't try to change form if it's transformed. { if (gBattleMons[battlerAtk].species == SPECIES_MELOETTA && gBattleMons[battlerDef].defense < gBattleMons[battlerDef].spDefense) @@ -4492,7 +4489,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (gBattleMons[battlerAtk].species == SPECIES_MELOETTA_PIROUETTE && gBattleMons[battlerDef].spDefense < gBattleMons[battlerDef].defense) score += 3; // Change to Aria if can do more damage } - #endif break; case EFFECT_ELECTRIC_TERRAIN: case EFFECT_MISTY_TERRAIN: diff --git a/src/battle_util.c b/src/battle_util.c index 52a3202007..5629acc95b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5019,18 +5019,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_HUNGER_SWITCH: - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { - if (gBattleMons[battler].species == SPECIES_MORPEKO) - { - gBattleMons[battler].species = SPECIES_MORPEKO_HANGRY; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); - } - else if (gBattleMons[battler].species == SPECIES_MORPEKO_HANGRY) - { - gBattleMons[battler].species = SPECIES_MORPEKO; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); - } + BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); effect++; } break; @@ -9788,7 +9779,6 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) targetSpecies = formChanges[i].targetSpecies; break; case FORM_CHANGE_BATTLE_HP_PERCENT: - { if (formChanges[i].param1 == GetBattlerAbility(battlerId)) { // We multiply by 100 to make sure that integer division doesn't mess with the health check. @@ -9806,7 +9796,10 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) } } break; - } + case FORM_CHANGE_BATTLE_TURN_END: + if (formChanges[i].param1 == GetBattlerAbility(battlerId)) + targetSpecies = formChanges[i].targetSpecies; + break; } } } diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 7b8c4a6ce7..9f01f83203 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -604,9 +604,11 @@ static const struct FormChange sCramorantFormChangeTable[] = { }; static const struct FormChange sMorpekoFormChangeTable[] = { - {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, - {FORM_CHANGE_FAINT, SPECIES_MORPEKO}, - {FORM_CHANGE_END_BATTLE, SPECIES_MORPEKO}, + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO_HANGRY, ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO , ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, + {FORM_CHANGE_FAINT, SPECIES_MORPEKO}, + {FORM_CHANGE_END_BATTLE, SPECIES_MORPEKO}, {FORM_CHANGE_TERMINATOR}, }; From 034ba7d5d2a345c27de32019b869319a9dbed94a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 26 Dec 2022 08:59:37 -0300 Subject: [PATCH 021/131] Fixed usage of gBattleStruct->changedSpecies so its only used by player's party --- src/battle_util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index b3b16f255c..6a31bc9e2b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9796,8 +9796,8 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) targetSpecies = GetBattleFormChangeTargetSpecies(battlerId, method); if (targetSpecies != SPECIES_NONE) { - // Saves the original species on the first form change. - if (gBattleStruct->changedSpecies[monId] == SPECIES_NONE) + // Saves the original species on the first form change for the player. + if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE) gBattleStruct->changedSpecies[monId] = gBattleMons[battlerId].species; TryToSetBattleFormChangeMoves(&party[monId], method); @@ -9810,8 +9810,8 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); if (targetSpecies != SPECIES_NONE) { - // Saves the original species on the first form change. - if (gBattleStruct->changedSpecies[monId] == SPECIES_NONE) + // Saves the original species on the first form change for the player. + if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE) gBattleStruct->changedSpecies[monId] = targetSpecies; TryToSetBattleFormChangeMoves(&party[monId], method); From b5b7631be75619384f889147b964f08b694c5238 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 26 Dec 2022 09:14:28 -0300 Subject: [PATCH 022/131] Added guards to form_change_types.h --- include/constants/form_change_types.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index f6a858f976..4e60904aa6 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -1,3 +1,5 @@ +#ifndef GUARD_CONSTANTS_FORM_CHANGE_TYPES_H +#define GUARD_CONSTANTS_FORM_CHANGE_TYPES_H // FORM_CHANGE_BATTLE_HP_PERCENT param2 arguments #define HP_HIGHER_THAN 1 @@ -88,3 +90,5 @@ // Form change that activates automatically when the turn ends. // param1: ability to check. #define FORM_CHANGE_BATTLE_TURN_END 14 + +#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H From 6e134bb7dc0b5650946318a28cbe72a2e5743e24 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 17 Feb 2023 12:52:43 -0300 Subject: [PATCH 023/131] Removed pointless IsBattlerHpLow function --- src/battle_message.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/battle_message.c b/src/battle_message.c index 2b8005f64b..9c8a1b7020 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3899,14 +3899,6 @@ static u32 GetEnemyMonCount(bool32 onlyAlive) return count; } -static bool32 IsBattlerHpLow(u32 battler) -{ - if ((gBattleMons[battler].hp * 100) / gBattleMons[battler].maxHP < 25) - return TRUE; - else - return FALSE; -} - bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which) { s32 i; @@ -3931,7 +3923,7 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which) case TRAINER_SLIDE_LAST_LOW_HP: if (sTrainerSlides[i].msgLastLowHp != NULL && GetEnemyMonCount(TRUE) == 1 - && IsBattlerHpLow(battlerId) + && gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4) && !gBattleStruct->trainerSlideLowHpMsgDone) { gBattleStruct->trainerSlideLowHpMsgDone = TRUE; From 3a91a5c930d8c06de95882b5ca0ce90d017cbbc9 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 17 Feb 2023 12:53:24 -0300 Subject: [PATCH 024/131] =?UTF-8?q?Added=20new=20trainer=20slide-in=20msg?= =?UTF-8?q?=20conditions=20Now=20they=20can=20say=20something:=20-When=20t?= =?UTF-8?q?heir=20last=20Pok=C3=A9mon's=20HP=20is=20between=2025%=20and=20?= =?UTF-8?q?50%.=20-When=20a=20critical=20hit=20is=20dealt=20to=20their=20f?= =?UTF-8?q?irst=20Pok=C3=A9mon=20for=20the=20first=20time.=20-When=20a=20s?= =?UTF-8?q?uper=20effective=20hit=20is=20dealt=20to=20their=20first=20Pok?= =?UTF-8?q?=C3=A9mon=20for=20the=20first=20time.=20-When=20a=20STAB=20move?= =?UTF-8?q?=20is=20used=20against=20(but=20doesn't=20faint)=20the=20oppone?= =?UTF-8?q?nt's=20Pok=C3=A9mon.=20-When=20the=20Player's=20Pok=C3=A9mon's?= =?UTF-8?q?=20move=20doesn't=20affect=20the=20opponent's=20Pok=C3=A9mon.?= =?UTF-8?q?=20-When=20they're=20about=20to=20trigger=20a=20Mega=20Evolutio?= =?UTF-8?q?n.=20-When=20they're=20about=20to=20trigger=20a=20Z-Move.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Misc. changes: -Split GetEnemyMonCount for readability's sake. -Optimized the size allocated to trainerSlideLowHpMsgDone. --- asm/macros/battle_script.inc | 8 + data/battle_scripts_1.s | 8 + include/battle.h | 9 +- include/battle_message.h | 7 + include/constants/battle_script_commands.h | 338 +++++++++++---------- src/battle_main.c | 10 + src/battle_message.c | 109 ++++++- src/battle_script_commands.c | 35 +++ src/battle_util.c | 10 + 9 files changed, 356 insertions(+), 178 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 4f11fc78b8..e24e20e6e9 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2049,6 +2049,14 @@ .4byte \jumpInstr .endm + .macro trytrainerslidezmovemsg battler:req + various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE + .endm + + .macro trytrainerslidemegaevolutionmsg battler:req + various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ae92aba7cf..c6c9626384 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7763,6 +7763,8 @@ BattleScript_FocusPunchSetUp:: end2 BattleScript_MegaEvolution:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidemegaevolutionmsg BS_ATTACKER printstring STRINGID_MEGAEVOREACTING waitmessage B_WAIT_TIME_LONG setbyte gIsCriticalHit, 0 @@ -7777,6 +7779,8 @@ BattleScript_MegaEvolution:: end2 BattleScript_WishMegaEvolution:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidemegaevolutionmsg BS_ATTACKER printstring STRINGID_FERVENTWISHREACHED waitmessage B_WAIT_TIME_LONG setbyte gIsCriticalHit, 0 @@ -9989,6 +9993,8 @@ BattleScript_JabocaRowapBerryActivate_Dmg: @ z moves / effects BattleScript_ZMoveActivateDamaging:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidezmovemsg BS_ATTACKER printstring STRINGID_ZPOWERSURROUNDS playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL printstring STRINGID_ZMOVEUNLEASHED @@ -9996,6 +10002,8 @@ BattleScript_ZMoveActivateDamaging:: return BattleScript_ZMoveActivateStatus:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidezmovemsg BS_ATTACKER savetarget printstring STRINGID_ZPOWERSURROUNDS playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL diff --git a/include/battle.h b/include/battle.h index 8be922384f..f4b10c813c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -620,7 +620,7 @@ struct BattleStruct struct MegaEvolutionData mega; struct ZMoveData zmove; const u8 *trainerSlideMsg; - bool8 trainerSlideLowHpMsgDone; + bool8 trainerSlideLowHpMsgDone:1; u8 introState; u8 ateBerry[2]; // array id determined by side, each party pokemon as bit u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages @@ -655,6 +655,13 @@ struct BattleStruct u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching) bool8 allowedToChangeFormInWeather[PARTY_SIZE][2]; // For each party member and side, used by Ice Face. u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party. + bool8 trainerSlideHalfHpMsgDone:1; + u8 trainerSlideFirstCriticalHitMsgState:2; + u8 trainerSlideFirstSuperEffectiveHitMsgState:2; + u8 trainerSlideFirstSTABMoveMsgState:2; + u8 trainerSlidePlayerMonUnaffectedMsgState:2; + bool8 trainerSlideMegaEvolutionMsgDone:1; + bool8 trainerSlideZMoveMsgDone:1; }; #define F_DYNAMIC_TYPE_1 (1 << 6) diff --git a/include/battle_message.h b/include/battle_message.h index 9f6905abd3..57c6c21c24 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -229,6 +229,13 @@ enum TRAINER_SLIDE_LAST_SWITCHIN, TRAINER_SLIDE_LAST_LOW_HP, TRAINER_SLIDE_FIRST_DOWN, + TRAINER_SLIDE_LAST_HALF_HP, + TRAINER_SLIDE_FIRST_CRITICAL_HIT, + TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT, + TRAINER_SLIDE_FIRST_STAB_MOVE, + TRAINER_SLIDE_PLAYER_MON_UNAFFECTED, + TRAINER_SLIDE_MEGA_EVOLUTION, + TRAINER_SLIDE_Z_MOVE, }; void BufferStringBattle(u16 stringID); diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 68e927d75f..f55628315c 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -89,174 +89,176 @@ #define CMP_NO_COMMON_BITS 5 // Cmd_various -#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0 -#define VARIOUS_SET_MAGIC_COAT_TARGET 1 -#define VARIOUS_IS_RUNNING_IMPOSSIBLE 2 -#define VARIOUS_GET_MOVE_TARGET 3 -#define VARIOUS_GET_BATTLER_FAINTED 4 -#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 5 -#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 6 -#define VARIOUS_RESET_PLAYER_FAINTED 7 -#define VARIOUS_PALACE_FLAVOR_TEXT 8 -#define VARIOUS_ARENA_JUDGMENT_WINDOW 9 -#define VARIOUS_ARENA_OPPONENT_MON_LOST 10 -#define VARIOUS_ARENA_PLAYER_MON_LOST 11 -#define VARIOUS_ARENA_BOTH_MONS_LOST 12 -#define VARIOUS_EMIT_YESNOBOX 13 -#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 14 -#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 15 -#define VARIOUS_ARENA_JUDGMENT_STRING 16 -#define VARIOUS_ARENA_WAIT_STRING 17 -#define VARIOUS_WAIT_CRY 18 -#define VARIOUS_RETURN_OPPONENT_MON1 19 -#define VARIOUS_RETURN_OPPONENT_MON2 20 -#define VARIOUS_VOLUME_DOWN 21 -#define VARIOUS_VOLUME_UP 22 -#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 23 -#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 24 -#define VARIOUS_SET_TELEPORT_OUTCOME 25 -#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26 -#define VARIOUS_STAT_TEXT_BUFFER 27 -#define VARIOUS_SWITCHIN_ABILITIES 28 -#define VARIOUS_SAVE_TARGET 29 -#define VARIOUS_RESTORE_TARGET 30 -#define VARIOUS_INSTANT_HP_DROP 31 -#define VARIOUS_CLEAR_STATUS 32 -#define VARIOUS_RESTORE_PP 33 -#define VARIOUS_TRY_ACTIVATE_MOXIE 34 -#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 35 -#define VARIOUS_PLAY_MOVE_ANIMATION 36 -#define VARIOUS_SET_LUCKY_CHANT 37 -#define VARIOUS_SUCKER_PUNCH_CHECK 38 -#define VARIOUS_SET_SIMPLE_BEAM 39 -#define VARIOUS_TRY_ENTRAINMENT 40 -#define VARIOUS_SET_LAST_USED_ABILITY 41 -#define VARIOUS_TRY_HEAL_PULSE 42 -#define VARIOUS_TRY_QUASH 43 -#define VARIOUS_INVERT_STAT_STAGES 44 -#define VARIOUS_SET_TERRAIN 45 -#define VARIOUS_TRY_ME_FIRST 46 -#define VARIOUS_JUMP_IF_BATTLE_END 47 -#define VARIOUS_TRY_ELECTRIFY 48 -#define VARIOUS_TRY_REFLECT_TYPE 49 -#define VARIOUS_TRY_SOAK 50 -#define VARIOUS_HANDLE_MEGA_EVO 51 -#define VARIOUS_TRY_LAST_RESORT 52 -#define VARIOUS_ARGUMENT_STATUS_EFFECT 53 -#define VARIOUS_TRY_HIT_SWITCH_TARGET 54 -#define VARIOUS_TRY_AUTOTOMIZE 55 -#define VARIOUS_TRY_COPYCAT 56 -#define VARIOUS_ABILITY_POPUP 57 -#define VARIOUS_DEFOG 58 -#define VARIOUS_JUMP_IF_TARGET_ALLY 59 -#define VARIOUS_TRY_SYNCHRONOISE 60 -#define VARIOUS_PSYCHO_SHIFT 61 -#define VARIOUS_CURE_STATUS 62 -#define VARIOUS_POWER_TRICK 63 -#define VARIOUS_AFTER_YOU 64 -#define VARIOUS_BESTOW 65 -#define VARIOUS_ARGUMENT_TO_MOVE_EFFECT 66 -#define VARIOUS_JUMP_IF_NOT_GROUNDED 67 -#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 68 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 69 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 70 -#define VARIOUS_SET_AURORA_VEIL 71 -#define VARIOUS_TRY_THIRD_TYPE 72 -#define VARIOUS_ACUPRESSURE 73 -#define VARIOUS_SET_POWDER 74 -#define VARIOUS_SPECTRAL_THIEF 75 -#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 76 -#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 77 -#define VARIOUS_JUMP_IF_ROAR_FAILS 78 -#define VARIOUS_TRY_INSTRUCT 79 -#define VARIOUS_JUMP_IF_NOT_BERRY 80 -#define VARIOUS_TRACE_ABILITY 81 -#define VARIOUS_UPDATE_NICK 82 -#define VARIOUS_TRY_ILLUSION_OFF 83 -#define VARIOUS_SET_SPRITEIGNORE0HP 84 -#define VARIOUS_HANDLE_FORM_CHANGE 85 -#define VARIOUS_GET_STAT_VALUE 86 -#define VARIOUS_JUMP_IF_FULL_HP 87 -#define VARIOUS_LOSE_TYPE 88 -#define VARIOUS_TRY_ACTIVATE_SOULHEART 89 -#define VARIOUS_TRY_ACTIVATE_RECEIVER 90 -#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 91 -#define VARIOUS_TRY_FRISK 92 -#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 93 -#define VARIOUS_TRY_FAIRY_LOCK 94 -#define VARIOUS_JUMP_IF_NO_ALLY 95 -#define VARIOUS_POISON_TYPE_IMMUNITY 96 -#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 97 -#define VARIOUS_INFATUATE_WITH_BATTLER 98 -#define VARIOUS_SET_LAST_USED_ITEM 99 -#define VARIOUS_PARALYZE_TYPE_IMMUNITY 100 -#define VARIOUS_JUMP_IF_ABSENT 101 -#define VARIOUS_DESTROY_ABILITY_POPUP 102 -#define VARIOUS_TOTEM_BOOST 103 -#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 -#define VARIOUS_MOVEEND_ITEM_EFFECTS 105 -#define VARIOUS_TERRAIN_SEED 106 -#define VARIOUS_MAKE_INVISIBLE 107 -#define VARIOUS_ROOM_SERVICE 108 -#define VARIOUS_JUMP_IF_TERRAIN_AFFECTED 109 -#define VARIOUS_EERIE_SPELL_PP_REDUCE 110 -#define VARIOUS_JUMP_IF_TEAM_HEALTHY 111 -#define VARIOUS_TRY_HEAL_QUARTER_HP 112 -#define VARIOUS_REMOVE_TERRAIN 113 -#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114 -#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 115 -#define VARIOUS_GET_ROTOTILLER_TARGETS 116 -#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 117 -#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 118 -#define VARIOUS_CONSUME_BERRY 119 -#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 120 -#define VARIOUS_HANDLE_PRIMAL_REVERSION 121 -#define VARIOUS_APPLY_PLASMA_FISTS 122 -#define VARIOUS_JUMP_IF_SPECIES 123 -#define VARIOUS_UPDATE_ABILITY_POPUP 124 -#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125 -#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126 -#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127 -#define VARIOUS_PHOTON_GEYSER_CHECK 128 -#define VARIOUS_SHELL_SIDE_ARM_CHECK 129 -#define VARIOUS_TRY_NO_RETREAT 130 -#define VARIOUS_TRY_TAR_SHOT 131 -#define VARIOUS_CAN_TAR_SHOT_WORK 132 -#define VARIOUS_CHECK_POLTERGEIST 133 -#define VARIOUS_SET_OCTOLOCK 134 -#define VARIOUS_CUT_1_3_HP_RAISE_STATS 135 -#define VARIOUS_TRY_END_NEUTRALIZING_GAS 136 -#define VARIOUS_JUMP_IF_UNDER_200 137 -#define VARIOUS_SET_SKY_DROP 138 -#define VARIOUS_CLEAR_SKY_DROP 139 -#define VARIOUS_SKY_DROP_YAWN 140 -#define VARIOUS_JUMP_IF_CANT_FLING 141 -#define VARIOUS_JUMP_IF_HOLD_EFFECT 142 -#define VARIOUS_CURE_CERTAIN_STATUSES 143 -#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 144 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 145 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 146 -#define VARIOUS_SAVE_BATTLER_ITEM 147 -#define VARIOUS_RESTORE_BATTLER_ITEM 148 -#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 149 -#define VARIOUS_SET_BEAK_BLAST 150 -#define VARIOUS_SWAP_SIDE_STATUSES 151 -#define VARIOUS_SET_Z_EFFECT 152 -#define VARIOUS_TRY_SYMBIOSIS 153 -#define VARIOUS_CAN_TELEPORT 154 -#define VARIOUS_GET_BATTLER_SIDE 155 -#define VARIOUS_CHECK_PARENTAL_BOND_COUNTER 156 -#define VARIOUS_SWAP_STATS 157 -#define VARIOUS_JUMP_IF_ROD 158 -#define VARIOUS_JUMP_IF_ABSORB 159 -#define VARIOUS_JUMP_IF_MOTOR 160 -#define VARIOUS_TEATIME_INVUL 161 -#define VARIOUS_TEATIME_TARGETS 162 -#define VARIOUS_TRY_WIND_RIDER_POWER 163 -#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 164 -#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 165 -#define VARIOUS_JUMP_IF_NO_VALID_TARGETS 166 -#define VARIOUS_JUMP_IF_EMERGENCY_EXITED 167 +#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0 +#define VARIOUS_SET_MAGIC_COAT_TARGET 1 +#define VARIOUS_IS_RUNNING_IMPOSSIBLE 2 +#define VARIOUS_GET_MOVE_TARGET 3 +#define VARIOUS_GET_BATTLER_FAINTED 4 +#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 5 +#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 6 +#define VARIOUS_RESET_PLAYER_FAINTED 7 +#define VARIOUS_PALACE_FLAVOR_TEXT 8 +#define VARIOUS_ARENA_JUDGMENT_WINDOW 9 +#define VARIOUS_ARENA_OPPONENT_MON_LOST 10 +#define VARIOUS_ARENA_PLAYER_MON_LOST 11 +#define VARIOUS_ARENA_BOTH_MONS_LOST 12 +#define VARIOUS_EMIT_YESNOBOX 13 +#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 14 +#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 15 +#define VARIOUS_ARENA_JUDGMENT_STRING 16 +#define VARIOUS_ARENA_WAIT_STRING 17 +#define VARIOUS_WAIT_CRY 18 +#define VARIOUS_RETURN_OPPONENT_MON1 19 +#define VARIOUS_RETURN_OPPONENT_MON2 20 +#define VARIOUS_VOLUME_DOWN 21 +#define VARIOUS_VOLUME_UP 22 +#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 23 +#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 24 +#define VARIOUS_SET_TELEPORT_OUTCOME 25 +#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26 +#define VARIOUS_STAT_TEXT_BUFFER 27 +#define VARIOUS_SWITCHIN_ABILITIES 28 +#define VARIOUS_SAVE_TARGET 29 +#define VARIOUS_RESTORE_TARGET 30 +#define VARIOUS_INSTANT_HP_DROP 31 +#define VARIOUS_CLEAR_STATUS 32 +#define VARIOUS_RESTORE_PP 33 +#define VARIOUS_TRY_ACTIVATE_MOXIE 34 +#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 35 +#define VARIOUS_PLAY_MOVE_ANIMATION 36 +#define VARIOUS_SET_LUCKY_CHANT 37 +#define VARIOUS_SUCKER_PUNCH_CHECK 38 +#define VARIOUS_SET_SIMPLE_BEAM 39 +#define VARIOUS_TRY_ENTRAINMENT 40 +#define VARIOUS_SET_LAST_USED_ABILITY 41 +#define VARIOUS_TRY_HEAL_PULSE 42 +#define VARIOUS_TRY_QUASH 43 +#define VARIOUS_INVERT_STAT_STAGES 44 +#define VARIOUS_SET_TERRAIN 45 +#define VARIOUS_TRY_ME_FIRST 46 +#define VARIOUS_JUMP_IF_BATTLE_END 47 +#define VARIOUS_TRY_ELECTRIFY 48 +#define VARIOUS_TRY_REFLECT_TYPE 49 +#define VARIOUS_TRY_SOAK 50 +#define VARIOUS_HANDLE_MEGA_EVO 51 +#define VARIOUS_TRY_LAST_RESORT 52 +#define VARIOUS_ARGUMENT_STATUS_EFFECT 53 +#define VARIOUS_TRY_HIT_SWITCH_TARGET 54 +#define VARIOUS_TRY_AUTOTOMIZE 55 +#define VARIOUS_TRY_COPYCAT 56 +#define VARIOUS_ABILITY_POPUP 57 +#define VARIOUS_DEFOG 58 +#define VARIOUS_JUMP_IF_TARGET_ALLY 59 +#define VARIOUS_TRY_SYNCHRONOISE 60 +#define VARIOUS_PSYCHO_SHIFT 61 +#define VARIOUS_CURE_STATUS 62 +#define VARIOUS_POWER_TRICK 63 +#define VARIOUS_AFTER_YOU 64 +#define VARIOUS_BESTOW 65 +#define VARIOUS_ARGUMENT_TO_MOVE_EFFECT 66 +#define VARIOUS_JUMP_IF_NOT_GROUNDED 67 +#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 68 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 69 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 70 +#define VARIOUS_SET_AURORA_VEIL 71 +#define VARIOUS_TRY_THIRD_TYPE 72 +#define VARIOUS_ACUPRESSURE 73 +#define VARIOUS_SET_POWDER 74 +#define VARIOUS_SPECTRAL_THIEF 75 +#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 76 +#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 77 +#define VARIOUS_JUMP_IF_ROAR_FAILS 78 +#define VARIOUS_TRY_INSTRUCT 79 +#define VARIOUS_JUMP_IF_NOT_BERRY 80 +#define VARIOUS_TRACE_ABILITY 81 +#define VARIOUS_UPDATE_NICK 82 +#define VARIOUS_TRY_ILLUSION_OFF 83 +#define VARIOUS_SET_SPRITEIGNORE0HP 84 +#define VARIOUS_HANDLE_FORM_CHANGE 85 +#define VARIOUS_GET_STAT_VALUE 86 +#define VARIOUS_JUMP_IF_FULL_HP 87 +#define VARIOUS_LOSE_TYPE 88 +#define VARIOUS_TRY_ACTIVATE_SOULHEART 89 +#define VARIOUS_TRY_ACTIVATE_RECEIVER 90 +#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 91 +#define VARIOUS_TRY_FRISK 92 +#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 93 +#define VARIOUS_TRY_FAIRY_LOCK 94 +#define VARIOUS_JUMP_IF_NO_ALLY 95 +#define VARIOUS_POISON_TYPE_IMMUNITY 96 +#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 97 +#define VARIOUS_INFATUATE_WITH_BATTLER 98 +#define VARIOUS_SET_LAST_USED_ITEM 99 +#define VARIOUS_PARALYZE_TYPE_IMMUNITY 100 +#define VARIOUS_JUMP_IF_ABSENT 101 +#define VARIOUS_DESTROY_ABILITY_POPUP 102 +#define VARIOUS_TOTEM_BOOST 103 +#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 +#define VARIOUS_MOVEEND_ITEM_EFFECTS 105 +#define VARIOUS_TERRAIN_SEED 106 +#define VARIOUS_MAKE_INVISIBLE 107 +#define VARIOUS_ROOM_SERVICE 108 +#define VARIOUS_JUMP_IF_TERRAIN_AFFECTED 109 +#define VARIOUS_EERIE_SPELL_PP_REDUCE 110 +#define VARIOUS_JUMP_IF_TEAM_HEALTHY 111 +#define VARIOUS_TRY_HEAL_QUARTER_HP 112 +#define VARIOUS_REMOVE_TERRAIN 113 +#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114 +#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 115 +#define VARIOUS_GET_ROTOTILLER_TARGETS 116 +#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 117 +#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 118 +#define VARIOUS_CONSUME_BERRY 119 +#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 120 +#define VARIOUS_HANDLE_PRIMAL_REVERSION 121 +#define VARIOUS_APPLY_PLASMA_FISTS 122 +#define VARIOUS_JUMP_IF_SPECIES 123 +#define VARIOUS_UPDATE_ABILITY_POPUP 124 +#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125 +#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126 +#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127 +#define VARIOUS_PHOTON_GEYSER_CHECK 128 +#define VARIOUS_SHELL_SIDE_ARM_CHECK 129 +#define VARIOUS_TRY_NO_RETREAT 130 +#define VARIOUS_TRY_TAR_SHOT 131 +#define VARIOUS_CAN_TAR_SHOT_WORK 132 +#define VARIOUS_CHECK_POLTERGEIST 133 +#define VARIOUS_SET_OCTOLOCK 134 +#define VARIOUS_CUT_1_3_HP_RAISE_STATS 135 +#define VARIOUS_TRY_END_NEUTRALIZING_GAS 136 +#define VARIOUS_JUMP_IF_UNDER_200 137 +#define VARIOUS_SET_SKY_DROP 138 +#define VARIOUS_CLEAR_SKY_DROP 139 +#define VARIOUS_SKY_DROP_YAWN 140 +#define VARIOUS_JUMP_IF_CANT_FLING 141 +#define VARIOUS_JUMP_IF_HOLD_EFFECT 142 +#define VARIOUS_CURE_CERTAIN_STATUSES 143 +#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 144 +#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 145 +#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 146 +#define VARIOUS_SAVE_BATTLER_ITEM 147 +#define VARIOUS_RESTORE_BATTLER_ITEM 148 +#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 149 +#define VARIOUS_SET_BEAK_BLAST 150 +#define VARIOUS_SWAP_SIDE_STATUSES 151 +#define VARIOUS_SET_Z_EFFECT 152 +#define VARIOUS_TRY_SYMBIOSIS 153 +#define VARIOUS_CAN_TELEPORT 154 +#define VARIOUS_GET_BATTLER_SIDE 155 +#define VARIOUS_CHECK_PARENTAL_BOND_COUNTER 156 +#define VARIOUS_SWAP_STATS 157 +#define VARIOUS_JUMP_IF_ROD 158 +#define VARIOUS_JUMP_IF_ABSORB 159 +#define VARIOUS_JUMP_IF_MOTOR 160 +#define VARIOUS_TEATIME_INVUL 161 +#define VARIOUS_TEATIME_TARGETS 162 +#define VARIOUS_TRY_WIND_RIDER_POWER 163 +#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 164 +#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 165 +#define VARIOUS_JUMP_IF_NO_VALID_TARGETS 166 +#define VARIOUS_JUMP_IF_EMERGENCY_EXITED 167 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 168 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 169 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_main.c b/src/battle_main.c index b23d8af553..5ec0937f09 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3868,6 +3868,16 @@ void BattleTurnPassed(void) BattleScriptExecute(BattleScript_ArenaTurnBeginning); else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_LAST_LOW_HP)) BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2); + else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_LAST_HALF_HP)) + BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2); + else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_CRITICAL_HIT)) + BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2); + else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT)) + BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2); + else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_STAB_MOVE)) + BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2); + else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_PLAYER_MON_UNAFFECTED)) + BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2); } u8 IsRunningFromBattleImpossible(void) diff --git a/src/battle_message.c b/src/battle_message.c index 9c8a1b7020..6a301d9ee7 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3868,6 +3868,13 @@ struct TrainerSlide const u8 *msgLastSwitchIn; const u8 *msgLastLowHp; const u8 *msgFirstDown; + const u8 *msgLastHalfHp; + const u8 *msgFirstCriticalHit; + const u8 *msgFirstSuperEffectiveHit; + const u8 *msgFirstSTABMove; + const u8 *msgPlayerMonUnaffected; + const u8 *msgMegaEvolution; + const u8 *msgZMove; }; static const struct TrainerSlide sTrainerSlides[] = @@ -3879,20 +3886,39 @@ static const struct TrainerSlide sTrainerSlides[] = .msgLastSwitchIn = sText_AarghAlmostHadIt, .msgLastLowHp = sText_BoxIsFull, .msgFirstDown = sText_123Poof, + .msgLastHalfHp = sText_ShootSoClose, + .msgFirstCriticalHit = sText_CriticalHit, + .msgFirstSuperEffectiveHit = sText_SuperEffective, + .msgFirstSTABMove = sText_ABoosted, + .msgPlayerMonUnaffected = sText_ButNoEffect, + .msgMegaEvolution = sText_PowderExplodes, + .msgZMove = sText_Electromagnetism, }, */ }; -static u32 GetEnemyMonCount(bool32 onlyAlive) +static u32 GetAliveEnemyMonCount(void) { u32 i, count = 0; for (i = 0; i < PARTY_SIZE; i++) { u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2, NULL); - if (species != SPECIES_NONE - && species != SPECIES_EGG - && (!onlyAlive || GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL))) + if (species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL)) + count++; + } + + return count; +} + +static u32 GetTotalEnemyMonCount(void) +{ + u32 i, count = 0; + + for (i = 0; i < PARTY_SIZE; i++) + { + u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2, NULL); + if (species != SPECIES_NONE && species != SPECIES_EGG) count++; } @@ -3914,7 +3940,7 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which) switch (which) { case TRAINER_SLIDE_LAST_SWITCHIN: - if (sTrainerSlides[i].msgLastSwitchIn != NULL && GetEnemyMonCount(TRUE) == 1) + if (sTrainerSlides[i].msgLastSwitchIn != NULL && GetAliveEnemyMonCount() == 1) { gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastSwitchIn; return TRUE; @@ -3922,9 +3948,9 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which) break; case TRAINER_SLIDE_LAST_LOW_HP: if (sTrainerSlides[i].msgLastLowHp != NULL - && GetEnemyMonCount(TRUE) == 1 - && gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4) - && !gBattleStruct->trainerSlideLowHpMsgDone) + && GetAliveEnemyMonCount() == 1 + && gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4) + && !gBattleStruct->trainerSlideLowHpMsgDone) { gBattleStruct->trainerSlideLowHpMsgDone = TRUE; gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastLowHp; @@ -3932,12 +3958,77 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which) } break; case TRAINER_SLIDE_FIRST_DOWN: - if (sTrainerSlides[i].msgFirstDown != NULL && GetEnemyMonCount(TRUE) == GetEnemyMonCount(FALSE) - 1) + if (sTrainerSlides[i].msgFirstDown != NULL && GetAliveEnemyMonCount() == GetTotalEnemyMonCount() - 1) { gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstDown; return TRUE; } break; + case TRAINER_SLIDE_LAST_HALF_HP: + if (sTrainerSlides[i].msgLastHalfHp != NULL + && GetAliveEnemyMonCount() == 1 + && (gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 2) && gBattleMons[battlerId].hp > (gBattleMons[battlerId].maxHP / 4)) + && !gBattleStruct->trainerSlideHalfHpMsgDone) + { + gBattleStruct->trainerSlideHalfHpMsgDone = TRUE; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastHalfHp; + return TRUE; + } + break; + case TRAINER_SLIDE_FIRST_CRITICAL_HIT: + if (sTrainerSlides[i].msgFirstCriticalHit != NULL && gBattleStruct->trainerSlideFirstCriticalHitMsgState == 1) + { + gBattleStruct->trainerSlideFirstCriticalHitMsgState = 2; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstCriticalHit; + return TRUE; + } + break; + case TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT: + if (sTrainerSlides[i].msgFirstSuperEffectiveHit != NULL + && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState == 1 + && gBattleMons[battlerId].hp) + { + gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 2; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSuperEffectiveHit; + return TRUE; + } + break; + case TRAINER_SLIDE_FIRST_STAB_MOVE: + if (sTrainerSlides[i].msgFirstSTABMove != NULL + && gBattleStruct->trainerSlideFirstSTABMoveMsgState == 1 + && GetAliveEnemyMonCount() == GetTotalEnemyMonCount()) + { + gBattleStruct->trainerSlideFirstSTABMoveMsgState = 2; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSTABMove; + return TRUE; + } + break; + case TRAINER_SLIDE_PLAYER_MON_UNAFFECTED: + if (sTrainerSlides[i].msgPlayerMonUnaffected != NULL + && gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState == 1 + && GetAliveEnemyMonCount() == GetTotalEnemyMonCount()) + { + gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 2; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgPlayerMonUnaffected; + return TRUE; + } + break; + case TRAINER_SLIDE_MEGA_EVOLUTION: + if (sTrainerSlides[i].msgMegaEvolution != NULL && !gBattleStruct->trainerSlideMegaEvolutionMsgDone) + { + gBattleStruct->trainerSlideMegaEvolutionMsgDone = TRUE; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgMegaEvolution; + return TRUE; + } + break; + case TRAINER_SLIDE_Z_MOVE: + if (sTrainerSlides[i].msgZMove != NULL && !gBattleStruct->trainerSlideZMoveMsgDone) + { + gBattleStruct->trainerSlideZMoveMsgDone = TRUE; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgZMove; + return TRUE; + } + break; } break; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 87feb56271..683a979bdd 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2540,6 +2540,11 @@ static void Cmd_critmessage(void) if (gIsCriticalHit == TRUE && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker); + + // Signal for the trainer slide-in system. + if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstCriticalHitMsgState != 2) + gBattleStruct->trainerSlideFirstCriticalHitMsgState = 1; + gBattleCommunication[MSG_DISPLAY] = 1; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -2619,7 +2624,13 @@ static void Cmd_resultmessage(void) { case MOVE_RESULT_SUPER_EFFECTIVE: if (!gMultiHitCounter) // Don't print effectiveness on each hit in a multi hit attack + { + // Signal for the trainer slide-in system. + if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState != 2) + gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 1; + stringId = STRINGID_SUPEREFFECTIVE; + } break; case MOVE_RESULT_NOT_VERY_EFFECTIVE: if (!gMultiHitCounter) @@ -11040,6 +11051,30 @@ static void Cmd_various(void) gBattlescriptCurrInstr = cmd->nextInstr; return; } + case VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE: + { + VARIOUS_ARGS(); + if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_Z_MOVE)) + { + gBattleScripting.battler = gActiveBattler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet; + return; + } + break; + } + case VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION: + { + VARIOUS_ARGS(); + if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_MEGA_EVOLUTION)) + { + gBattleScripting.battler = gActiveBattler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet; + return; + } + break; + } } // End of switch (cmd->id) gBattlescriptCurrInstr = cmd->nextInstr; diff --git a/src/battle_util.c b/src/battle_util.c index 46f8d3a3d3..18ac8fa543 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1607,6 +1607,12 @@ void PrepareStringBattle(u16 stringId, u8 battler) } #endif + // Signal for the trainer slide-in system. + if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED) + && GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT + && gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState != 2) + gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 1; + gActiveBattler = battler; BtlController_EmitPrintString(BUFFER_A, stringId); MarkBattlerForControllerExec(gActiveBattler); @@ -9884,6 +9890,10 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat } } + // Signal for the trainer slide-in system. + if (GetBattlerSide(battlerDef) != B_SIDE_PLAYER && modifier && gBattleStruct->trainerSlideFirstSTABMoveMsgState != 2) + gBattleStruct->trainerSlideFirstSTABMoveMsgState = 1; + return modifier; } From 8a036e6007cdc8152a89b3ef211cb51fb759091e Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 27 Feb 2023 07:45:01 -0300 Subject: [PATCH 025/131] Made this build again --- src/battle_main.c | 10 +++++----- src/battle_message.c | 2 +- src/battle_script_commands.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 0f841a89be..d144590d59 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3868,15 +3868,15 @@ void BattleTurnPassed(void) BattleScriptExecute(BattleScript_ArenaTurnBeginning); else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_LOW_HP))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); - else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_HALF_HP)) + else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_HALF_HP))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); - else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_CRITICAL_HIT)) + else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_CRITICAL_HIT))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); - else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT)) + else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); - else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_STAB_MOVE)) + else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_STAB_MOVE))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); - else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_MON_UNAFFECTED)) + else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_MON_UNAFFECTED))) BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); } diff --git a/src/battle_message.c b/src/battle_message.c index a9536d5a13..f321da46c0 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3964,7 +3964,7 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which) case TRAINER_SLIDE_LAST_LOW_HP: if (sTrainerSlides[i].msgLastLowHp != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == 1 - && IsBattlerHpLow(battlerId) + && gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4) && !gBattleStruct->trainerSlideLowHpMsgDone) { gBattleStruct->trainerSlideLowHpMsgDone = TRUE; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e50aed2429..21e1d4d9c5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11170,11 +11170,11 @@ static void Cmd_various(void) case VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE: { VARIOUS_ARGS(); - if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_Z_MOVE)) + if ((i = ShouldDoTrainerSlide(gActiveBattler, TRAINER_SLIDE_Z_MOVE))) { gBattleScripting.battler = gActiveBattler; BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet; + gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); return; } break; @@ -11182,11 +11182,11 @@ static void Cmd_various(void) case VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION: { VARIOUS_ARGS(); - if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_MEGA_EVOLUTION)) + if ((i = ShouldDoTrainerSlide(gActiveBattler, TRAINER_SLIDE_MEGA_EVOLUTION))) { gBattleScripting.battler = gActiveBattler; BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet; + gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); return; } break; From ff15856820bd30e9820e8fb5a46b093e39f47a0d Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 2 Mar 2023 06:14:42 -0300 Subject: [PATCH 026/131] Added yet another trainer slide condition Now a trainer NPC can also say something before the first turn of a battle starts for good. --- include/battle.h | 1 + include/battle_message.h | 1 + src/battle_main.c | 3 +++ src/battle_message.c | 10 ++++++++++ 4 files changed, 15 insertions(+) diff --git a/include/battle.h b/include/battle.h index 3c2b6ed197..f3b788037e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -669,6 +669,7 @@ struct BattleStruct u8 trainerSlidePlayerMonUnaffectedMsgState:2; bool8 trainerSlideMegaEvolutionMsgDone:1; bool8 trainerSlideZMoveMsgDone:1; + bool8 trainerSlideBeforeFirstTurnMsgDone:1; }; #define F_DYNAMIC_TYPE_1 (1 << 6) diff --git a/include/battle_message.h b/include/battle_message.h index de60d6d026..93bb63022b 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -236,6 +236,7 @@ enum TRAINER_SLIDE_PLAYER_MON_UNAFFECTED, TRAINER_SLIDE_MEGA_EVOLUTION, TRAINER_SLIDE_Z_MOVE, + TRAINER_SLIDE_BEFORE_FIRST_TURN, }; void BufferStringBattle(u16 stringID); diff --git a/src/battle_main.c b/src/battle_main.c index d144590d59..a93bef7ac6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3776,6 +3776,9 @@ static void TryDoEventsBeforeFirstTurn(void) StopCryAndClearCrySongs(); BattleScriptExecute(BattleScript_ArenaTurnBeginning); } + + if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_BEFORE_FIRST_TURN))) + BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2); } static void HandleEndTurn_ContinueBattle(void) diff --git a/src/battle_message.c b/src/battle_message.c index f321da46c0..ed430e9f8c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3881,6 +3881,7 @@ struct TrainerSlide const u8 *msgPlayerMonUnaffected; const u8 *msgMegaEvolution; const u8 *msgZMove; + const u8 *msgBeforeFirstTurn; }; static const struct TrainerSlide sTrainerSlides[] = @@ -3899,6 +3900,7 @@ static const struct TrainerSlide sTrainerSlides[] = .msgPlayerMonUnaffected = sText_ButNoEffect, .msgMegaEvolution = sText_PowderExplodes, .msgZMove = sText_Electromagnetism, + .msgBeforeFirstTurn = sText_GravityIntensified, }, */ }; @@ -4044,6 +4046,14 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which) return TRUE; } break; + case TRAINER_SLIDE_BEFORE_FIRST_TURN: + if (sTrainerSlides[i].msgBeforeFirstTurn != NULL && !gBattleStruct->trainerSlideBeforeFirstTurnMsgDone) + { + gBattleStruct->trainerSlideBeforeFirstTurnMsgDone = TRUE; + gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgBeforeFirstTurn; + return TRUE; + } + break; } break; } From 46bdd21e7a9c96f4dbad84f775daef920a4d58ca Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 7 Mar 2023 11:39:47 -0300 Subject: [PATCH 027/131] Cleaned up stray comment --- src/battle_script_commands.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e8b23d43f9..360cef1252 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8670,7 +8670,6 @@ static bool32 CourtChangeSwapSideStatuses(void) SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp); } -//cmd->case_, gActiveBattler, TRUE static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega) { struct Pokemon *mon = GetBattlerPartyData(battlerId); From dbf757be886736e6a0f8f813cc8c0a544124a287 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 8 Mar 2023 11:07:44 -0500 Subject: [PATCH 028/131] Treat map data as const --- include/field_control_avatar.h | 2 +- include/fieldmap.h | 4 ++-- include/global.fieldmap.h | 22 +++++++++++----------- src/event_object_movement.c | 24 ++++++++++++------------ src/field_control_avatar.c | 24 ++++++++++++------------ src/fieldmap.c | 32 ++++++++++++++++---------------- src/item_use.c | 6 +++--- src/overworld.c | 6 +++--- src/trainer_hill.c | 3 ++- 9 files changed, 62 insertions(+), 61 deletions(-) diff --git a/include/field_control_avatar.h b/include/field_control_avatar.h index e02fcd5afe..b259eb53c1 100644 --- a/include/field_control_avatar.h +++ b/include/field_control_avatar.h @@ -32,7 +32,7 @@ bool8 TryDoDiveWarp(struct MapPosition *position, u16 b); int SetCableClubWarp(void); u8 TrySetDiveWarp(void); const u8 *GetInteractedLinkPlayerScript(struct MapPosition *position, u8 metatileBehavior, u8 direction); -u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position); +const u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position); void ClearPoisonStepCounter(void); #endif // GUARD_FIELDCONTROLAVATAR_H diff --git a/include/fieldmap.h b/include/fieldmap.h index f2dbefae86..47072bd1be 100644 --- a/include/fieldmap.h +++ b/include/fieldmap.h @@ -48,8 +48,8 @@ void LoadSecondaryTilesetPalette(struct MapLayout const *mapLayout); void CopySecondaryTilesetToVramUsingHeap(struct MapLayout const *mapLayout); void CopyPrimaryTilesetToVram(const struct MapLayout *); void CopySecondaryTilesetToVram(const struct MapLayout *); -struct MapHeader const *const GetMapHeaderFromConnection(struct MapConnection *connection); -struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y); +const struct MapHeader *const GetMapHeaderFromConnection(const struct MapConnection *connection); +const struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y); void MapGridSetMetatileImpassabilityAt(int x, int y, bool32 impassable); // field_region_map.c diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index d8fea5b23c..7461929c3a 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -50,10 +50,10 @@ struct MapLayout { /*0x00*/ s32 width; /*0x04*/ s32 height; - /*0x08*/ u16 *border; - /*0x0C*/ u16 *map; - /*0x10*/ struct Tileset *primaryTileset; - /*0x14*/ struct Tileset *secondaryTileset; + /*0x08*/ const u16 *border; + /*0x0C*/ const u16 *map; + /*0x10*/ const struct Tileset *primaryTileset; + /*0x14*/ const struct Tileset *secondaryTileset; }; struct BackupMapLayout @@ -98,7 +98,7 @@ struct CoordEvent u8 elevation; u16 trigger; u16 index; - u8 *script; + const u8 *script; }; struct BgEvent @@ -107,7 +107,7 @@ struct BgEvent u8 elevation; u8 kind; // The "kind" field determines how to access bgUnion union below. union { - u8 *script; + const u8 *script; struct { u16 item; u16 hiddenItemId; @@ -122,10 +122,10 @@ struct MapEvents u8 warpCount; u8 coordEventCount; u8 bgEventCount; - struct ObjectEventTemplate *objectEvents; - struct WarpEvent *warps; - struct CoordEvent *coordEvents; - struct BgEvent *bgEvents; + const struct ObjectEventTemplate *objectEvents; + const struct WarpEvent *warps; + const struct CoordEvent *coordEvents; + const struct BgEvent *bgEvents; }; struct MapConnection @@ -139,7 +139,7 @@ struct MapConnection struct MapConnections { s32 count; - struct MapConnection *connections; + const struct MapConnection *connections; }; struct MapHeader diff --git a/src/event_object_movement.c b/src/event_object_movement.c index be0c4ce26d..3025e0849a 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -131,9 +131,9 @@ static void SetObjectEventDynamicGraphicsId(struct ObjectEvent *); static void RemoveObjectEventInternal(struct ObjectEvent *); static u16 GetObjectEventFlagIdByObjectEventId(u8); static void UpdateObjectEventVisibility(struct ObjectEvent *, struct Sprite *); -static void MakeSpriteTemplateFromObjectEventTemplate(struct ObjectEventTemplate *, struct SpriteTemplate *, const struct SubspriteTable **); +static void MakeSpriteTemplateFromObjectEventTemplate(const struct ObjectEventTemplate *, struct SpriteTemplate *, const struct SubspriteTable **); static void GetObjectEventMovingCameraOffset(s16 *, s16 *); -static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8, u8, u8); +static const struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8, u8, u8); static void LoadObjectEventPalette(u16); static void RemoveObjectEventIfOutsideView(struct ObjectEvent *); static void SpawnObjectEventOnReturnToField(u8, s16, s16); @@ -147,7 +147,7 @@ static void SpriteCB_CameraObject(struct Sprite *); static void CameraObject_0(struct Sprite *); static void CameraObject_1(struct Sprite *); static void CameraObject_2(struct Sprite *); -static struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8, struct ObjectEventTemplate *, u8); +static const struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8, const struct ObjectEventTemplate *, u8); static void ClearObjectEventMovement(struct ObjectEvent *, struct Sprite *); static void ObjectEventSetSingleMovement(struct ObjectEvent *, struct Sprite *, u8); static void SetSpriteDataForNormalStep(struct Sprite *, u8, u8); @@ -1267,7 +1267,7 @@ static u8 GetObjectEventIdByLocalId(u8 localId) return OBJECT_EVENTS_COUNT; } -static u8 InitObjectEventStateFromTemplate(struct ObjectEventTemplate *template, u8 mapNum, u8 mapGroup) +static u8 InitObjectEventStateFromTemplate(const struct ObjectEventTemplate *template, u8 mapNum, u8 mapGroup) { struct ObjectEvent *objectEvent; u8 objectEventId; @@ -1398,7 +1398,7 @@ void RemoveAllObjectEventsExceptPlayer(void) } } -static u8 TrySetupObjectEventSprite(struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) +static u8 TrySetupObjectEventSprite(const struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) { u8 spriteId; u8 paletteSlot; @@ -1458,7 +1458,7 @@ static u8 TrySetupObjectEventSprite(struct ObjectEventTemplate *objectEventTempl return objectEventId; } -static u8 TrySpawnObjectEventTemplate(struct ObjectEventTemplate *objectEventTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) +static u8 TrySpawnObjectEventTemplate(const struct ObjectEventTemplate *objectEventTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) { u8 objectEventId; struct SpriteTemplate spriteTemplate; @@ -1512,7 +1512,7 @@ u8 SpawnSpecialObjectEventParameterized(u8 graphicsId, u8 movementBehavior, u8 l u8 TrySpawnObjectEvent(u8 localId, u8 mapNum, u8 mapGroup) { - struct ObjectEventTemplate *objectEventTemplate; + const struct ObjectEventTemplate *objectEventTemplate; s16 cameraX, cameraY; objectEventTemplate = GetObjectEventTemplateByLocalIdAndMap(localId, mapNum, mapGroup); @@ -1542,7 +1542,7 @@ static void CopyObjectGraphicsInfoToSpriteTemplate_WithMovementType(u16 graphics CopyObjectGraphicsInfoToSpriteTemplate(graphicsId, sMovementTypeCallbacks[movementType], spriteTemplate, subspriteTables); } -static void MakeSpriteTemplateFromObjectEventTemplate(struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables) +static void MakeSpriteTemplateFromObjectEventTemplate(const struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables) { CopyObjectGraphicsInfoToSpriteTemplate_WithMovementType(objectEventTemplate->graphicsId, objectEventTemplate->movementType, spriteTemplate, subspriteTables); } @@ -2374,7 +2374,7 @@ const u8 *GetObjectEventScriptPointerByObjectEventId(u8 objectEventId) static u16 GetObjectEventFlagIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) { - struct ObjectEventTemplate *obj = GetObjectEventTemplateByLocalIdAndMap(localId, mapNum, mapGroup); + const struct ObjectEventTemplate *obj = GetObjectEventTemplateByLocalIdAndMap(localId, mapNum, mapGroup); #ifdef UBFIX // BUG: The function may return NULL, and attempting to read from NULL may freeze the game using modern compilers. if (obj == NULL) @@ -2421,9 +2421,9 @@ u8 GetObjectEventBerryTreeId(u8 objectEventId) return gObjectEvents[objectEventId].trainerRange_berryTreeId; } -static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +static const struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) { - struct ObjectEventTemplate *templates; + const struct ObjectEventTemplate *templates; const struct MapHeader *mapHeader; u8 count; @@ -2441,7 +2441,7 @@ static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 loca return FindObjectEventTemplateByLocalId(localId, templates, count); } -static struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8 localId, struct ObjectEventTemplate *templates, u8 count) +static const struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8 localId, const struct ObjectEventTemplate *templates, u8 count) { u8 i; diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 9c526f0f72..3a0c97e8cf 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -60,8 +60,8 @@ static s8 GetWarpEventAtMapPosition(struct MapHeader *, struct MapPosition *); static void SetupWarp(struct MapHeader *, s8, struct MapPosition *); static bool8 TryDoorWarp(struct MapPosition *, u16, u8); static s8 GetWarpEventAtPosition(struct MapHeader *, u16, u16, u8); -static u8 *GetCoordEventScriptAtPosition(struct MapHeader *, u16, u16, u8); -static struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *, u16, u16, u8); +static const u8 *GetCoordEventScriptAtPosition(struct MapHeader *, u16, u16, u8); +static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *, u16, u16, u8); static bool8 TryStartCoordEventScript(struct MapPosition *); static bool8 TryStartWarpEventScript(struct MapPosition *, u16); static bool8 TryStartMiscWalkingScripts(u16); @@ -315,7 +315,7 @@ static const u8 *GetInteractedObjectEventScript(struct MapPosition *position, u8 static const u8 *GetInteractedBackgroundEventScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) { - struct BgEvent *bgEvent = GetBackgroundEventAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); + const struct BgEvent *bgEvent = GetBackgroundEventAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); if (bgEvent == NULL) return NULL; @@ -497,7 +497,7 @@ static bool8 TryStartStepBasedScript(struct MapPosition *position, u16 metatileB static bool8 TryStartCoordEventScript(struct MapPosition *position) { - u8 *script = GetCoordEventScriptAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); + const u8 *script = GetCoordEventScriptAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); if (script == NULL) return FALSE; @@ -861,7 +861,7 @@ static bool8 TryDoorWarp(struct MapPosition *position, u16 metatileBehavior, u8 static s8 GetWarpEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) { s32 i; - struct WarpEvent *warpEvent = mapHeader->events->warps; + const struct WarpEvent *warpEvent = mapHeader->events->warps; u8 warpCount = mapHeader->events->warpCount; for (i = 0; i < warpCount; i++, warpEvent++) @@ -875,7 +875,7 @@ static s8 GetWarpEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 e return WARP_ID_NONE; } -static u8 *TryRunCoordEventScript(struct CoordEvent *coordEvent) +static const u8 *TryRunCoordEventScript(const struct CoordEvent *coordEvent) { if (coordEvent != NULL) { @@ -895,10 +895,10 @@ static u8 *TryRunCoordEventScript(struct CoordEvent *coordEvent) return NULL; } -static u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +static const u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) { s32 i; - struct CoordEvent *coordEvents = mapHeader->events->coordEvents; + const struct CoordEvent *coordEvents = mapHeader->events->coordEvents; u8 coordEventCount = mapHeader->events->coordEventCount; for (i = 0; i < coordEventCount; i++) @@ -907,7 +907,7 @@ static u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 { if (coordEvents[i].elevation == elevation || coordEvents[i].elevation == 0) { - u8 *script = TryRunCoordEventScript(&coordEvents[i]); + const u8 *script = TryRunCoordEventScript(&coordEvents[i]); if (script != NULL) return script; } @@ -916,15 +916,15 @@ static u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 return NULL; } -u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position) +const u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position) { return GetCoordEventScriptAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); } -static struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) { u8 i; - struct BgEvent *bgEvents = mapHeader->events->bgEvents; + const struct BgEvent *bgEvents = mapHeader->events->bgEvents; u8 bgEventCount = mapHeader->events->bgEventCount; for (i = 0; i < bgEventCount; i++) diff --git a/src/fieldmap.c b/src/fieldmap.c index 89d6b602c2..df4db47b53 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -36,7 +36,7 @@ struct BackupMapLayout gBackupMapLayout; static const struct ConnectionFlags sDummyConnectionFlags = {0}; static void InitMapLayoutData(struct MapHeader *mapHeader); -static void InitBackupMapLayoutData(u16 *map, u16 width, u16 height); +static void InitBackupMapLayoutData(const u16 *map, u16 width, u16 height); static void FillSouthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset); static void FillNorthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset); static void FillWestConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset); @@ -44,14 +44,14 @@ static void FillEastConnection(struct MapHeader const *mapHeader, struct MapHead static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader); static void LoadSavedMapView(void); static bool8 SkipCopyingMetatileFromSavedMap(u16 *mapBlock, u16 mapWidth, u8 yMode); -static struct MapConnection *GetIncomingConnection(u8 direction, int x, int y); -static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, struct MapConnection *connection); +static const struct MapConnection *GetIncomingConnection(u8 direction, int x, int y); +static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, const struct MapConnection *connection); static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, int offset); #define GetBorderBlockAt(x, y)({ \ u16 block; \ int i; \ - u16 *border = gMapHeader.mapLayout->border; \ + const u16 *border = gMapHeader.mapLayout->border; /* Unused, they read it again below */ \ \ i = (x + 1) & 1; \ i += ((y + 1) & 1) * 2; \ @@ -63,7 +63,7 @@ static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, #define GetMapGridBlockAt(x, y) (AreCoordsWithinMapGridBounds(x, y) ? gBackupMapLayout.map[x + gBackupMapLayout.width * y] : GetBorderBlockAt(x, y)) -struct MapHeader const *const GetMapHeaderFromConnection(struct MapConnection *connection) +const struct MapHeader *const GetMapHeaderFromConnection(const struct MapConnection *connection) { return Overworld_GetMapHeaderByGroupAndId(connection->mapGroup, connection->mapNum); } @@ -116,7 +116,7 @@ static void InitMapLayoutData(struct MapHeader *mapHeader) } } -static void InitBackupMapLayoutData(u16 *map, u16 width, u16 height) +static void InitBackupMapLayoutData(const u16 *map, u16 width, u16 height) { u16 *dest; int y; @@ -133,7 +133,7 @@ static void InitBackupMapLayoutData(u16 *map, u16 width, u16 height) static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader) { int count; - struct MapConnection *connection; + const struct MapConnection *connection; int i; if (mapHeader->connections) @@ -171,7 +171,7 @@ static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader) static void FillConnection(int x, int y, struct MapHeader const *connectedMapHeader, int x2, int y2, int width, int height) { int i; - u16 *src; + const u16 *src; u16 *dest; int mapWidth; @@ -619,7 +619,7 @@ bool32 CanCameraMoveInDirection(int direction) return TRUE; } -static void SetPositionFromConnection(struct MapConnection *connection, int direction, int x, int y) +static void SetPositionFromConnection(const struct MapConnection *connection, int direction, int x, int y) { struct MapHeader const *mapHeader; mapHeader = GetMapHeaderFromConnection(connection); @@ -647,7 +647,7 @@ static void SetPositionFromConnection(struct MapConnection *connection, int dire bool8 CameraMove(int x, int y) { int direction; - struct MapConnection *connection; + const struct MapConnection *connection; int old_x, old_y; gCamera.active = FALSE; direction = GetPostCameraMoveMapBorderId(x, y); @@ -675,11 +675,11 @@ bool8 CameraMove(int x, int y) return gCamera.active; } -static struct MapConnection *GetIncomingConnection(u8 direction, int x, int y) +static const struct MapConnection *GetIncomingConnection(u8 direction, int x, int y) { int count; int i; - struct MapConnection *connection; + const struct MapConnection *connection; const struct MapConnections *connections = gMapHeader.connections; #ifdef UBFIX // UB: Multiple possible null dereferences @@ -696,7 +696,7 @@ static struct MapConnection *GetIncomingConnection(u8 direction, int x, int y) return NULL; } -static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, struct MapConnection *connection) +static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, const struct MapConnection *connection) { struct MapHeader const *mapHeader; mapHeader = GetMapHeaderFromConnection(connection); @@ -737,7 +737,7 @@ static int IsCoordInConnectingMap(int coord, int max) return FALSE; } -static int IsPosInConnectingMap(struct MapConnection *connection, int x, int y) +static int IsPosInConnectingMap(const struct MapConnection *connection, int x, int y) { struct MapHeader const *mapHeader; mapHeader = GetMapHeaderFromConnection(connection); @@ -753,10 +753,10 @@ static int IsPosInConnectingMap(struct MapConnection *connection, int x, int y) return FALSE; } -struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y) +const struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y) { int count; - struct MapConnection *connection; + const struct MapConnection *connection; int i; u8 direction; if (!gMapHeader.connections) diff --git a/src/item_use.c b/src/item_use.c index 41e8884968..8a02827176 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -375,7 +375,7 @@ static bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *events, u8 ta static bool8 IsHiddenItemPresentAtCoords(const struct MapEvents *events, s16 x, s16 y) { u8 bgEventCount = events->bgEventCount; - struct BgEvent *bgEvent = events->bgEvents; + const struct BgEvent *bgEvent = events->bgEvents; int i; for (i = 0; i < bgEventCount; i++) @@ -391,7 +391,7 @@ static bool8 IsHiddenItemPresentAtCoords(const struct MapEvents *events, s16 x, return FALSE; } -static bool8 IsHiddenItemPresentInConnection(struct MapConnection *connection, int x, int y) +static bool8 IsHiddenItemPresentInConnection(const struct MapConnection *connection, int x, int y) { u16 localX, localY; @@ -456,7 +456,7 @@ static void CheckForHiddenItemsInMapConnection(u8 taskId) || var2 > y || y >= height) { - struct MapConnection *conn = GetMapConnectionAtPos(x, y); + const struct MapConnection *conn = GetMapConnectionAtPos(x, y); if (conn && IsHiddenItemPresentInConnection(conn, x, y) == TRUE) SetDistanceOfClosestHiddenItem(taskId, x - playerX, y - playerY); } diff --git a/src/overworld.c b/src/overworld.c index 4f7cccdffb..70b102fd28 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -156,7 +156,7 @@ static void InitMenuBasedScript(const u8 *); static void LoadCableClubPlayer(s32, s32, struct CableClubPlayer *); static bool32 IsCableClubPlayerUnfrozen(struct CableClubPlayer *); static bool32 CanCableClubPlayerPressStart(struct CableClubPlayer *); -static u8 *TryGetTileEventScript(struct CableClubPlayer *); +static const u8 *TryGetTileEventScript(struct CableClubPlayer *); static bool32 PlayerIsAtSouthExit(struct CableClubPlayer *); static const u8 *TryInteractWithPlayer(struct CableClubPlayer *); static u16 KeyInterCB_DeferToRecvQueue(u32); @@ -482,7 +482,7 @@ void LoadObjEventTemplatesFromHeader(void) void LoadSaveblockObjEventScripts(void) { - struct ObjectEventTemplate *mapHeaderObjTemplates = gMapHeader.events->objectEvents; + const struct ObjectEventTemplate *mapHeaderObjTemplates = gMapHeader.events->objectEvents; struct ObjectEventTemplate *savObjTemplates = gSaveBlock1Ptr->objectEventTemplates; s32 i; @@ -2714,7 +2714,7 @@ static bool32 CanCableClubPlayerPressStart(struct CableClubPlayer *player) return FALSE; } -static u8 *TryGetTileEventScript(struct CableClubPlayer *player) +static const u8 *TryGetTileEventScript(struct CableClubPlayer *player) { if (player->movementMode != MOVEMENT_MODE_SCRIPTED) return FACING_NONE; diff --git a/src/trainer_hill.c b/src/trainer_hill.c index 528ee18a48..a74270ec77 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -685,7 +685,8 @@ static u16 GetMetatileForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floo void GenerateTrainerHillFloorLayout(u16 *mapArg) { s32 y, x; - u16 *src, *dst; + const u16 *src; + u16 *dst; u8 mapId = GetCurrentTrainerHillMapId(); if (mapId == TRAINER_HILL_ENTRANCE) From 7ce68994ec3f05c305f1800c490b429b3923d4f4 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 12 Mar 2023 02:32:09 -0300 Subject: [PATCH 029/131] Made Mega Evolution properly use TryBattleFormChange --- data/battle_scripts_1.s | 3 +- src/battle_script_commands.c | 20 ++---- src/battle_util.c | 63 +++++++++++------- src/data/pokemon/form_change_tables.h | 94 --------------------------- src/pokemon.c | 1 - 5 files changed, 45 insertions(+), 136 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8bba932865..e8b45cc3d3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7833,10 +7833,9 @@ BattleScript_MegaEvolutionAfeterString: waitmessage B_WAIT_TIME_LONG setbyte gIsCriticalHit, 0 handlemegaevo BS_ATTACKER, 0 - handlemegaevo BS_ATTACKER, 1 playanimation BS_ATTACKER, B_ANIM_MEGA_EVOLUTION waitanimation - handlemegaevo BS_ATTACKER, 2 + handlemegaevo BS_ATTACKER, 1 printstring STRINGID_MEGAEVOEVOLVED waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 360cef1252..4867722574 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8679,37 +8679,27 @@ static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega) // Change species. if (caseId == 0) { - u16 newSpecies; if (isMega) { - //Checks regular Mega Evolution - newSpecies = GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM); - //Checks Wish Mega Evolution - if (newSpecies == SPECIES_NONE) - newSpecies = GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE); + if (!TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM)) + TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE); } else - newSpecies = GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_PRIMAL_REVERSION); + TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_PRIMAL_REVERSION); - gBattleMons[battlerId].species = newSpecies; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battlerId].species); BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[battlerId]], sizeof(gBattleMons[battlerId].species), &gBattleMons[battlerId].species); MarkBattlerForControllerExec(battlerId); } - // Change stats. - else if (caseId == 1) - { - RecalcBattlerStats(battlerId, mon); - if (isMega) - gBattleStruct->mega.alreadyEvolved[position] = TRUE; - } // Update healthbox and elevation and play cry. else { UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], mon, HEALTHBOX_ALL); if (side == B_SIDE_OPPONENT) SetBattlerShadowSpriteCallback(battlerId, gBattleMons[battlerId].species); + if (isMega) + gBattleStruct->mega.alreadyEvolved[position] = TRUE; } } diff --git a/src/battle_util.c b/src/battle_util.c index 9a8954fd5f..aba70e377f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10071,11 +10071,17 @@ bool32 CanMegaEvolve(u8 battlerId) bool32 IsBattlerMegaEvolved(u8 battlerId) { + // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; return (gSpeciesInfo[gBattleMons[battlerId].species].flags & SPECIES_FLAG_MEGA_EVOLUTION); } bool32 IsBattlerPrimalReverted(u8 battlerId) { + // While Transform does copy stats and visuals, it shouldn't be counted as true Primal Revesion. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; return (gSpeciesInfo[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION); } @@ -10145,6 +10151,18 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) return targetSpecies; } +bool32 CanBattlerFormChange(u8 battlerId, u16 method) +{ + // Can't change form if transformed. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; + // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle. + if (IsBattlerMegaEvolved(battlerId) + && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + return TRUE; + return DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method); +} + bool32 TryBattleFormChange(u8 battlerId, u16 method) { u8 monId = gBattlerPartyIndexes[battlerId]; @@ -10152,14 +10170,12 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; u16 targetSpecies; - // Can't change form if transformed. - if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) - return FALSE; - - if (!DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method)) + if (!CanBattlerFormChange(battlerId, method)) return FALSE; targetSpecies = GetBattleFormChangeTargetSpecies(battlerId, method); + if (targetSpecies == SPECIES_NONE) + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); if (targetSpecies != SPECIES_NONE) { // Saves the original species on the first form change for the player. @@ -10172,27 +10188,26 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) RecalcBattlerStats(battlerId, &party[monId]); return TRUE; } - - targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies != SPECIES_NONE) + else if (gBattleStruct->changedSpecies[monId] != SPECIES_NONE) { - // Saves the original species on the first form change for the player. - if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE) - gBattleStruct->changedSpecies[monId] = targetSpecies; + bool8 restoreSpecies = FALSE; - TryToSetBattleFormChangeMoves(&party[monId], method); - SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); - gBattleMons[battlerId].species = targetSpecies; - RecalcBattlerStats(battlerId, &party[monId]); - return TRUE; - } - else if ((method == FORM_CHANGE_END_BATTLE || method == FORM_CHANGE_FAINT) - && gBattleStruct->changedSpecies[monId] != SPECIES_NONE) - { - TryToSetBattleFormChangeMoves(&party[monId], method); - SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); - RecalcBattlerStats(battlerId, &party[monId]); - return TRUE; + // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle, so no need to add it to the form change tables. + if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + // Unlike Megas, Primal Reversion isn't canceled on fainting. + else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + if (restoreSpecies) + { + // Reverts the original species + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; + } } return FALSE; diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 5050b488b7..9787d2a9bf 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,287 +1,207 @@ static const struct FormChange sVenusaurFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, - {FORM_CHANGE_FAINT, SPECIES_VENUSAUR}, - {FORM_CHANGE_END_BATTLE, SPECIES_VENUSAUR}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sCharizardFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_X, ITEM_CHARIZARDITE_X}, {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_Y, ITEM_CHARIZARDITE_Y}, - {FORM_CHANGE_FAINT, SPECIES_CHARIZARD}, - {FORM_CHANGE_END_BATTLE, SPECIES_CHARIZARD}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBlastoiseFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, - {FORM_CHANGE_FAINT, SPECIES_BLASTOISE}, - {FORM_CHANGE_END_BATTLE, SPECIES_BLASTOISE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBeedrillFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, - {FORM_CHANGE_FAINT, SPECIES_BEEDRILL}, - {FORM_CHANGE_END_BATTLE, SPECIES_BEEDRILL}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sPidgeotFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, - {FORM_CHANGE_FAINT, SPECIES_PIDGEOT}, - {FORM_CHANGE_END_BATTLE, SPECIES_PIDGEOT}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAlakazamFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, - {FORM_CHANGE_FAINT, SPECIES_ALAKAZAM}, - {FORM_CHANGE_END_BATTLE, SPECIES_ALAKAZAM}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSlowbroFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, - {FORM_CHANGE_FAINT, SPECIES_SLOWBRO}, - {FORM_CHANGE_END_BATTLE, SPECIES_SLOWBRO}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGengarFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, - {FORM_CHANGE_FAINT, SPECIES_GENGAR}, - {FORM_CHANGE_END_BATTLE, SPECIES_GENGAR}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKangaskhanFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, - {FORM_CHANGE_FAINT, SPECIES_KANGASKHAN}, - {FORM_CHANGE_END_BATTLE, SPECIES_KANGASKHAN}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sPinsirFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, - {FORM_CHANGE_FAINT, SPECIES_PINSIR}, - {FORM_CHANGE_END_BATTLE, SPECIES_PINSIR}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGyaradosFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, - {FORM_CHANGE_FAINT, SPECIES_GYARADOS}, - {FORM_CHANGE_END_BATTLE, SPECIES_GYARADOS}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAerodactylFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, - {FORM_CHANGE_FAINT, SPECIES_AERODACTYL}, - {FORM_CHANGE_END_BATTLE, SPECIES_AERODACTYL}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMewtwoFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_X, ITEM_MEWTWONITE_X}, {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_Y, ITEM_MEWTWONITE_Y}, - {FORM_CHANGE_FAINT, SPECIES_MEWTWO}, - {FORM_CHANGE_END_BATTLE, SPECIES_MEWTWO}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAmpharosFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, - {FORM_CHANGE_FAINT, SPECIES_AMPHAROS}, - {FORM_CHANGE_END_BATTLE, SPECIES_AMPHAROS}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSteelixFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, - {FORM_CHANGE_FAINT, SPECIES_STEELIX}, - {FORM_CHANGE_END_BATTLE, SPECIES_STEELIX}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sScizorFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, - {FORM_CHANGE_FAINT, SPECIES_SCIZOR}, - {FORM_CHANGE_END_BATTLE, SPECIES_SCIZOR}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHeracrossFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, - {FORM_CHANGE_FAINT, SPECIES_HERACROSS}, - {FORM_CHANGE_END_BATTLE, SPECIES_HERACROSS}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHoundoomFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, - {FORM_CHANGE_FAINT, SPECIES_HOUNDOOM}, - {FORM_CHANGE_END_BATTLE, SPECIES_HOUNDOOM}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sTyranitarFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, - {FORM_CHANGE_FAINT, SPECIES_TYRANITAR}, - {FORM_CHANGE_END_BATTLE, SPECIES_TYRANITAR}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSceptileFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, - {FORM_CHANGE_FAINT, SPECIES_SCEPTILE}, - {FORM_CHANGE_END_BATTLE, SPECIES_SCEPTILE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBlazikenFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, - {FORM_CHANGE_FAINT, SPECIES_BLAZIKEN}, - {FORM_CHANGE_END_BATTLE, SPECIES_BLAZIKEN}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSwampertFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, - {FORM_CHANGE_FAINT, SPECIES_SWAMPERT}, - {FORM_CHANGE_END_BATTLE, SPECIES_SWAMPERT}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSableyeFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, - {FORM_CHANGE_FAINT, SPECIES_SABLEYE}, - {FORM_CHANGE_END_BATTLE, SPECIES_SABLEYE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSharpedoFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, - {FORM_CHANGE_FAINT, SPECIES_SHARPEDO}, - {FORM_CHANGE_END_BATTLE, SPECIES_SHARPEDO}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sManectricFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, - {FORM_CHANGE_FAINT, SPECIES_MANECTRIC}, - {FORM_CHANGE_END_BATTLE, SPECIES_MANECTRIC}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sCameruptFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, - {FORM_CHANGE_FAINT, SPECIES_CAMERUPT}, - {FORM_CHANGE_END_BATTLE, SPECIES_CAMERUPT}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGlalieFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, - {FORM_CHANGE_FAINT, SPECIES_GLALIE}, - {FORM_CHANGE_END_BATTLE, SPECIES_GLALIE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMawileFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, - {FORM_CHANGE_FAINT, SPECIES_MAWILE}, - {FORM_CHANGE_END_BATTLE, SPECIES_MAWILE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMedichamFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, - {FORM_CHANGE_FAINT, SPECIES_MEDICHAM}, - {FORM_CHANGE_END_BATTLE, SPECIES_MEDICHAM}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAltariaFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, - {FORM_CHANGE_FAINT, SPECIES_ALTARIA}, - {FORM_CHANGE_END_BATTLE, SPECIES_ALTARIA}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAbsolFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, - {FORM_CHANGE_FAINT, SPECIES_ABSOL}, - {FORM_CHANGE_END_BATTLE, SPECIES_ABSOL}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sBanetteFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, - {FORM_CHANGE_FAINT, SPECIES_BANETTE}, - {FORM_CHANGE_END_BATTLE, SPECIES_BANETTE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAggronFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, - {FORM_CHANGE_FAINT, SPECIES_AGGRON}, - {FORM_CHANGE_END_BATTLE, SPECIES_AGGRON}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGardevoirFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, - {FORM_CHANGE_FAINT, SPECIES_GARDEVOIR}, - {FORM_CHANGE_END_BATTLE, SPECIES_GARDEVOIR}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSalamenceFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, - {FORM_CHANGE_FAINT, SPECIES_SALAMENCE}, - {FORM_CHANGE_END_BATTLE, SPECIES_SALAMENCE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sMetagrossFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, - {FORM_CHANGE_FAINT, SPECIES_METAGROSS}, - {FORM_CHANGE_END_BATTLE, SPECIES_METAGROSS}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLatiasFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, - {FORM_CHANGE_FAINT, SPECIES_LATIAS}, - {FORM_CHANGE_END_BATTLE, SPECIES_LATIAS}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLatiosFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, - {FORM_CHANGE_FAINT, SPECIES_LATIOS}, - {FORM_CHANGE_END_BATTLE, SPECIES_LATIOS}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKyogreFormChangeTable[] = { {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, - {FORM_CHANGE_END_BATTLE, SPECIES_KYOGRE}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGroudonFormChangeTable[] = { {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, - {FORM_CHANGE_END_BATTLE, SPECIES_GROUDON}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sRayquazaFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, - {FORM_CHANGE_FAINT, SPECIES_RAYQUAZA}, - {FORM_CHANGE_END_BATTLE, SPECIES_RAYQUAZA}, {FORM_CHANGE_TERMINATOR}, }; @@ -300,36 +220,26 @@ static const struct FormChange sBurmyFormChangeTable[] = { static const struct FormChange sLopunnyFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, - {FORM_CHANGE_FAINT, SPECIES_LOPUNNY}, - {FORM_CHANGE_END_BATTLE, SPECIES_LOPUNNY}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGarchompFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, - {FORM_CHANGE_FAINT, SPECIES_GARCHOMP}, - {FORM_CHANGE_END_BATTLE, SPECIES_GARCHOMP}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLucarioFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, - {FORM_CHANGE_FAINT, SPECIES_LUCARIO}, - {FORM_CHANGE_END_BATTLE, SPECIES_LUCARIO}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAbomasnowFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, - {FORM_CHANGE_FAINT, SPECIES_ABOMASNOW}, - {FORM_CHANGE_END_BATTLE, SPECIES_ABOMASNOW}, {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGalladeFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, - {FORM_CHANGE_FAINT, SPECIES_GALLADE}, - {FORM_CHANGE_END_BATTLE, SPECIES_GALLADE}, {FORM_CHANGE_TERMINATOR}, }; @@ -388,8 +298,6 @@ static const struct FormChange sArceusFormChangeTable[] = { #if P_GEN_5_POKEMON == TRUE static const struct FormChange sAudinoFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, - {FORM_CHANGE_FAINT, SPECIES_AUDINO}, - {FORM_CHANGE_END_BATTLE, SPECIES_AUDINO}, {FORM_CHANGE_TERMINATOR}, }; @@ -478,8 +386,6 @@ static const struct FormChange sZygardePowerConstructFormChangeTable[] = { static const struct FormChange sDiancieFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, - {FORM_CHANGE_FAINT, SPECIES_DIANCIE}, - {FORM_CHANGE_END_BATTLE, SPECIES_DIANCIE}, {FORM_CHANGE_TERMINATOR}, }; diff --git a/src/pokemon.c b/src/pokemon.c index f01e72dcdb..e11014120a 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8659,7 +8659,6 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gSpeciesInfo[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } -// Returns species that it transformed into. If it didn't, returns SPECIES_NONE. bool32 TryFormChange(u32 monId, u32 side, u16 method) { struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; From c46e70ca8215831038c8312baf7caf3a29f323dd Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 12 Mar 2023 02:38:27 -0300 Subject: [PATCH 030/131] Forgot about Primal Reversion --- src/battle_util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index aba70e377f..f4aa344b5d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10157,8 +10157,9 @@ bool32 CanBattlerFormChange(u8 battlerId, u16 method) if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) return FALSE; // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle. - if (IsBattlerMegaEvolved(battlerId) - && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + return TRUE; + else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) return TRUE; return DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method); } From a101476d5187243b1d9c7a22d44d9fc60bbd7481 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 12 Mar 2023 17:01:53 -0300 Subject: [PATCH 031/131] Hunger Switch test --- test/ability_hunger_switch.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/ability_hunger_switch.c diff --git a/test/ability_hunger_switch.c b/test/ability_hunger_switch.c new file mode 100644 index 0000000000..8ae3139299 --- /dev/null +++ b/test/ability_hunger_switch.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the turn") +{ + u16 species; + PARAMETRIZE { species = SPECIES_MORPEKO; } + PARAMETRIZE { species = SPECIES_MORPEKO_HANGRY; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(species) { Moves(MOVE_CELEBRATE); Speed(2); }; + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); }; + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("Morpeko used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + if (species == SPECIES_MORPEKO) + EXPECT_EQ(player->species, SPECIES_MORPEKO_HANGRY); + else + EXPECT_EQ(player->species, SPECIES_MORPEKO); + } +} From 0c380862d61a9c4eccd9ed4915e12db6e7ca4310 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 13 Mar 2023 15:37:46 -0400 Subject: [PATCH 032/131] Document the trendy saying word group --- data/scripts/mauville_man.inc | 10 ++-- data/specials.inc | 4 +- include/constants/easy_chat.h | 2 +- include/constants/flags.h | 2 +- include/easy_chat.h | 4 +- include/global.h | 6 +-- src/easy_chat.c | 97 +++++++++++++++++++++-------------- src/mauville_old_man.c | 19 +++---- src/mystery_event_script.c | 2 +- 9 files changed, 83 insertions(+), 63 deletions(-) diff --git a/data/scripts/mauville_man.inc b/data/scripts/mauville_man.inc index eda3505bf4..a336360436 100644 --- a/data/scripts/mauville_man.inc +++ b/data/scripts/mauville_man.inc @@ -64,9 +64,9 @@ MauvilleCity_PokemonCenter_1F_EventScript_DeclineWritingLyrics:: MauvilleCity_PokemonCenter_1F_EventScript_Hipster:: lock faceplayer - setflag FLAG_SYS_HIPSTER_MEET + setflag FLAG_UNLOCKED_TRENDY_SAYINGS msgbox MauvilleCity_PokemonCenter_1F_Text_TeachWhatsHipAndHappening, MSGBOX_DEFAULT - special GetHipsterSpokenFlag + special HasHipsterTaughtWord goto_if_eq VAR_RESULT, FALSE, MauvilleCity_PokemonCenter_1F_EventScript_TryTeachWord msgbox MauvilleCity_PokemonCenter_1F_Text_IAlreadyTaughtYou, MSGBOX_DEFAULT release @@ -80,8 +80,8 @@ MauvilleCity_PokemonCenter_1F_EventScript_TryTeachWord:: end MauvilleCity_PokemonCenter_1F_EventScript_TeachWord:: - msgbox MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfPhrase, MSGBOX_DEFAULT - special SetHipsterSpokenFlag + msgbox MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfWord, MSGBOX_DEFAULT + special SetHipsterTaughtWord release end @@ -969,7 +969,7 @@ MauvilleCity_PokemonCenter_1F_Text_IveGotNothingNewToTeach: .string "what's hip and happening.\p" .string "I've got nothing new to teach you!$" -MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfPhrase: +MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfWord: .string "Hey, have you heard about\n" .string "“{STR_VAR_1}”?\p" .string "What's it mean? Well…\n" diff --git a/data/specials.inc b/data/specials.inc index a0dbde8683..52b539a805 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -111,8 +111,8 @@ gSpecials:: def_special Script_GetCurrentMauvilleMan def_special HasBardSongBeenChanged def_special SaveBardSongLyrics - def_special GetHipsterSpokenFlag - def_special SetHipsterSpokenFlag + def_special HasHipsterTaughtWord + def_special SetHipsterTaughtWord def_special HipsterTryTeachWord def_special PlayBardSong def_special SetMauvilleOldManObjEventGfx diff --git a/include/constants/easy_chat.h b/include/constants/easy_chat.h index b5875b8814..b1f38941fc 100644 --- a/include/constants/easy_chat.h +++ b/include/constants/easy_chat.h @@ -1095,7 +1095,7 @@ #define EC_WORD_OLD ((EC_GROUP_TRENDY_SAYING << EC_MASK_BITS) | 30) #define EC_WORD_YOUNG ((EC_GROUP_TRENDY_SAYING << EC_MASK_BITS) | 31) #define EC_WORD_UGLY ((EC_GROUP_TRENDY_SAYING << EC_MASK_BITS) | 32) -#define NUM_ADDITIONAL_PHRASES 33 +#define NUM_TRENDY_SAYINGS 33 // Special Berry Masters Wife phrases #define NOT_SPECIAL_PHRASE 0 diff --git a/include/constants/flags.h b/include/constants/flags.h index 99a8377a75..377f18107d 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1348,7 +1348,7 @@ #define FLAG_UNUSED_0x863 (SYSTEM_FLAGS + 0x3) // Unused Flag #define FLAG_SYS_GAME_CLEAR (SYSTEM_FLAGS + 0x4) #define FLAG_SYS_CHAT_USED (SYSTEM_FLAGS + 0x5) -#define FLAG_SYS_HIPSTER_MEET (SYSTEM_FLAGS + 0x6) +#define FLAG_UNLOCKED_TRENDY_SAYINGS (SYSTEM_FLAGS + 0x6) // Badges #define FLAG_BADGE01_GET (SYSTEM_FLAGS + 0x7) diff --git a/include/easy_chat.h b/include/easy_chat.h index c9ef4428f7..4bcc7389cd 100644 --- a/include/easy_chat.h +++ b/include/easy_chat.h @@ -128,11 +128,11 @@ void InitializeEasyChatWordArray(u16 *words, u16 length); u8 *ConvertEasyChatWordsToString(u8 *dest, const u16 *src, u16 columns, u16 rows); bool8 IsBardWordInvalid(u16 word); u16 GetRandomEasyChatWordFromGroup(u16 group); -u16 GetNewHipsterPhraseToTeach(void); +u16 UnlockRandomTrendySaying(void); u16 EasyChat_GetNumWordsInGroup(u8); u16 GetRandomEasyChatWordFromUnlockedGroup(u16); void DoEasyChatScreen(u8 type, u16 *words, MainCallback callback, u8 displayedPersonType); void InitQuestionnaireWords(void); -void UnlockAdditionalPhrase(u8 additionalPhraseId); +void UnlockTrendySaying(u8 wordIndex); #endif // GUARD_EASYCHAT_H diff --git a/include/global.h b/include/global.h index e0ff9f0c23..9396a95f7a 100644 --- a/include/global.h +++ b/include/global.h @@ -133,7 +133,7 @@ // values that don't appear in the Pokedex. NATIONAL_DEX_COUNT does not include these values. #define NUM_DEX_FLAG_BYTES ROUND_BITS_TO_BYTES(NUM_SPECIES) #define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT) -#define NUM_ADDITIONAL_PHRASE_BYTES ROUND_BITS_TO_BYTES(NUM_ADDITIONAL_PHRASES) +#define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS) // This produces an error at compile-time if expr is zero. // It looks like file.c:line: size of array `id' is negative @@ -673,7 +673,7 @@ struct MauvilleManGiddy struct MauvilleManHipster { u8 id; - bool8 alreadySpoken; + bool8 taughtWord; u8 language; }; @@ -1031,7 +1031,7 @@ struct SaveBlock1 /*0x2BC8*/ u16 easyChatBattleWon[EASY_CHAT_BATTLE_WORDS_COUNT]; /*0x2BD4*/ u16 easyChatBattleLost[EASY_CHAT_BATTLE_WORDS_COUNT]; /*0x2BE0*/ struct Mail mail[MAIL_COUNT]; - /*0x2E20*/ u8 additionalPhrases[NUM_ADDITIONAL_PHRASE_BYTES]; // bitfield for 33 additional phrases in easy chat system + /*0x2E20*/ u8 unlockedTrendySayings[NUM_TRENDY_SAYING_BYTES]; // Bitfield for unlockable Easy Chat words in EC_GROUP_TRENDY_SAYING /*0x2E25*/ //u8 padding5[3]; /*0x2E28*/ OldMan oldMan; /*0x2e64*/ struct DewfordTrend dewfordTrends[SAVED_TRENDS_COUNT]; diff --git a/src/easy_chat.c b/src/easy_chat.c index d08ea4b33d..35ba633cf4 100644 --- a/src/easy_chat.c +++ b/src/easy_chat.c @@ -5109,7 +5109,7 @@ static bool8 IsEasyChatGroupUnlocked(u8 groupId) switch (groupId) { case EC_GROUP_TRENDY_SAYING: - return FlagGet(FLAG_SYS_HIPSTER_MEET); + return FlagGet(FLAG_UNLOCKED_TRENDY_SAYINGS); case EC_GROUP_EVENTS: case EC_GROUP_MOVE_1: case EC_GROUP_MOVE_2: @@ -5425,80 +5425,99 @@ void BufferDeepLinkPhrase(void) CopyEasyChatWord(gStringVar2, easyChatWord); } -static bool8 IsAdditionalPhraseUnlocked(u8 additionalPhraseId) +/* + ### Trendy Sayings + + Not to be confused with Dewford Town's "trendy phrase". + + This is a group of easy chat words (EC_GROUP_TRENDY_SAYING) that are normally inaccessible. + They can be unlocked either through Mystery Event (where they're referred to as "rare" words) + or from the "Hipster" variety of the Mauville Old Man. The Hipster can unlock one word each + time he is received via record mixing (and once if he is the player's default Old Man). + + Which words have been unlocked is saved in the unlockedTrendySayings bitfield in SaveBlock1 + + Unlocked trendy saying words are only accessible if the flag FLAG_UNLOCKED_TRENDY_SAYINGS is set. + It's set any time the player talks to the Hipster, but is not apparently set by Mystery Event, + meaning trendy saying words unlocked via Mystery Event may not be available until the player has + talked to the Hipster. +*/ +static bool8 IsTrendySayingUnlocked(u8 wordIndex) { - int byteOffset = additionalPhraseId / 8; - int shift = additionalPhraseId % 8; - return (gSaveBlock1Ptr->additionalPhrases[byteOffset] >> shift) & 1; + int byteOffset = wordIndex / 8; + int shift = wordIndex % 8; + return (gSaveBlock1Ptr->unlockedTrendySayings[byteOffset] >> shift) & 1; } -void UnlockAdditionalPhrase(u8 additionalPhraseId) +void UnlockTrendySaying(u8 wordIndex) { - if (additionalPhraseId < NUM_ADDITIONAL_PHRASES) + if (wordIndex < NUM_TRENDY_SAYINGS) { - int byteOffset = additionalPhraseId / 8; - int shift = additionalPhraseId % 8; - gSaveBlock1Ptr->additionalPhrases[byteOffset] |= 1 << shift; + int byteOffset = wordIndex / 8; + int shift = wordIndex % 8; + gSaveBlock1Ptr->unlockedTrendySayings[byteOffset] |= 1 << shift; } } -static u8 GetNumAdditionalPhrasesUnlocked(void) +static u8 GetNumTrendySayingsUnlocked(void) { u8 i; - u8 numAdditionalPhrasesUnlocked; + u8 numUnlocked; - for (i = 0, numAdditionalPhrasesUnlocked = 0; i < NUM_ADDITIONAL_PHRASES; i++) + for (i = 0, numUnlocked = 0; i < NUM_TRENDY_SAYINGS; i++) { - if (IsAdditionalPhraseUnlocked(i)) - numAdditionalPhrasesUnlocked++; + if (IsTrendySayingUnlocked(i)) + numUnlocked++; } - return numAdditionalPhrasesUnlocked; + return numUnlocked; } -u16 GetNewHipsterPhraseToTeach(void) +u16 UnlockRandomTrendySaying(void) { u16 i; - u16 additionalPhraseId; - u8 numAdditionalPhrasesUnlocked = GetNumAdditionalPhrasesUnlocked(); - if (numAdditionalPhrasesUnlocked == NUM_ADDITIONAL_PHRASES) + u16 numToSkip; + u8 numUnlocked = GetNumTrendySayingsUnlocked(); + if (numUnlocked == NUM_TRENDY_SAYINGS) return EC_EMPTY_WORD; - additionalPhraseId = Random() % (NUM_ADDITIONAL_PHRASES - numAdditionalPhrasesUnlocked); - for (i = 0; i < NUM_ADDITIONAL_PHRASES; i++) + numToSkip = Random() % (NUM_TRENDY_SAYINGS - numUnlocked); + for (i = 0; i < NUM_TRENDY_SAYINGS; i++) { - if (!IsAdditionalPhraseUnlocked(i)) + if (!IsTrendySayingUnlocked(i)) { - if (additionalPhraseId) + if (numToSkip) { - additionalPhraseId--; + // Skip the first n locked words, as determined by the Random call above. + numToSkip--; } else { - UnlockAdditionalPhrase(i); + UnlockTrendySaying(i); return EC_WORD(EC_GROUP_TRENDY_SAYING, i); } } } + // Would only be reached if there are no new words to teach, which is handled at the start. return EC_EMPTY_WORD; } // Unused -u16 GetRandomTaughtHipsterPhrase(void) +static u16 GetRandomUnlockedTrendySaying(void) { u16 i; - u16 additionalPhraseId = GetNumAdditionalPhrasesUnlocked(); - if (additionalPhraseId == 0) + u16 n = GetNumTrendySayingsUnlocked(); + if (n == 0) return EC_EMPTY_WORD; - additionalPhraseId = Random() % additionalPhraseId; - for (i = 0; i < NUM_ADDITIONAL_PHRASES; i++) + n = Random() % n; + for (i = 0; i < NUM_TRENDY_SAYINGS; i++) { - if (IsAdditionalPhraseUnlocked(i)) + if (IsTrendySayingUnlocked(i)) { - if (additionalPhraseId) - additionalPhraseId--; + if (n) + n--; else return EC_WORD(EC_GROUP_TRENDY_SAYING, i); } @@ -5569,10 +5588,10 @@ void InitEasyChatPhrases(void) // Mauville old man data is corrupted, which is initialized directly after // this function is called when starting a new game. for (i = 0; i < 64; i++) - gSaveBlock1Ptr->additionalPhrases[i] = 0; + gSaveBlock1Ptr->unlockedTrendySayings[i] = 0; #else - for (i = 0; i < ARRAY_COUNT(gSaveBlock1Ptr->additionalPhrases); i++) - gSaveBlock1Ptr->additionalPhrases[i] = 0; + for (i = 0; i < ARRAY_COUNT(gSaveBlock1Ptr->unlockedTrendySayings); i++) + gSaveBlock1Ptr->unlockedTrendySayings[i] = 0; #endif } @@ -5611,7 +5630,7 @@ static void SetUnlockedEasyChatGroups(void) sWordData->unlockedGroupIds[sWordData->numUnlockedGroups++] = EC_GROUP_MOVE_2; } - if (FlagGet(FLAG_SYS_HIPSTER_MEET)) + if (FlagGet(FLAG_UNLOCKED_TRENDY_SAYINGS)) sWordData->unlockedGroupIds[sWordData->numUnlockedGroups++] = EC_GROUP_TRENDY_SAYING; if (IsNationalPokedexEnabled()) @@ -5800,7 +5819,7 @@ static bool8 IsEasyChatIndexAndGroupUnlocked(u16 wordIndex, u8 groupId) case EC_GROUP_MOVE_2: return TRUE; case EC_GROUP_TRENDY_SAYING: - return IsAdditionalPhraseUnlocked(wordIndex); + return IsTrendySayingUnlocked(wordIndex); default: return gEasyChatGroups[groupId].wordData.words[wordIndex].enabled; } diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c index 689dcf6a16..6075bd5d95 100644 --- a/src/mauville_old_man.c +++ b/src/mauville_old_man.c @@ -88,7 +88,7 @@ static void SetupHipster(void) struct MauvilleManHipster *hipster = &gSaveBlock1Ptr->oldMan.hipster; hipster->id = MAUVILLE_MAN_HIPSTER; - hipster->alreadySpoken = FALSE; + hipster->taughtWord = FALSE; hipster->language = gGameLanguage; } @@ -225,27 +225,28 @@ void PlayBardSong(void) ScriptContext_Stop(); } -void GetHipsterSpokenFlag(void) +void HasHipsterTaughtWord(void) { - gSpecialVar_Result = (&gSaveBlock1Ptr->oldMan.hipster)->alreadySpoken; + gSpecialVar_Result = (&gSaveBlock1Ptr->oldMan.hipster)->taughtWord; } -void SetHipsterSpokenFlag(void) +void SetHipsterTaughtWord(void) { - (&gSaveBlock1Ptr->oldMan.hipster)->alreadySpoken = TRUE; + (&gSaveBlock1Ptr->oldMan.hipster)->taughtWord = TRUE; } void HipsterTryTeachWord(void) { - u16 phrase = GetNewHipsterPhraseToTeach(); + u16 word = UnlockRandomTrendySaying(); - if (phrase == EC_EMPTY_WORD) + if (word == EC_EMPTY_WORD) { + // All words already unlocked gSpecialVar_Result = FALSE; } else { - CopyEasyChatWord(gStringVar1, phrase); + CopyEasyChatWord(gStringVar1, word); gSpecialVar_Result = TRUE; } } @@ -369,7 +370,7 @@ static void ResetBardFlag(void) static void ResetHipsterFlag(void) { - (&gSaveBlock1Ptr->oldMan.hipster)->alreadySpoken = FALSE; + (&gSaveBlock1Ptr->oldMan.hipster)->taughtWord = FALSE; } static void ResetTraderFlag(void) diff --git a/src/mystery_event_script.c b/src/mystery_event_script.c index 124ababa45..b146bbab39 100644 --- a/src/mystery_event_script.c +++ b/src/mystery_event_script.c @@ -293,7 +293,7 @@ bool8 MEScrCmd_givenationaldex(struct ScriptContext *ctx) bool8 MEScrCmd_addrareword(struct ScriptContext *ctx) { - UnlockAdditionalPhrase(ScriptReadByte(ctx)); + UnlockTrendySaying(ScriptReadByte(ctx)); StringExpandPlaceholders(gStringVar4, gText_MysteryEventRareWord); ctx->mStatus = MEVENT_STATUS_SUCCESS; return FALSE; From 0dfb60f2e462f2980cab20697a46db8fa3102c47 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 14 Mar 2023 11:07:26 -0300 Subject: [PATCH 033/131] Removed uneeded parameters --- test/ability_hunger_switch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ability_hunger_switch.c b/test/ability_hunger_switch.c index 8ae3139299..9250ae85a5 100644 --- a/test/ability_hunger_switch.c +++ b/test/ability_hunger_switch.c @@ -8,8 +8,8 @@ SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the tur PARAMETRIZE { species = SPECIES_MORPEKO_HANGRY; } GIVEN { ASSUME(P_GEN_8_POKEMON == TRUE); - PLAYER(species) { Moves(MOVE_CELEBRATE); Speed(2); }; - OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(1); }; + PLAYER(species) { Speed(2); }; + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }; } WHEN { TURN { MOVE(player, MOVE_CELEBRATE); } } SCENE { From bef5d98b88cef4138fe83adad0b572f0893f6661 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 18 Mar 2023 09:47:54 -0300 Subject: [PATCH 034/131] =?UTF-8?q?Fixed=20Pok=C3=A9mon=20fainting=20in=20?= =?UTF-8?q?the=20Overworld=20that=20don't=20have=20that=20specific=20form?= =?UTF-8?q?=20change=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pokemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pokemon.c b/src/pokemon.c index e11014120a..62e1891ab6 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8670,7 +8670,7 @@ bool32 TryFormChange(u32 monId, u32 side, u16 method) targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies == SPECIES_NONE) + if (targetSpecies == SPECIES_NONE && gBattleStruct != NULL) targetSpecies = gBattleStruct->changedSpecies[monId]; if (targetSpecies != SPECIES_NONE) From 168ed1cc55468863107edda6af375284a7cd133a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 22 Mar 2023 07:33:13 -0300 Subject: [PATCH 035/131] Xerneas/Zacian/Zamazenta form change tests --- test/form_change.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 test/form_change.c diff --git a/test/form_change.c b/test/form_change.c new file mode 100644 index 0000000000..8d761bb12d --- /dev/null +++ b/test/form_change.c @@ -0,0 +1,81 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Xerneas changes into Active Form upon battle start") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_XERNEAS); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + EXPECT_EQ(player->species, SPECIES_XERNEAS_ACTIVE); + } +} + +SINGLE_BATTLE_TEST("Zacian changes into its Crowned Form when holding the Rusted Sword upon battle start") +{ + u16 item; + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_RUSTED_SWORD; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZACIAN) { Item(item); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + if (item == ITEM_NONE) + EXPECT_EQ(player->species, SPECIES_ZACIAN); + else + EXPECT_EQ(player->species, SPECIES_ZACIAN_CROWNED_SWORD); + } +} + +SINGLE_BATTLE_TEST("Zacian's Iron Head becomes Behemoth Blade upon form change") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZACIAN) { Item(ITEM_RUSTED_SWORD); Moves(MOVE_IRON_HEAD, MOVE_CELEBRATE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + ASSUME(player->species == SPECIES_ZACIAN_CROWNED_SWORD); // Assumes form change worked. + EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BLADE); + } +} + +SINGLE_BATTLE_TEST("Zamazenta changes into its Crowned Form when holding the Rusted Shield upon battle start") +{ + u16 item; + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_RUSTED_SHIELD; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZAMAZENTA) { Item(item); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + if (item == ITEM_NONE) + EXPECT_EQ(player->species, SPECIES_ZAMAZENTA); + else + EXPECT_EQ(player->species, SPECIES_ZAMAZENTA_CROWNED_SHIELD); + } +} + +SINGLE_BATTLE_TEST("Zamazenta's Iron Head becomes Behemoth Bash upon form change") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZAMAZENTA) { Item(ITEM_RUSTED_SHIELD); Moves(MOVE_IRON_HEAD, MOVE_CELEBRATE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + ASSUME(player->species == SPECIES_ZAMAZENTA_CROWNED_SHIELD); // Assumes form change worked. + EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BASH); + } +} From 492422b6bd268178aa687ca017fe44d67a399546 Mon Sep 17 00:00:00 2001 From: Zunawe Date: Thu, 23 Mar 2023 21:47:26 -0700 Subject: [PATCH 036/131] Fix scanner item flag name --- data/maps/AbandonedShip_CaptainsOffice/scripts.inc | 2 +- data/maps/AbandonedShip_HiddenFloorRooms/map.json | 2 +- include/constants/flags.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/maps/AbandonedShip_CaptainsOffice/scripts.inc b/data/maps/AbandonedShip_CaptainsOffice/scripts.inc index 7c59fec967..78fdc6434a 100644 --- a/data/maps/AbandonedShip_CaptainsOffice/scripts.inc +++ b/data/maps/AbandonedShip_CaptainsOffice/scripts.inc @@ -7,7 +7,7 @@ AbandonedShip_CaptainsOffice_EventScript_CaptSternAide:: goto_if_set FLAG_EXCHANGED_SCANNER, AbandonedShip_CaptainsOffice_EventScript_ThisIsSSCactus checkitem ITEM_SCANNER goto_if_eq VAR_RESULT, TRUE, AbandonedShip_CaptainsOffice_EventScript_CanYouDeliverScanner - goto_if_set FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_4_SCANNER, AbandonedShip_CaptainsOffice_EventScript_ThisIsSSCactus + goto_if_set FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_2_SCANNER, AbandonedShip_CaptainsOffice_EventScript_ThisIsSSCactus msgbox AbandonedShip_CaptainsOffice_Text_NoSuccessFindingScanner, MSGBOX_DEFAULT release end diff --git a/data/maps/AbandonedShip_HiddenFloorRooms/map.json b/data/maps/AbandonedShip_HiddenFloorRooms/map.json index 9c480a1c92..e808250f47 100644 --- a/data/maps/AbandonedShip_HiddenFloorRooms/map.json +++ b/data/maps/AbandonedShip_HiddenFloorRooms/map.json @@ -38,7 +38,7 @@ "trainer_type": "TRAINER_TYPE_NONE", "trainer_sight_or_berry_tree_id": "0", "script": "AbandonedShip_HiddenFloorRooms_EventScript_ItemScanner", - "flag": "FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_4_SCANNER" + "flag": "FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_2_SCANNER" }, { "graphics_id": "OBJ_EVENT_GFX_ITEM_BALL", diff --git a/include/constants/flags.h b/include/constants/flags.h index 99a8377a75..ed5dd5c68b 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1123,7 +1123,7 @@ #define FLAG_ITEM_NEW_MAUVILLE_ULTRA_BALL 0x433 #define FLAG_ITEM_NEW_MAUVILLE_ESCAPE_ROPE 0x434 #define FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_6_LUXURY_BALL 0x435 -#define FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_4_SCANNER 0x436 +#define FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_2_SCANNER 0x436 #define FLAG_ITEM_SCORCHED_SLAB_TM11 0x437 #define FLAG_ITEM_METEOR_FALLS_B1F_2R_TM02 0x438 #define FLAG_ITEM_SHOAL_CAVE_ENTRANCE_BIG_PEARL 0x439 From 52011804b96fb57f12f2871721ead16dc5ff8baa Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 24 Mar 2023 09:36:33 -0300 Subject: [PATCH 037/131] Level command now also sets experience to avoid losing level upon form changes --- test/test_runner_battle.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index ec7ba275c2..524525c132 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -933,9 +933,11 @@ void Ability_(u32 sourceLine, u32 ability) void Level_(u32 sourceLine, u32 level) { // TODO: Preserve any explicitly-set stats. + u32 species = GetMonData(DATA.currentMon, MON_DATA_SPECIES); INVALID_IF(!DATA.currentMon, "Level outside of PLAYER/OPPONENT"); INVALID_IF(level == 0 || level > MAX_LEVEL, "Illegal level: %d", level); SetMonData(DATA.currentMon, MON_DATA_LEVEL, &level); + SetMonData(DATA.currentMon, MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][level]); } void MaxHP_(u32 sourceLine, u32 maxHP) From 498f4a2c972941bd271e3487007eb6a919e15584 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 24 Mar 2023 10:04:38 -0300 Subject: [PATCH 038/131] Schooling and Zen Mode tests --- test/ability_schooling.c | 111 ++++++++++++++++++++++++++++++++++++++ test/ability_zen_mode.c | 93 ++++++++++++++++++++++++++++++++ test/test_runner_battle.c | 1 + 3 files changed, 205 insertions(+) create mode 100644 test/ability_schooling.c create mode 100644 test/ability_zen_mode.c diff --git a/test/ability_schooling.c b/test/ability_schooling.c new file mode 100644 index 0000000000..03a5303f0a --- /dev/null +++ b/test/ability_schooling.c @@ -0,0 +1,111 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is 25-percent or less at the end of the turn") +{ + u16 level; + PARAMETRIZE { level = 19; } + PARAMETRIZE { level = 20; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SUPER_FANG); } + } SCENE { + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Super Fang!"); + HP_BAR(player); + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + } THEN { + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is over 25-percent before the first turn") +{ + u16 level; + bool32 overQuarterHP; + PARAMETRIZE { level = 19; overQuarterHP = FALSE; } + PARAMETRIZE { level = 20; overQuarterHP = FALSE; } + PARAMETRIZE { level = 19; overQuarterHP = TRUE; } + PARAMETRIZE { level = 20; overQuarterHP = TRUE; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / (overQuarterHP ? 2 : 4)); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + if (level >= 20 && overQuarterHP) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + if (level >= 20 && overQuarterHP) + EXPECT_EQ(player->species, SPECIES_WISHIWASHI_SCHOOL); + else + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is healed above 25-percent") +{ + u16 level; + PARAMETRIZE { level = 19; } + PARAMETRIZE { level = 20; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 4); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_HEAL_PULSE); } + } SCENE { + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Heal Pulse!"); + HP_BAR(player); + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + } THEN { + if (level >= 20) + EXPECT_EQ(player->species, SPECIES_WISHIWASHI_SCHOOL); + else + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} diff --git a/test/ability_zen_mode.c b/test/ability_zen_mode.c new file mode 100644 index 0000000000..acf0ba291d --- /dev/null +++ b/test/ability_zen_mode.c @@ -0,0 +1,93 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less at the end of the turn") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP((GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2) + 1); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + ASSUME(player->hp <= player->maxHP / 2); + EXPECT_EQ(player->species, zenSpecies); + } +} + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less before the first turn") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_LE(player->hp, player->maxHP / 2); + EXPECT_EQ(player->species, zenSpecies); + } +} + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is healed above half") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_HEAL_PULSE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Heal Pulse!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + EXPECT_GT(player->hp, player->maxHP / 2); + EXPECT_EQ(player->species, standardSpecies); + } +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 524525c132..e96a6ea7b3 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -938,6 +938,7 @@ void Level_(u32 sourceLine, u32 level) INVALID_IF(level == 0 || level > MAX_LEVEL, "Illegal level: %d", level); SetMonData(DATA.currentMon, MON_DATA_LEVEL, &level); SetMonData(DATA.currentMon, MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][level]); + CalculateMonStats(DATA.currentMon); } void MaxHP_(u32 sourceLine, u32 maxHP) From fad11981a58ad3a5d2299533da0c29ec38a461e9 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 24 Mar 2023 11:03:34 -0300 Subject: [PATCH 039/131] Tests for form change on switch out and fainting --- test/ability_zen_mode.c | 10 +++++----- test/form_change.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/test/ability_zen_mode.c b/test/ability_zen_mode.c index acf0ba291d..f18f6d6595 100644 --- a/test/ability_zen_mode.c +++ b/test/ability_zen_mode.c @@ -20,11 +20,11 @@ SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less } WHEN { TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } } SCENE { - MESSAGE("Darmanitan used Celebrate!"); - MESSAGE("Foe Wobbuffet used Tackle!"); - HP_BAR(player); - ABILITY_POPUP(player, ABILITY_ZEN_MODE); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); } THEN { ASSUME(player->hp <= player->maxHP / 2); EXPECT_EQ(player->species, zenSpecies); diff --git a/test/form_change.c b/test/form_change.c index 8d761bb12d..74ba2b75f7 100644 --- a/test/form_change.c +++ b/test/form_change.c @@ -79,3 +79,41 @@ SINGLE_BATTLE_TEST("Zamazenta's Iron Head becomes Behemoth Bash upon form change EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BASH); } } + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon switching out") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + } SCENE { + ABILITY_POPUP(player, ABILITY_STANCE_CHANGE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Aegislash used Tackle!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_AEGISLASH); + } +} + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH) { HP(1); }; + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GUST); SEND_OUT(player, 1);} + } SCENE { + MESSAGE("Foe Wobbuffet used Gust!"); + MESSAGE("Aegislash fainted!"); + } THEN { + EXPECT_EQ(GetMonData(&PLAYER_PARTY[0], MON_DATA_SPECIES), SPECIES_AEGISLASH); + } +} From 2c3db747027aab2346b57058115c50814619562f Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 24 Mar 2023 10:36:10 -0400 Subject: [PATCH 040/131] fix base power calcs using battler addresses --- src/battle_util.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 7bf090a73b..8338d10459 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8602,7 +8602,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; break; case EFFECT_PURSUIT: - if (gActionsByTurnOrder[GetBattlerTurnOrderNum(gBattlerTarget)] == B_ACTION_SWITCH) + if (gActionsByTurnOrder[GetBattlerTurnOrderNum(battlerDef)] == B_ACTION_SWITCH) basePower *= 2; break; case EFFECT_NATURAL_GIFT: @@ -8736,12 +8736,12 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) #if B_HIDDEN_POWER_DMG < GEN_6 u8 powerBits; - 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); + powerBits = ((gBattleMons[battlerAtk].hpIV & 2) >> 1) + | ((gBattleMons[battlerAtk].attackIV & 2) << 0) + | ((gBattleMons[battlerAtk].defenseIV & 2) << 1) + | ((gBattleMons[battlerAtk].speedIV & 2) << 2) + | ((gBattleMons[battlerAtk].spAttackIV & 2) << 3) + | ((gBattleMons[battlerAtk].spDefenseIV & 2) << 4); basePower = (40 * powerBits) / 63 + 30; #endif @@ -8753,15 +8753,15 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_TERRAIN_PULSE: if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) - && IsBattlerGrounded(gBattlerAttacker)) + && IsBattlerGrounded(battlerAtk)) basePower *= 2; break; case EFFECT_EXPANDING_FORCE: - if (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) MulModifier(&basePower, UQ_4_12(1.5)); break; case EFFECT_RISING_VOLTAGE: - if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) basePower *= 2; break; case EFFECT_BEAT_UP: @@ -8770,7 +8770,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) #endif break; case EFFECT_PSYBLADE: - if (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) MulModifier(&basePower, UQ_4_12(1.5)); break; } @@ -9611,7 +9611,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move || (gSideStatuses[defSide] & SIDE_STATUS_AURORA_VEIL)) && abilityAtk != ABILITY_INFILTRATOR && !(isCrit) - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg) + && !gProtectStructs[battlerAtk].confusionSelfDmg) { if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) MulModifier(&finalModifier, UQ_4_12(0.66)); @@ -9620,7 +9620,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } // Parental Bond Second Strike - if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT) + if (gSpecialStatuses[battlerAtk].parentalBondState == PARENTAL_BOND_2ND_HIT) { if (B_PARENTAL_BOND_DMG < GEN_7) MulModifier(&finalModifier, UQ_4_12(0.5)); From 0b8285737a7434c8d48d05e623105fea2e8186cf Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 27 Mar 2023 09:19:48 -0300 Subject: [PATCH 041/131] Fixed Comatose AI checks --- include/battle_ai_util.h | 1 + src/battle_ai_main.c | 8 ++++---- src/battle_ai_util.c | 5 +++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 11eba7b661..892736b54e 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -144,6 +144,7 @@ bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof); u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move); bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move); bool32 IsWakeupTurn(u8 battler); +bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId); // partner logic u16 GetAllyChosenMove(u8 battlerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 19eedb41cc..a359358b92 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -974,7 +974,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } break; case EFFECT_DREAM_EATER: - if (!(gBattleMons[battlerDef].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerDef] == ABILITY_COMATOSE) + if (!AI_IsBattlerAsleepOrComatose(battlerDef)) score -= 8; else if (effectiveness == AI_EFFECTIVENESS_x0) score -= 10; @@ -1453,7 +1453,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) break; case EFFECT_SNORE: case EFFECT_SLEEP_TALK: - if (IsWakeupTurn(battlerAtk) || (!(gBattleMons[battlerAtk].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerAtk] != ABILITY_COMATOSE)) + if (IsWakeupTurn(battlerAtk) || !AI_IsBattlerAsleepOrComatose(battlerAtk)) score -= 10; // if mon will wake up, is not asleep, or is not comatose break; case EFFECT_MEAN_LOOK: @@ -1463,7 +1463,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_NIGHTMARE: if (gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE) score -= 10; - else if (!(gBattleMons[battlerDef].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerDef] == ABILITY_COMATOSE) + else if (!AI_IsBattlerAsleepOrComatose(battlerDef)) score -= 8; else if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, AI_DATA->partnerMove)) score -= 10; @@ -3780,7 +3780,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_NIGHTMARE: if (AI_DATA->abilities[battlerDef] != ABILITY_MAGIC_GUARD && !(gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE) - && (AI_DATA->abilities[battlerDef] == ABILITY_COMATOSE || gBattleMons[battlerDef].status1 & STATUS1_SLEEP)) + && AI_IsBattlerAsleepOrComatose(battlerDef)) { score += 5; if (IsBattlerTrapped(battlerDef, TRUE)) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a9e3ed3e0b..7b8fb04638 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3749,3 +3749,8 @@ bool32 ShouldUseZMove(u8 battlerAtk, u8 battlerDef, u16 chosenMove) return FALSE; } + +bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId) +{ + return (gBattleMons[battlerId].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerId] == ABILITY_COMATOSE; +} From 7b306b61473f2fa31b676769c7fb66fbf6bb7d2d Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 27 Mar 2023 17:32:16 +0100 Subject: [PATCH 042/131] RandomElement for structured RNG Converts Tri Attack and Dire Claw to use structured RNG. --- include/random.h | 16 ++++- src/battle_script_commands.c | 5 +- src/random.c | 10 +++- test/move_effect_dire_claw.c | 46 ++++++-------- test/move_effect_tri_attack.c | 48 ++++++--------- test/random.c | 33 +++++++++- test/test_battle.h | 16 ++++- test/test_runner_battle.c | 109 +++++++++++++++++++++++++++------- 8 files changed, 199 insertions(+), 84 deletions(-) diff --git a/include/random.h b/include/random.h index 60c718348c..fd340c26db 100644 --- a/include/random.h +++ b/include/random.h @@ -29,7 +29,12 @@ void SeedRng2(u16 seed); * * RandomTag identifies the purpose of the value. * - * RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive. + * RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive + * with uniform probability. + * + * RandomElement(tag, array) returns an element in array with uniform + * probability. The array must be known at compile-time (e.g. a global + * const array). * * RandomPercentage(tag, t) returns FALSE with probability (1-t)/100, * and TRUE with probability t/100. @@ -47,6 +52,7 @@ enum RandomTag RNG_CRITICAL_HIT, RNG_CUTE_CHARM, RNG_DAMAGE_MODIFIER, + RNG_DIRE_CLAW, RNG_FLAME_BODY, RNG_FORCE_RANDOM_SWITCH, RNG_FROZEN, @@ -60,6 +66,7 @@ enum RandomTag RNG_SPEED_TIE, RNG_STATIC, RNG_STENCH, + RNG_TRI_ATTACK, }; #define RandomWeighted(tag, ...) \ @@ -77,10 +84,17 @@ enum RandomTag RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \ }) +#define RandomElement(tag, array) \ + ({ \ + *(typeof((array)[0]) *)RandomElementArray(tag, array, sizeof((array)[0]), ARRAY_COUNT(array)); \ + }) + u32 RandomUniform(enum RandomTag, u32 lo, u32 hi); u32 RandomWeightedArray(enum RandomTag, u32 sum, u32 n, const u8 *weights); +const void *RandomElementArray(enum RandomTag, const void *array, size_t size, size_t count); u32 RandomUniformDefault(enum RandomTag, u32 lo, u32 hi); u32 RandomWeightedArrayDefault(enum RandomTag, u32 sum, u32 n, const u8 *weights); +const void *RandomElementArrayDefault(enum RandomTag, const void *array, size_t size, size_t count); #endif // GUARD_RANDOM_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3376f9db60..62dcbf4472 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3318,7 +3318,8 @@ void SetMoveEffect(bool32 primary, u32 certain) } else { - gBattleScripting.moveEffect = Random() % 3 + 3; + static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FREEZE, MOVE_EFFECT_PARALYSIS }; + gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects); SetMoveEffect(FALSE, 0); } break; @@ -3779,7 +3780,7 @@ void SetMoveEffect(bool32 primary, u32 certain) if (!gBattleMons[gEffectBattler].status1) { static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP }; - gBattleScripting.moveEffect = sDireClawEffects[Random() % ARRAY_COUNT(sDireClawEffects)]; + gBattleScripting.moveEffect = RandomElement(RNG_DIRE_CLAW, sDireClawEffects); SetMoveEffect(TRUE, 0); } break; diff --git a/src/random.c b/src/random.c index e59b563876..14983e7764 100644 --- a/src/random.c +++ b/src/random.c @@ -38,9 +38,12 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi); __attribute__((weak, alias("RandomWeightedArrayDefault"))) u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights); +__attribute__((weak, alias("RandomElementArrayDefault"))) +const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count); + u32 RandomUniformDefault(enum RandomTag tag, u32 lo, u32 hi) { - return lo + (((hi - lo) * Random()) >> 16); + return lo + (((hi - lo + 1) * Random()) >> 16); } u32 RandomWeightedArrayDefault(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) @@ -55,3 +58,8 @@ u32 RandomWeightedArrayDefault(enum RandomTag tag, u32 sum, u32 n, const u8 *wei } return n - 1; } + +const void *RandomElementArrayDefault(enum RandomTag tag, const void *array, size_t size, size_t count) +{ + return (const u8 *)array + size * RandomUniformDefault(tag, 0, count - 1); +} diff --git a/test/move_effect_dire_claw.c b/test/move_effect_dire_claw.c index f02555df30..2212c3cb0e 100644 --- a/test/move_effect_dire_claw.c +++ b/test/move_effect_dire_claw.c @@ -6,21 +6,14 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_DIRE_CLAW].effect == EFFECT_DIRE_CLAW); } -// found by brute-force -#define RNG_SLEEP 0xcb0 -#define RNG_POISON 0x2BE -#define RNG_PARALYSIS 5 - SINGLE_BATTLE_TEST("Dire Claw can inflict poison, paralysis or sleep") { u8 statusAnim; - u32 rng; - KNOWN_FAILING; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; } + PASSES_RANDOMLY(1, 3, RNG_DIRE_CLAW); GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -48,15 +41,14 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respe u16 species; u32 rng; #if B_PARALYZE_ELECTRIC >= GEN_6 - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; } #endif // B_PARALYZE_ELECTRIC - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; species = SPECIES_ARBOK;} + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ARBOK;} GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { - TURN { MOVE(player, MOVE_DIRE_CLAW); } + TURN { MOVE(player, MOVE_DIRE_CLAW, WITH_RNG(RNG_DIRE_CLAW, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); @@ -76,21 +68,20 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep pokemo u8 statusAnim; u16 species, ability; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } #if P_GEN_4_POKEMON == TRUE - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } #endif // P_GEN_4_POKEMON - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) {Ability(ability);} } WHEN { - TURN { MOVE(player, MOVE_DIRE_CLAW); } + TURN { MOVE(player, MOVE_DIRE_CLAW, WITH_RNG(RNG_DIRE_CLAW, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); @@ -112,15 +103,14 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep a mon { u8 statusAnim; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_BURN);} } WHEN { - TURN { MOVE(player, MOVE_DIRE_CLAW); } + TURN { MOVE(player, MOVE_DIRE_CLAW, WITH_RNG(RNG_DIRE_CLAW, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); diff --git a/test/move_effect_tri_attack.c b/test/move_effect_tri_attack.c index 9bfacdb985..c3fbfaaceb 100644 --- a/test/move_effect_tri_attack.c +++ b/test/move_effect_tri_attack.c @@ -6,21 +6,14 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_TRI_ATTACK].effect == EFFECT_TRI_ATTACK); } -// found by brute-force -#define RNG_PARALYSIS 0xcb0 -#define RNG_BURN 0x2BE -#define RNG_FREEZE 5 - SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze") { u8 statusAnim; - u32 rng; - KNOWN_FAILING; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; } + PASSES_RANDOMLY(1, 3, RNG_TRI_ATTACK); GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -48,16 +41,15 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ u16 species; u32 rng; #if B_PARALYZE_ELECTRIC >= GEN_6 - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU;} + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU;} #endif // B_PARALYZE_ELECTRIC - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_ARCANINE; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; species = SPECIES_GLALIE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_ARCANINE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; species = SPECIES_GLALIE; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { - TURN { MOVE(player, MOVE_TRI_ATTACK); } + TURN { MOVE(player, MOVE_TRI_ATTACK, WITH_RNG(RNG_TRI_ATTACK, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); @@ -80,23 +72,22 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilitie u8 statusAnim; u16 species, ability; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } #if P_GEN_4_POKEMON == TRUE - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } #endif // P_GEN_4_POKEMON #if P_GEN_7_POKEMON == TRUE - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; } #endif // P_GEN_7_POKEMON - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_SEAKING; ability = ABILITY_WATER_VEIL; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_SEAKING; ability = ABILITY_WATER_VEIL; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) {Ability(ability);} } WHEN { - TURN { MOVE(player, MOVE_TRI_ATTACK); } + TURN { MOVE(player, MOVE_TRI_ATTACK, WITH_RNG(RNG_TRI_ATTACK, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); @@ -118,15 +109,14 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze a mon which is alread { u8 statusAnim; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} } WHEN { - TURN { MOVE(player, MOVE_TRI_ATTACK); } + TURN { MOVE(player, MOVE_TRI_ATTACK, WITH_RNG(RNG_TRI_ATTACK, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); diff --git a/test/random.c b/test/random.c index abaf4a4f82..39f587c062 100644 --- a/test/random.c +++ b/test/random.c @@ -34,6 +34,17 @@ TEST("RandomWeighted generates 0..n-1") } } +TEST("RandomElement generates an element") +{ + u32 i; + static const u8 es[4] = { 1, 2, 4, 8 }; + for (i = 0; i < 1024; i++) + { + u32 e = *(const u8 *)RandomElementArrayDefault(RNG_NONE, es, sizeof(es[0]), ARRAY_COUNT(es)); + EXPECT(e == 1 || e == 2 || e == 4 || e == 8); + } +} + TEST("RandomUniform generates uniform distribution") { u32 i, error; @@ -42,7 +53,7 @@ TEST("RandomUniform generates uniform distribution") memset(distribution, 0, sizeof(distribution)); for (i = 0; i < 4096; i++) { - u32 r = RandomUniformDefault(RNG_NONE, 0, ARRAY_COUNT(distribution)); + u32 r = RandomUniformDefault(RNG_NONE, 0, ARRAY_COUNT(distribution) - 1); EXPECT(0 <= r && r < ARRAY_COUNT(distribution)); distribution[r]++; } @@ -79,3 +90,23 @@ TEST("RandomWeighted generates distribution in proportion to the weights") EXPECT_LT(error, UQ_4_12(0.025)); } + +TEST("RandomElement generates a uniform distribution") +{ + u32 i, error; + static const u8 es[4] = { 1, 2, 4, 8 }; + u16 distribution[9]; + + memset(distribution, 0, sizeof(distribution)); + for (i = 0; i < 4096; i++) + { + u32 e = *(const u8 *)RandomElementArrayDefault(RNG_NONE, es, sizeof(es[0]), ARRAY_COUNT(es)); + distribution[e]++; + } + + error = 0; + for (i = 0; i < ARRAY_COUNT(es); i++) + error += abs(UQ_4_12(0.25) - distribution[es[i]]); + + EXPECT_LT(error, UQ_4_12(0.025)); +} diff --git a/test/test_battle.h b/test/test_battle.h index 0e0464254f..60d0dc33cc 100644 --- a/test/test_battle.h +++ b/test/test_battle.h @@ -303,13 +303,14 @@ * The inference process is naive, if your test contains anything that * modifies the speed of a battler you should specify them explicitly. * - * MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:]) + * MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:], [WITH_RNG(tag, value]) * Used when the battler chooses Fight. Either the move ID or move slot * must be specified. megaEvolve: TRUE causes the battler to Mega Evolve * if able, hit: FALSE causes the move to miss, criticalHit: TRUE causes * the move to land a critical hit, target: is used in double battles to * choose the target (when necessary), and allowed: FALSE is used to - * reject an illegal move e.g. a Disabled one. + * reject an illegal move e.g. a Disabled one. WITH_RNG allows the move + * to specify an explicit outcome for an RNG tag. * MOVE(playerLeft, MOVE_TACKLE, target: opponentRight); * If the battler does not have an explicit Moves specified the moveset * will be populated based on the MOVEs it uses. @@ -538,11 +539,18 @@ struct QueuedEvent } as; }; +struct TurnRNG +{ + u16 tag; + u16 value; +}; + struct BattlerTurn { u8 hit:2; u8 criticalHit:2; u8 secondaryEffect:2; + struct TurnRNG rng; }; struct BattleTestData @@ -758,6 +766,8 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING }; #define SKIP_TURN(battler) SkipTurn(__LINE__, battler) #define SEND_OUT(battler, partyIndex) SendOut(__LINE__, battler, partyIndex) +#define WITH_RNG(tag, value) rng: ((struct TurnRNG) { tag, value }) + struct MoveContext { u16 move; @@ -777,6 +787,8 @@ struct MoveContext u16 explicitAllowed:1; struct BattlePokemon *target; bool8 explicitTarget; + struct TurnRNG rng; + bool8 explicitRNG; }; void OpenTurn(u32 sourceLine); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index d869bf2e51..1b03341a45 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -292,6 +292,20 @@ static void BattleTest_Run(void *data) u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) { + const struct BattlerTurn *turn = NULL; + u32 default_ = hi; + + if (gCurrentTurnActionNumber < gBattlersCount) + { + u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; + } + + if (turn && turn->rng.tag == tag) + { + default_ = turn->rng.value; + } + if (tag == STATE->rngTag) { u32 n = hi - lo + 1; @@ -308,7 +322,7 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) return STATE->runTrial + lo; } - return hi; + return default_; } u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) @@ -322,28 +336,35 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; } - switch (tag) + if (turn && turn->rng.tag == tag) { - case RNG_ACCURACY: - ASSUME(n == 2); - if (turn && turn->hit) - return turn->hit - 1; - default_ = TRUE; - break; + default_ = turn->rng.value; + } + else + { + switch (tag) + { + case RNG_ACCURACY: + ASSUME(n == 2); + if (turn && turn->hit) + return turn->hit - 1; + default_ = TRUE; + break; - case RNG_CRITICAL_HIT: - ASSUME(n == 2); - if (turn && turn->criticalHit) - return turn->criticalHit - 1; - default_ = FALSE; - break; + case RNG_CRITICAL_HIT: + ASSUME(n == 2); + if (turn && turn->criticalHit) + return turn->criticalHit - 1; + default_ = FALSE; + break; - case RNG_SECONDARY_EFFECT: - ASSUME(n == 2); - if (turn && turn->secondaryEffect) - return turn->secondaryEffect - 1; - default_ = TRUE; - break; + case RNG_SECONDARY_EFFECT: + ASSUME(n == 2); + if (turn && turn->secondaryEffect) + return turn->secondaryEffect - 1; + default_ = TRUE; + break; + } } if (tag == STATE->rngTag) @@ -365,6 +386,52 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) return default_; } +const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count) +{ + const struct BattlerTurn *turn = NULL; + u32 index = count-1; + + if (gCurrentTurnActionNumber < gBattlersCount) + { + u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; + } + + if (turn && turn->rng.tag == tag) + { + u32 element; + for (index = 0; index < count; index++) + { + memcpy(&element, (const u8 *)array + size * index, size); + if (element == turn->rng.value) + break; + } + if (index == count) + { + // TODO: Incorporate the line number. + const char *filename = gTestRunnerState.test->filename; + Test_ExitWithResult(TEST_RESULT_ERROR, "%s: RandomElement illegal value requested: %d", filename, turn->rng.value); + } + } + + if (tag == STATE->rngTag) + { + if (STATE->trials == 1) + { + STATE->trials = count; + PrintTestName(); + } + else if (STATE->trials != count) + { + Test_ExitWithResult(TEST_RESULT_ERROR, "RandomElement called with inconsistent trials %d and %d", STATE->trials, count); + } + STATE->trialRatio = Q_4_12(1) / count; + index = STATE->runTrial; + } + + return (const u8 *)array + size * index; +} + static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, u32 ability) { struct QueuedAbilityEvent *event; @@ -1357,6 +1424,8 @@ void Move(u32 sourceLine, struct BattlePokemon *battler, struct MoveContext ctx) DATA.battleRecordTurns[DATA.turns][battlerId].criticalHit = 1 + ctx.criticalHit; if (ctx.explicitSecondaryEffect) DATA.battleRecordTurns[DATA.turns][battlerId].secondaryEffect = 1 + ctx.secondaryEffect; + if (ctx.explicitRNG) + DATA.battleRecordTurns[DATA.turns][battlerId].rng = ctx.rng; if (!(DATA.actionBattlers & (1 << battlerId))) { From 2017bee3f8efc1c0d37175cf913bf8a593519b97 Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Mon, 27 Mar 2023 11:35:23 -0700 Subject: [PATCH 043/131] fixed Castform + Cherrim --- data/battle_scripts_1.s | 60 ++++++------------- include/battle_scripts.h | 3 - include/config/battle.h | 1 + include/constants/battle.h | 1 + include/constants/battle_script_commands.h | 7 +-- include/constants/form_change_types.h | 6 +- src/battle_script_commands.c | 36 +++-------- src/battle_util.c | 26 ++++++-- src/data/pokemon/form_change_table_pointers.h | 4 ++ src/data/pokemon/form_change_tables.h | 22 +++++++ 10 files changed, 82 insertions(+), 84 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index b8740cb6b4..e07ecdb728 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5156,7 +5156,7 @@ BattleScript_MoveWeatherChange:: waitanimation printfromtable gMoveWeatherChangeStringIds waitmessage B_WAIT_TIME_LONG - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities goto BattleScript_MoveEnd BattleScript_EffectSunnyDay:: @@ -6860,7 +6860,7 @@ BattleScript_OverworldWeatherStarts:: printfromtable gWeatherStartsStringIds waitmessage B_WAIT_TIME_LONG playanimation_var BS_ATTACKER, sB_ANIM_ARG1 - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_OverworldTerrain:: @@ -8413,7 +8413,7 @@ BattleScript_DrizzleActivates:: printstring STRINGID_PKMNMADEITRAIN waitstate playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_AbilityRaisesDefenderStat:: @@ -8575,7 +8575,7 @@ BattleScript_SandstreamActivates:: printstring STRINGID_PKMNSXWHIPPEDUPSANDSTORM waitstate playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_SandSpitActivates:: @@ -8584,7 +8584,7 @@ BattleScript_SandSpitActivates:: printstring STRINGID_ASANDSTORMKICKEDUP waitstate playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities return BattleScript_ShedSkinActivates:: @@ -8594,37 +8594,15 @@ BattleScript_ShedSkinActivates:: updatestatusicon BS_ATTACKER end3 -BattleScript_WeatherFormChanges:: - setbyte sBATTLER, 0 -BattleScript_WeatherFormChangesLoop:: - tryweatherformdatachange - activateweatherchangeabilities BS_SCRIPTING - addbyte sBATTLER, 1 - jumpifbytenotequal sBATTLER, gBattlersCount, BattleScript_WeatherFormChangesLoop - return - -BattleScript_WeatherFormChange:: - call BattleScript_DoWeatherFormChange - end3 - -BattleScript_DoWeatherFormChange:: - copybyte gBattlerAbility, sBATTLER -.if B_WEATHER_FORMS >= GEN_5 - jumpifspecies BS_SCRIPTING, SPECIES_CASTFORM, BattleScript_DoWeatherFormChange_ForecastCheck -BattleScript_DoWeatherFormChange_FlowerGiftCheck: - jumpifability BS_SCRIPTING, ABILITY_FLOWER_GIFT, BattleScript_DoWeatherFormChange_PopUp - goto BattleScript_DoWeatherFormChange_AfterPopUp -.endif -BattleScript_DoWeatherFormChange_ForecastCheck: - jumpifability BS_SCRIPTING, ABILITY_FORECAST, BattleScript_DoWeatherFormChange_PopUp - goto BattleScript_DoWeatherFormChange_AfterPopUp -BattleScript_DoWeatherFormChange_PopUp: - call BattleScript_AbilityPopUp -BattleScript_DoWeatherFormChange_AfterPopUp: - doweatherformchangeanimation - waitstate - printstring STRINGID_PKMNTRANSFORMED - waitmessage B_WAIT_TIME_LONG +BattleScript_ActivateWeatherAbilities: + copybyte sBATTLER, gBattlerAttacker + setbyte gBattlerAttacker, 0 +BattleScript_ActivateWeatherAbilities_Loop: + activateweatherchangeabilities BS_ATTACKER +BattleScript_ActivateWeatherAbilities_Increment: + addbyte gBattlerAttacker, 1 + jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop + copybyte gBattlerAttacker, sBATTLER return BattleScript_TryAdrenalineOrb: @@ -8719,7 +8697,7 @@ BattleScript_DroughtActivates:: printstring STRINGID_PKMNSXINTENSIFIEDSUN waitstate playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_DesolateLandActivates:: @@ -8728,7 +8706,7 @@ BattleScript_DesolateLandActivates:: printstring STRINGID_EXTREMELYHARSHSUNLIGHT waitstate playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_DesolateLandEvaporatesWaterTypeMoves:: @@ -8748,7 +8726,7 @@ BattleScript_PrimordialSeaActivates:: printstring STRINGID_HEAVYRAIN waitstate playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_PrimordialSeaFizzlesOutFireTypeMoves:: @@ -8825,7 +8803,7 @@ BattleScript_SnowWarningActivates:: printstring STRINGID_SNOWWARNINGHAIL waitstate playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_TerrainSeedLoop: @@ -10002,7 +9980,7 @@ BattleScript_AnnounceAirLockCloudNine:: call BattleScript_AbilityPopUp printstring STRINGID_AIRLOCKACTIVATES waitmessage B_WAIT_TIME_LONG - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_QuickClawActivation:: diff --git a/include/battle_scripts.h b/include/battle_scripts.h index c78fcafe48..b6a2844885 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -149,9 +149,6 @@ extern const u8 BattleScript_TraceActivatesEnd3[]; extern const u8 BattleScript_RainDishActivates[]; extern const u8 BattleScript_SandstreamActivates[]; extern const u8 BattleScript_ShedSkinActivates[]; -extern const u8 BattleScript_WeatherFormChanges[]; -extern const u8 BattleScript_WeatherFormChangesLoop[]; -extern const u8 BattleScript_WeatherFormChange[]; extern const u8 BattleScript_IntimidateActivates[]; extern const u8 BattleScript_DroughtActivates[]; extern const u8 BattleScript_TookAttack[]; diff --git a/include/config/battle.h b/include/config/battle.h index 4a3d6382fb..173f57ac3d 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -99,6 +99,7 @@ // Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon. #define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain. #define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp.Defense stats. Once Spit Up / Swallow is used, these stat changes are lost. +#define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms. // Ability settings #define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters. diff --git a/include/constants/battle.h b/include/constants/battle.h index 61c3776c6c..5d5dca20a2 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -269,6 +269,7 @@ #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) // Battle Weather flags +#define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_TEMPORARY (1 << 0) #define B_WEATHER_RAIN_DOWNPOUR (1 << 1) // unused #define B_WEATHER_RAIN_PERMANENT (1 << 2) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 26064bcfb1..b8a6890988 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -332,10 +332,9 @@ #define MOVEEND_PICKPOCKET 30 #define MOVEEND_DANCER 31 #define MOVEEND_EMERGENCY_EXIT 32 -#define MOVEEND_WEATHER_FORM 33 -#define MOVEEND_SYMBIOSIS 34 -#define MOVEEND_CLEAR_BITS 35 -#define MOVEEND_COUNT 36 +#define MOVEEND_SYMBIOSIS 33 +#define MOVEEND_CLEAR_BITS 34 +#define MOVEEND_COUNT 35 // switch cases #define B_SWITCH_NORMAL 0 diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index 4e60904aa6..651bcf7888 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -87,8 +87,12 @@ // param1: item to hold. #define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 13 +// Form change that activates when a specific weather is set during battle. +// param1: weather to check +#define FORM_CHANGE_BATTLE_WEATHER 14 + // Form change that activates automatically when the turn ends. // param1: ability to check. -#define FORM_CHANGE_BATTLE_TURN_END 14 +#define FORM_CHANGE_BATTLE_TURN_END 15 #endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 51d71e3474..c1df49b4a8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6216,28 +6216,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_WEATHER_FORM: - for (i = 0; i < MAX_BATTLERS_COUNT; i++) - { - switch (gBattleMons[i].species) - { - case SPECIES_CASTFORM: - case SPECIES_CASTFORM_RAINY: - case SPECIES_CASTFORM_SNOWY: - case SPECIES_CASTFORM_SUNNY: - case SPECIES_CHERRIM: - case SPECIES_CHERRIM_SUNSHINE: - effect = TryWeatherFormChange(i); - if (effect) - { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - gBattleScripting.battler = i; - gBattleStruct->formToChangeInto = effect - 1; - } - } - } - gBattleScripting.moveendState++; - break; case MOVEEND_SYMBIOSIS: for (i = 0; i < gBattlersCount; i++) { @@ -15080,13 +15058,13 @@ static void Cmd_tryweatherformdatachange(void) u8 form; - gBattlescriptCurrInstr = cmd->nextInstr; - form = TryWeatherFormChange(gBattleScripting.battler); - if (form) - { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - *(&gBattleStruct->formToChangeInto) = form - 1; - } + // gBattlescriptCurrInstr = cmd->nextInstr; + // form = TryWeatherFormChange(gBattleScripting.battler); + // if (form) + // { + // BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); + // *(&gBattleStruct->formToChangeInto) = form - 1; + // } } // Water and Mud Sport diff --git a/src/battle_util.c b/src/battle_util.c index c6a59acf5b..3f85d298a0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2564,7 +2564,15 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_WEATHER_FORM: - AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, 0, 0, 0, 0); + for (i = 0; i < gBattlersCount; ++i) + { + // This breaks Eiscue right now, because Eiscue doesn't use FORM_CHANGE_BATTLE_WEATHER. + if(TryBattleFormChange(i, FORM_CHANGE_BATTLE_WEATHER)) + { + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); + effect++; + } + } gBattleStruct->turnCountersTracker++; break; case ENDTURN_STATUS_HEAL: @@ -6155,11 +6163,11 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move #else TRY_WEATHER_FORM: #endif - effect = TryWeatherFormChange(battler); - if (effect != 0) + if (IsBattlerWeatherAffected(battler, gBattleWeather) + && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - *(&gBattleStruct->formToChangeInto) = effect - 1; + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); + effect++; } break; case ABILITY_ICE_FACE: @@ -10153,6 +10161,11 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) } } break; + case FORM_CHANGE_BATTLE_WEATHER: + if (gBattleWeather & formChanges[i].param1 + || (gBattleWeather == B_WEATHER_NONE && formChanges[i].param1 == B_WEATHER_NONE)) + targetSpecies = formChanges[i].targetSpecies; + break; case FORM_CHANGE_BATTLE_TURN_END: if (formChanges[i].param1 == GetBattlerAbility(battlerId)) targetSpecies = formChanges[i].targetSpecies; @@ -10168,7 +10181,8 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) bool32 CanBattlerFormChange(u8 battlerId, u16 method) { // Can't change form if transformed. - if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED + && B_TRANSFORM_FORM_CHANGES >= GEN_5) return FALSE; // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle. if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 83f68d70c0..daeaa9cbbe 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -64,6 +64,10 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ALTARIA_MEGA] = sAltariaFormChangeTable, [SPECIES_ABSOL] = sAbsolFormChangeTable, [SPECIES_ABSOL_MEGA] = sAbsolFormChangeTable, + [SPECIES_CASTFORM] = sCastformFormChangeTable, + [SPECIES_CASTFORM_SUNNY] = sCastformFormChangeTable, + [SPECIES_CASTFORM_RAINY] = sCastformFormChangeTable, + [SPECIES_CASTFORM_SNOWY] = sCastformFormChangeTable, [SPECIES_BANETTE] = sBanetteFormChangeTable, [SPECIES_BANETTE_MEGA] = sBanetteFormChangeTable, [SPECIES_AGGRON] = sAggronFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index afe54f6322..c4ade7b9a8 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -155,6 +155,18 @@ static const struct FormChange sAbsolFormChangeTable[] = { {FORM_CHANGE_TERMINATOR}, }; +static const struct FormChange sCastformFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SUNNY, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_RAINY, B_WEATHER_RAIN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SNOWY, B_WEATHER_HAIL}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM, ~(B_WEATHER_SUN | B_WEATHER_RAIN | B_WEATHER_HAIL)}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM, B_WEATHER_NONE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CASTFORM}, + {FORM_CHANGE_FAINT, SPECIES_CASTFORM}, + {FORM_CHANGE_END_BATTLE, SPECIES_CASTFORM}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sBanetteFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, {FORM_CHANGE_TERMINATOR}, @@ -218,6 +230,16 @@ static const struct FormChange sBurmyFormChangeTable[] = { {FORM_CHANGE_TERMINATOR}, }; +static const struct FormChange sCherrimFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_SUNSHINE, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM, ~B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM, B_WEATHER_NONE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CHERRIM}, + {FORM_CHANGE_FAINT, SPECIES_CHERRIM}, + {FORM_CHANGE_END_BATTLE, SPECIES_CHERRIM}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sLopunnyFormChangeTable[] = { {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, {FORM_CHANGE_TERMINATOR}, From b856cb3e624652e5fb4b75d598359c84cd3f5764 Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Mon, 27 Mar 2023 12:05:06 -0700 Subject: [PATCH 044/131] fixed Eiscue + multiple weather form changes at once (probably) --- src/battle_util.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 3f85d298a0..9e85f3ce39 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2566,14 +2566,14 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_WEATHER_FORM: for (i = 0; i < gBattlersCount; ++i) { - // This breaks Eiscue right now, because Eiscue doesn't use FORM_CHANGE_BATTLE_WEATHER. - if(TryBattleFormChange(i, FORM_CHANGE_BATTLE_WEATHER)) + if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) { - BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; + break; } } - gBattleStruct->turnCountersTracker++; + if (effect == 0) + gBattleStruct->turnCountersTracker++; break; case ENDTURN_STATUS_HEAL: for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) @@ -6163,7 +6163,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move #else TRY_WEATHER_FORM: #endif - if (IsBattlerWeatherAffected(battler, gBattleWeather) + if ((IsBattlerWeatherAffected(battler, gBattleWeather) || gBattleWeather == B_WEATHER_NONE) && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) { BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); From 00d695ac2b313c5a887d20aad4618f350725713c Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 28 Mar 2023 10:38:48 -0400 Subject: [PATCH 045/131] add AI_FLAG_OMNISCIENT --- include/battle.h | 4 ++-- include/battle_ai_util.h | 1 + include/constants/battle_ai.h | 1 + src/battle_ai_main.c | 13 +++++++++++++ src/battle_ai_util.c | 19 ++++++++++++++----- src/battle_debug.c | 4 ++-- src/battle_main.c | 4 ++-- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/include/battle.h b/include/battle.h index 491273b80b..19f9df13d8 100644 --- a/include/battle.h +++ b/include/battle.h @@ -272,8 +272,8 @@ struct AiPartyMon struct AIPartyData // Opposing battlers - party mons. { - struct AiPartyMon mons[2][PARTY_SIZE]; // 2 parties(player, opponent). Used to save information on opposing party. - u8 count[2]; + struct AiPartyMon mons[NUM_BATTLE_SIDES][PARTY_SIZE]; // 2 parties(player, opponent). Used to save information on opposing party. + u8 count[NUM_BATTLE_SIDES]; }; struct AiLogicData diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 11eba7b661..95f6619c5e 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -9,6 +9,7 @@ bool32 AI_RandLessThan(u8 val); void RecordLastUsedMoveByTarget(void); +bool32 BattlerHasAi(u32 battlerId); bool32 IsBattlerAIControlled(u32 battlerId); void ClearBattlerMoveHistory(u8 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 1cfb9cd4dc..1316054cd1 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -57,6 +57,7 @@ #define AI_FLAG_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished #define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks #define AI_FLAG_ACE_POKEMON (1 << 16) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. +#define AI_FLAG_OMNISCIENT (1 << 17) // AI has full knowledge of player moves, abilities, hold items // 'other' ai logic flags #define AI_FLAG_ROAMING (1 << 29) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 19eedb41cc..6e308003ad 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -257,6 +257,8 @@ static void CopyBattlerDataToAIParty(u32 bPosition, u32 side) void Ai_InitPartyStruct(void) { u32 i; + bool32 isOmniscient = (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT); + struct Pokemon *mon; AI_PARTY->count[B_SIDE_PLAYER] = gPlayerPartyCount; AI_PARTY->count[B_SIDE_OPPONENT] = gEnemyPartyCount; @@ -278,6 +280,17 @@ void Ai_InitPartyStruct(void) { if (GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0) AI_PARTY->mons[B_SIDE_PLAYER][i].isFainted = TRUE; + + if (isOmniscient) + { + u32 j; + mon = &gPlayerParty[i]; + AI_PARTY->mons[B_SIDE_PLAYER][i].item = GetMonData(mon, MON_DATA_HELD_ITEM); + AI_PARTY->mons[B_SIDE_PLAYER][i].heldEffect = ItemId_GetHoldEffect(AI_PARTY->mons[B_SIDE_PLAYER][i].item); + AI_PARTY->mons[B_SIDE_PLAYER][i].ability = GetMonAbility(mon); + for (j = 0; j < MAX_MON_MOVES; j++) + AI_PARTY->mons[B_SIDE_PLAYER][i].moves[j] = GetMonData(mon, MON_DATA_MOVE1 + j); + } } } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a9e3ed3e0b..93586626e2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -457,7 +457,7 @@ void RecordLastUsedMoveByTarget(void) RecordKnownMove(gBattlerTarget, gLastMoves[gBattlerTarget]); } -bool32 IsBattlerAIControlled(u32 battlerId) +bool32 BattlerHasAi(u32 battlerId) { switch (GetBattlerPosition(battlerId)) { @@ -473,6 +473,14 @@ bool32 IsBattlerAIControlled(u32 battlerId) } } +bool32 IsBattlerAIControlled(u32 battlerId) +{ + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT) + return TRUE; + + return BattlerHasAi(battlerId); +} + void ClearBattlerMoveHistory(u8 battlerId) { memset(BATTLE_HISTORY->usedMoves[battlerId], 0, sizeof(BATTLE_HISTORY->usedMoves[battlerId])); @@ -1230,8 +1238,9 @@ s32 AI_GetAbility(u32 battlerId) if (knownAbility == ABILITY_NONE) return knownAbility; - if (BATTLE_HISTORY->abilities[battlerId] != ABILITY_NONE) - return BATTLE_HISTORY->abilities[battlerId]; + if (AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability != ABILITY_NONE) { + return AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability; + } // Abilities that prevent fleeing - treat as always known if (knownAbility == ABILITY_SHADOW_TAG || knownAbility == ABILITY_MAGNET_PULL || knownAbility == ABILITY_ARENA_TRAP) @@ -1257,10 +1266,10 @@ u16 AI_GetHoldEffect(u32 battlerId) u32 holdEffect; if (!IsBattlerAIControlled(battlerId)) - holdEffect = BATTLE_HISTORY->itemEffects[battlerId]; + holdEffect = AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect; else holdEffect = GetBattlerHoldEffect(battlerId, FALSE); - + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) return holdEffect; diff --git a/src/battle_debug.c b/src/battle_debug.c index 027be03a45..1d690caaa0 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -774,7 +774,7 @@ static void Task_ShowAiPoints(u8 taskId) // Swap battler if it's player mon data->aiBattlerId = data->battlerId; - while (!IsBattlerAIControlled(data->aiBattlerId)) + while (!BattlerHasAi(data->aiBattlerId)) { if (++data->aiBattlerId >= gBattlersCount) data->aiBattlerId = 0; @@ -931,7 +931,7 @@ static void Task_ShowAiKnowledge(u8 taskId) // Swap battler if it's player mon data->aiBattlerId = data->battlerId; - while (!IsBattlerAIControlled(data->aiBattlerId)) + while (!BattlerHasAi(data->aiBattlerId)) { if (++data->aiBattlerId >= gBattlersCount) data->aiBattlerId = 0; diff --git a/src/battle_main.c b/src/battle_main.c index efbf1b8195..8e0dc6d878 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3859,7 +3859,7 @@ static void TryDoEventsBeforeFirstTurn(void) gChosenActionByBattler[i] = B_ACTION_NONE; gChosenMoveByBattler[i] = MOVE_NONE; // Record party slots of player's mons that appeared in battle - if (!IsBattlerAIControlled(i)) + if (!BattlerHasAi(i)) gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[i]]; } TurnValuesCleanUp(FALSE); @@ -4096,7 +4096,7 @@ static void HandleTurnActionSelectionState(void) // Do AI score computations here so we can use them in AI_TrySwitchOrUseItem if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) - && (IsBattlerAIControlled(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) { + && (BattlerHasAi(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) { gBattleStruct->aiMoveOrAction[gActiveBattler] = ComputeBattleAiScores(gActiveBattler); } break; From 10ef3e83483c08cc5f62a1f7f0469aafdfa4f7b8 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 28 Mar 2023 10:58:44 -0400 Subject: [PATCH 046/131] style fixes --- src/battle_ai_util.c | 5 ++--- src/battle_main.c | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 93586626e2..51f4ef0467 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1238,9 +1238,8 @@ s32 AI_GetAbility(u32 battlerId) if (knownAbility == ABILITY_NONE) return knownAbility; - if (AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability != ABILITY_NONE) { + if (AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability != ABILITY_NONE) return AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability; - } // Abilities that prevent fleeing - treat as always known if (knownAbility == ABILITY_SHADOW_TAG || knownAbility == ABILITY_MAGNET_PULL || knownAbility == ABILITY_ARENA_TRAP) @@ -1269,7 +1268,7 @@ u16 AI_GetHoldEffect(u32 battlerId) holdEffect = AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect; else holdEffect = GetBattlerHoldEffect(battlerId, FALSE); - + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) return holdEffect; diff --git a/src/battle_main.c b/src/battle_main.c index 8e0dc6d878..8175528525 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4096,7 +4096,8 @@ static void HandleTurnActionSelectionState(void) // Do AI score computations here so we can use them in AI_TrySwitchOrUseItem if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) - && (BattlerHasAi(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) { + && (BattlerHasAi(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) + { gBattleStruct->aiMoveOrAction[gActiveBattler] = ComputeBattleAiScores(gActiveBattler); } break; From 686d42709a6281c5baed0e5a6d8aad34b6b642a5 Mon Sep 17 00:00:00 2001 From: PSF Date: Tue, 28 Mar 2023 15:50:58 -0700 Subject: [PATCH 047/131] Added documentation on resetting battle flags and vars Added Overworld_ResetBattleFlagsAndVars to Overworld_ResetStateAfterWhiteOut --- include/config/battle.h | 2 ++ src/overworld.c | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index 4a3d6382fb..c6bca6de89 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -143,6 +143,7 @@ // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. // Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. +// Once these features are turned on within the game, they will remain on until they are explcitily turned off or until the player whites out. This can be turned off by disabling Overworld_ResetBattleFlagsAndVars. #define B_FLAG_INVERSE_BATTLE 0 // If this flag is set, the battle's type effectiveness are inversed. For example, fire is super effective against water. #define B_FLAG_FORCE_DOUBLE_WILD 0 // If this flag is set, all land and surfing wild battles will be double battles. #define B_SMART_WILD_AI_FLAG 0 // If not 0, you can set this flag in a script to enable smart wild pokemon @@ -152,6 +153,7 @@ // Var Settings // To use the following features in scripting, replace the 0s with the var ID you're assigning it to. // Eg: Replace with VAR_UNUSED_0x40F7 so you can use VAR_TERRAIN for that feature. +// Once these features are turned on within the game, they will remain on until they are explcitily turned off or until the player whites out. This can be turned off by disabling Overworld_ResetBattleFlagsAndVars. #define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active #define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15) diff --git a/src/overworld.c b/src/overworld.c index 6b63a60d5b..9fabe3ed90 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -401,6 +401,23 @@ void Overworld_ResetStateAfterDigEscRope(void) FlagClear(FLAG_SYS_USE_FLASH); } +void Overworld_ResetBattleFlagsAndVars(void) +{ +#if VAR_TERRAIN != 0 + VarSet(VAR_TERRAIN, 0); +#endif + +#if B_VAR_WILD_AI_FLAGS != 0 + VarSet(B_VAR_WILD_AI_FLAGS,0); +#endif + + FlagClear(B_FLAG_INVERSE_BATTLE); + FlagClear(B_FLAG_FORCE_DOUBLE_WILD); + FlagClear(B_SMART_WILD_AI_FLAG); + FlagClear(B_FLAG_NO_BAG_USE); + FlagClear(B_FLAG_NO_CATCHING); +} + static void Overworld_ResetStateAfterWhiteOut(void) { ResetInitialPlayerAvatarState(); @@ -409,9 +426,7 @@ static void Overworld_ResetStateAfterWhiteOut(void) FlagClear(FLAG_SYS_SAFARI_MODE); FlagClear(FLAG_SYS_USE_STRENGTH); FlagClear(FLAG_SYS_USE_FLASH); -#if VAR_TERRAIN != 0 - VarSet(VAR_TERRAIN, 0); -#endif + Overworld_ResetBattleFlagsAndVars(); // If you were defeated by Kyogre/Groudon and the step counter has // maxed out, end the abnormal weather. if (VarGet(VAR_SHOULD_END_ABNORMAL_WEATHER) == 1) From 6a7466c92982bb63f98554857f0ce48cf1347c2b Mon Sep 17 00:00:00 2001 From: pkmnsnfrn Date: Wed, 29 Mar 2023 11:11:07 -0700 Subject: [PATCH 048/131] =?UTF-8?q?Added=20B=5FDOUBLE=5FWILD=5FREQUIRE=5F2?= =?UTF-8?q?=5FMONS=20to=20allow=20use=20of=20B=5FDOUBLE=5FWILD=5FCHANCE=20?= =?UTF-8?q?even=20when=20there=20is=20only=20one=20Pok=C3=A9mon=20in=20the?= =?UTF-8?q?=20party?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/config/battle.h | 1 + src/wild_encounter.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/config/battle.h b/include/config/battle.h index 4a3d6382fb..66d4b92aa3 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -183,6 +183,7 @@ // Other settings #define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. +#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, when the player only has one Pokémon in the party, randomly generated wild battles will always be a Single battle, regardless of the number used in B_DOUBLE_WILD_CHANCE. #define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. #define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. #define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index d228b87a14..ef668c3a1c 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -1097,7 +1097,11 @@ static void ApplyCleanseTagEncounterRateMod(u32 *encRate) bool8 TryDoDoubleWildBattle(void) { +#if B_DOUBLE_WILD_REQUIRE_2_MONS == TRUE if (GetSafariZoneFlag() || GetMonsStateToDoubles() != PLAYER_HAS_TWO_USABLE_MONS) +#else + if (GetSafariZoneFlag()) +#endif return FALSE; #if B_FLAG_FORCE_DOUBLE_WILD != 0 else if (FlagGet(B_FLAG_FORCE_DOUBLE_WILD)) From 24df9823e8f1c20e723b2b9b8b2ab01ee84db379 Mon Sep 17 00:00:00 2001 From: PSF Date: Thu, 30 Mar 2023 06:35:38 -0700 Subject: [PATCH 049/131] In response to PR discussion, added new preproc config for developers to toggle Overworld_ResetBattleFlagsAndVars --- include/config/battle.h | 5 +++-- src/overworld.c | 18 +++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index c6bca6de89..77e0e0f4d9 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -143,7 +143,6 @@ // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. // Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. -// Once these features are turned on within the game, they will remain on until they are explcitily turned off or until the player whites out. This can be turned off by disabling Overworld_ResetBattleFlagsAndVars. #define B_FLAG_INVERSE_BATTLE 0 // If this flag is set, the battle's type effectiveness are inversed. For example, fire is super effective against water. #define B_FLAG_FORCE_DOUBLE_WILD 0 // If this flag is set, all land and surfing wild battles will be double battles. #define B_SMART_WILD_AI_FLAG 0 // If not 0, you can set this flag in a script to enable smart wild pokemon @@ -153,10 +152,12 @@ // Var Settings // To use the following features in scripting, replace the 0s with the var ID you're assigning it to. // Eg: Replace with VAR_UNUSED_0x40F7 so you can use VAR_TERRAIN for that feature. -// Once these features are turned on within the game, they will remain on until they are explcitily turned off or until the player whites out. This can be turned off by disabling Overworld_ResetBattleFlagsAndVars. #define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active #define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15) +//Flag and Var settings +#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If set to TRUE, Flag and Var settings (B_FLAG_INVERSE_BATTLE,B_FLAG_FORCE_DOUBLE_WILD,B_SMART_WILD_AI_FLAG,B_FLAG_NO_BAG_USE,B_FLAG_NO_CATCHING,B_VAR_WILD_AI_FLAGS, and VAR_TERRAIN) will be reset when the player whites out. + // Terrain settings #define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades. #define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8. diff --git a/src/overworld.c b/src/overworld.c index 9fabe3ed90..3af1cfd6d8 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -401,15 +401,16 @@ void Overworld_ResetStateAfterDigEscRope(void) FlagClear(FLAG_SYS_USE_FLASH); } -void Overworld_ResetBattleFlagsAndVars(void) +#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE + void Overworld_ResetBattleFlagsAndVars(void) { -#if VAR_TERRAIN != 0 - VarSet(VAR_TERRAIN, 0); -#endif + #if VAR_TERRAIN != 0 + VarSet(VAR_TERRAIN, 0); + #endif -#if B_VAR_WILD_AI_FLAGS != 0 - VarSet(B_VAR_WILD_AI_FLAGS,0); -#endif + #if B_VAR_WILD_AI_FLAGS != 0 + VarSet(B_VAR_WILD_AI_FLAGS,0); + #endif FlagClear(B_FLAG_INVERSE_BATTLE); FlagClear(B_FLAG_FORCE_DOUBLE_WILD); @@ -417,6 +418,7 @@ void Overworld_ResetBattleFlagsAndVars(void) FlagClear(B_FLAG_NO_BAG_USE); FlagClear(B_FLAG_NO_CATCHING); } +#endif static void Overworld_ResetStateAfterWhiteOut(void) { @@ -426,7 +428,9 @@ static void Overworld_ResetStateAfterWhiteOut(void) FlagClear(FLAG_SYS_SAFARI_MODE); FlagClear(FLAG_SYS_USE_STRENGTH); FlagClear(FLAG_SYS_USE_FLASH); +#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE Overworld_ResetBattleFlagsAndVars(); +#endif // If you were defeated by Kyogre/Groudon and the step counter has // maxed out, end the abnormal weather. if (VarGet(VAR_SHOULD_END_ABNORMAL_WEATHER) == 1) From 4b859ff1e47b482d578f37d5cba7815a86a3ded9 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 31 Mar 2023 00:44:22 -0400 Subject: [PATCH 050/131] Use tilemap file for cable car pylons --- .../cable_car/{pylons.bin => pylon_pole.bin} | 0 graphics/cable_car/pylon_top.bin | Bin 0 -> 20 bytes src/cable_car.c | 65 ++++++++---------- 3 files changed, 27 insertions(+), 38 deletions(-) rename graphics/cable_car/{pylons.bin => pylon_pole.bin} (100%) create mode 100755 graphics/cable_car/pylon_top.bin diff --git a/graphics/cable_car/pylons.bin b/graphics/cable_car/pylon_pole.bin similarity index 100% rename from graphics/cable_car/pylons.bin rename to graphics/cable_car/pylon_pole.bin diff --git a/graphics/cable_car/pylon_top.bin b/graphics/cable_car/pylon_top.bin new file mode 100755 index 0000000000000000000000000000000000000000..44b20744d4383964fb62e47f513541fbc6ad594e GIT binary patch literal 20 bcmZQDU^HMdU^ZYeU^QSfU^n0};4}aL6dnQ& literal 0 HcmV?d00001 diff --git a/src/cable_car.c b/src/cable_car.c index 4eb4c30804..7d18df7b7f 100644 --- a/src/cable_car.c +++ b/src/cable_car.c @@ -27,9 +27,11 @@ #define STATE_END 0xFF -#define TAG_CABLE_CAR 1 -#define TAG_DOOR 2 -#define TAG_CABLE 3 +enum { + TAG_CABLE_CAR = 1, + TAG_DOOR, + TAG_CABLE, +}; struct CableCar { @@ -62,8 +64,8 @@ struct CableCar u16 *groundTilemap; u16 *treesTilemap; u16 *bgMountainsTilemap; - const u16 *pylonHookTilemapEntries; - u8 *pylonStemTilemap; + const u16 *pylonTopTilemap; + u16 *pylonPoleTilemap; }; static EWRAM_DATA struct CableCar *sCableCar = NULL; @@ -129,24 +131,11 @@ static const struct BgTemplate sBgTemplates[4] = { }, }; -static const u8 sGround_Tilemap[] = INCBIN_U8("graphics/cable_car/ground.bin.lz"); -static const u8 sTrees_Tilemap[] = INCBIN_U8("graphics/cable_car/trees.bin.lz"); -static const u8 sBgMountains_Tilemap[] = INCBIN_U8("graphics/cable_car/bg_mountains.bin.lz"); - -static const u16 sPylonHook_TilemapEntries[] = { - 0x3000, - 0x3001, - 0x3002, - 0x3003, - 0x3004, - 0x3005, - 0x3006, - 0x3007, - 0x3008, - 0x3009, -}; - -static const u8 sPylonStems_Tilemap[] = INCBIN_U8("graphics/cable_car/pylons.bin.lz"); +static const u16 sGround_Tilemap[] = INCBIN_U16("graphics/cable_car/ground.bin.lz"); +static const u16 sTrees_Tilemap[] = INCBIN_U16("graphics/cable_car/trees.bin.lz"); +static const u16 sBgMountains_Tilemap[] = INCBIN_U16("graphics/cable_car/bg_mountains.bin.lz"); +static const u16 sPylonTop_Tilemap[] = INCBIN_U16("graphics/cable_car/pylon_top.bin"); +static const u16 sPylonPole_Tilemap[] = INCBIN_U16("graphics/cable_car/pylon_pole.bin.lz"); static const struct CompressedSpriteSheet sSpriteSheets[] = { { gCableCar_Gfx, 0x800, TAG_CABLE_CAR }, @@ -299,8 +288,8 @@ static void CB2_LoadCableCar(void) sCableCar->groundTilemap = malloc_and_decompress(sGround_Tilemap, &sizeOut); sCableCar->treesTilemap = malloc_and_decompress(sTrees_Tilemap, &sizeOut); sCableCar->bgMountainsTilemap = malloc_and_decompress(sBgMountains_Tilemap, &sizeOut); - sCableCar->pylonStemTilemap = malloc_and_decompress(sPylonStems_Tilemap, &sizeOut); - sCableCar->pylonHookTilemapEntries = sPylonHook_TilemapEntries; + sCableCar->pylonPoleTilemap = malloc_and_decompress(sPylonPole_Tilemap, &sizeOut); + sCableCar->pylonTopTilemap = sPylonTop_Tilemap; DecompressAndCopyTileDataToVram(0, gCableCarBg_Gfx, 0, 0, 0); gMain.state++; break; @@ -335,8 +324,8 @@ static void CB2_LoadCableCar(void) case 6: CopyToBgTilemapBufferRect_ChangePalette(1, sCableCar->treesTilemap, 0, 17, 32, 15, 17); CopyToBgTilemapBufferRect_ChangePalette(2, sCableCar->bgMountainsTilemap, 0, 0, 30, 20, 17); - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonHookTilemapEntries, 0, 0, 5, 2, 17); - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonStemTilemap, 0, 2, 2, 20, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonTopTilemap, 0, 0, 5, 2, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonPoleTilemap, 0, 2, 2, 20, 17); gMain.state++; break; case 7: @@ -404,8 +393,8 @@ static void CB2_EndCableCar(void) UnsetBgTilemapBuffer(2); UnsetBgTilemapBuffer(3); ResetBgsAndClearDma3BusyFlags(0); - sCableCar->pylonHookTilemapEntries = NULL; - FREE_AND_SET_NULL(sCableCar->pylonStemTilemap); + sCableCar->pylonTopTilemap = NULL; + FREE_AND_SET_NULL(sCableCar->pylonPoleTilemap); FREE_AND_SET_NULL(sCableCar->bgMountainsTilemap); FREE_AND_SET_NULL(sCableCar->treesTilemap); FREE_AND_SET_NULL(sCableCar->groundTilemap); @@ -514,8 +503,8 @@ static void Task_AnimateBgGoingUp(u8 taskId) FillBgTilemapBufferRect(3, 0, 2, 0, 1, 2, 17); break; case 16: - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonHookTilemapEntries, 0, 0, 5, 2, 17); - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonStemTilemap, 0, 2, 2, 30, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonTopTilemap, 0, 0, 5, 2, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonPoleTilemap, 0, 2, 2, 30, 17); sCableCar->bg3VerticalOffset = 64; break; } @@ -542,7 +531,7 @@ static void Task_AnimateBgGoingDown(u8 taskId) switch (sCableCar->bg3HorizontalOffset) { case 176: - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonStemTilemap, 0, 2, 2, 30, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonPoleTilemap, 0, 2, 2, 30, 17); break; case 16: FillBgTilemapBufferRect(3, 0, 2, 0, 3, 2, 17); @@ -550,14 +539,14 @@ static void Task_AnimateBgGoingDown(u8 taskId) sCableCar->bg3VerticalOffset = 192; break; case 32: - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[2], 2, 0, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[3], 3, 0, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[7], 2, 1, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[8], 3, 1, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[2], 2, 0, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[3], 3, 0, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[7], 2, 1, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[8], 3, 1, 1, 1, 17); break; case 40: - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[4], 4, 0, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[9], 4, 1, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[4], 4, 0, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[9], 4, 1, 1, 1, 17); break; } } From 57396026b2f212bbc7c2fa04d230311738d9f8ef Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 31 Mar 2023 14:57:51 -0400 Subject: [PATCH 051/131] Replace NUM_TEXT_PRINTERS with WINDOWS_MAX --- gflib/text.c | 6 +++--- gflib/text.h | 2 -- gflib/window.c | 2 -- gflib/window.h | 2 ++ src/contest.c | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/gflib/text.c b/gflib/text.c index 86dca38291..1bded26b5a 100644 --- a/gflib/text.c +++ b/gflib/text.c @@ -36,7 +36,7 @@ static u32 GetGlyphWidth_Narrow(u16, bool32); static u32 GetGlyphWidth_SmallNarrow(u16, bool32); static EWRAM_DATA struct TextPrinter sTempTextPrinter = {0}; -static EWRAM_DATA struct TextPrinter sTextPrinters[NUM_TEXT_PRINTERS] = {0}; +static EWRAM_DATA struct TextPrinter sTextPrinters[WINDOWS_MAX] = {0}; static u16 sFontHalfRowLookupTable[0x51]; static u16 sLastTextBgColor; @@ -244,7 +244,7 @@ static void SetFontsPointer(const struct FontInfo *fonts) void DeactivateAllTextPrinters(void) { int printer; - for (printer = 0; printer < NUM_TEXT_PRINTERS; ++printer) + for (printer = 0; printer < WINDOWS_MAX; ++printer) sTextPrinters[printer].active = FALSE; } @@ -322,7 +322,7 @@ void RunTextPrinters(void) if (!gDisableTextPrinters) { - for (i = 0; i < NUM_TEXT_PRINTERS; ++i) + for (i = 0; i < WINDOWS_MAX; ++i) { if (sTextPrinters[i].active) { diff --git a/gflib/text.h b/gflib/text.h index a88cb990e1..ff13efa9a8 100644 --- a/gflib/text.h +++ b/gflib/text.h @@ -3,8 +3,6 @@ #include "characters.h" -#define NUM_TEXT_PRINTERS 32 - // Given as a text speed when all the text should be // loaded at once but not copied to vram yet. #define TEXT_SKIP_DRAW 0xFF diff --git a/gflib/window.c b/gflib/window.c index 1621a08842..76e863f10e 100644 --- a/gflib/window.c +++ b/gflib/window.c @@ -9,8 +9,6 @@ u8 gTransparentTileNumber; void *gWindowBgTilemapBuffers[NUM_BACKGROUNDS]; extern u32 gWindowTileAutoAllocEnabled; -#define WINDOWS_MAX 32 - EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0}; EWRAM_DATA static struct Window* sWindowPtr = NULL; EWRAM_DATA static u16 sWindowSize = 0; diff --git a/gflib/window.h b/gflib/window.h index 0000dd864d..0f2dff2a8a 100644 --- a/gflib/window.h +++ b/gflib/window.h @@ -1,6 +1,8 @@ #ifndef GUARD_WINDOW_H #define GUARD_WINDOW_H +#define WINDOWS_MAX 32 + #define PIXEL_FILL(num) ((num) | ((num) << 4)) enum { diff --git a/src/contest.c b/src/contest.c index 2c0f66f6bd..8a1847f111 100644 --- a/src/contest.c +++ b/src/contest.c @@ -5503,7 +5503,7 @@ static void ContestBG_FillBoxWithTile(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 wi static bool32 Contest_RunTextPrinters(void) { RunTextPrinters(); - return IsTextPrinterActive(4); + return IsTextPrinterActive(WIN_GENERAL_TEXT); } static void Contest_SetBgCopyFlags(u32 flagIndex) From 83ef5a229de4aede0beb81270b807c65b2b6f0c9 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Fri, 31 Mar 2023 20:26:19 +0200 Subject: [PATCH 052/131] =?UTF-8?q?Center=20gen=201=20pok=C3=A9mon=20icons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graphics/pokemon/aerodactyl/icon.png | Bin 403 -> 431 bytes graphics/pokemon/alakazam/icon.png | Bin 492 -> 512 bytes graphics/pokemon/articuno/icon.png | Bin 386 -> 406 bytes graphics/pokemon/bellsprout/icon.png | Bin 311 -> 296 bytes graphics/pokemon/butterfree/icon.png | Bin 413 -> 430 bytes graphics/pokemon/cloyster/icon.png | Bin 454 -> 418 bytes graphics/pokemon/dodrio/icon.png | Bin 492 -> 452 bytes graphics/pokemon/dragonite/icon.png | Bin 407 -> 412 bytes graphics/pokemon/exeggutor/icon.png | Bin 376 -> 385 bytes graphics/pokemon/gastly/icon.png | Bin 400 -> 389 bytes graphics/pokemon/gyarados/icon.png | Bin 608 -> 563 bytes graphics/pokemon/haunter/icon.png | Bin 482 -> 405 bytes graphics/pokemon/hypno/icon.png | Bin 424 -> 443 bytes graphics/pokemon/kingler/icon.png | Bin 496 -> 461 bytes graphics/pokemon/koffing/icon.png | Bin 463 -> 476 bytes graphics/pokemon/krabby/icon.png | Bin 468 -> 407 bytes graphics/pokemon/magnemite/icon.png | Bin 313 -> 319 bytes graphics/pokemon/magneton/icon.png | Bin 360 -> 387 bytes graphics/pokemon/marowak/icon.png | Bin 330 -> 351 bytes graphics/pokemon/meowth/icon.png | Bin 348 -> 362 bytes graphics/pokemon/mew/icon.png | Bin 338 -> 348 bytes graphics/pokemon/mewtwo/icon.png | Bin 401 -> 403 bytes graphics/pokemon/moltres/icon.png | Bin 428 -> 457 bytes graphics/pokemon/muk/icon.png | Bin 475 -> 458 bytes graphics/pokemon/nidoking/icon.png | Bin 426 -> 457 bytes graphics/pokemon/oddish/icon.png | Bin 311 -> 327 bytes graphics/pokemon/onix/icon.png | Bin 492 -> 436 bytes graphics/pokemon/paras/icon.png | Bin 396 -> 377 bytes graphics/pokemon/parasect/icon.png | Bin 388 -> 386 bytes graphics/pokemon/rapidash/icon.png | Bin 520 -> 526 bytes graphics/pokemon/sandslash/icon.png | Bin 429 -> 448 bytes graphics/pokemon/shellder/icon.png | Bin 311 -> 338 bytes graphics/pokemon/snorlax/icon.png | Bin 381 -> 386 bytes graphics/pokemon/tauros/icon.png | Bin 436 -> 414 bytes graphics/pokemon/tentacool/icon.png | Bin 355 -> 360 bytes graphics/pokemon/tentacruel/icon.png | Bin 432 -> 428 bytes graphics/pokemon/victini/icon.png | Bin 346 -> 358 bytes graphics/pokemon/vileplume/icon.png | Bin 399 -> 392 bytes graphics/pokemon/voltorb/icon.png | Bin 230 -> 244 bytes graphics/pokemon/weezing/icon.png | Bin 493 -> 503 bytes 40 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/aerodactyl/icon.png b/graphics/pokemon/aerodactyl/icon.png index e354dbb0dcaaaa9cac8a26df89d4e138167a71d8..58c96d57c7fce6c6433c4cc58f8525ab2236e04f 100644 GIT binary patch delta 357 zcmV-r0h<1k1Fr*+7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SElET{R7i>KRKc!; zFbpH%fJCSG|NnMQ7;4iNxa{d&7Kv%pZjv_G%kqnxz!NSHj3)v_?inz#8KJHXB>NraH>@ zR_~VE)m{+^C%puJLAbpH+~MM=pV-)QN!$IXQQwO@0p4|YmrRX)X9IqY=(-;S@oirP zW*3tLwr$%H7ds^^SUmxWrdKKSn5RxZhNX^h=GwHT)wPNS6P{A6f@Q=;U7p13BeSar!wh7|2Kd zR5uBs;NC#|B%yBDF{art4|QM5|GeL8`B&mS{_S`Jl$8|TD$z^c00000NkvXXu0mjf DHBY5s delta 329 zcmV-P0k;0H1Cs-g7zqRe0001qplF?uE`tvdE)?mI1yx!H! z^%}sY1X%e=@wCiw9cn$p7_)emVM7gB1=h-ruZ|JX0Qj0yLWqqcq6$+&RjUcPbt8Yu zF*M$^vG~^aSJ{E~Rh!D4`)k^OTC=XZu1{C>t!5hP3tw`Z=7qcqH_Lr~J{{(v=oLPW zC)hN9dp0oJBH(6H^j^MRI1cu2{J+Of#6%9I7~xQe5e|wARX-*Q-ff5Rb$ bzsKPYqRF+jd!m|200000NkvXXu0mjf@TQh| diff --git a/graphics/pokemon/alakazam/icon.png b/graphics/pokemon/alakazam/icon.png index 6d136899d988ee651e5227763a1d5217fc442a78..e823e94cd36a740de8d352f1e5a02f75810ab1ee 100644 GIT binary patch delta 439 zcmV;o0Z9Jr1AqjO7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sen~_@R7i>4luM4p zAPhu1K_YnLy8msb%7jm560+_=O1Ff|Ha7TuK3}zfH-WtJfA zJ=F-bD>qw35fuml&)Xs>08ru%)b8TSsFt^8K(4JMs1&t@b)a4E+%~z%{Wxa9-un3MN|+Z1yuq}Ne- zvH#2U^#IW;T>&JqL+W3Q1GD>=7|rLQCRSyB4))0o_fs( h3D$hTB0a2002ovPDHLkV1kQ<#5Di_ delta 419 zcmV;U0bKro1ndKl7zqRe0001qplF?uE5dr5C?FcASX3@q~rlo z1(s$>-i9%3Wn?uA43R3lz^f&S)WTxBAOT){wN3K@>e_g)~wM<7AQatb+Fqxjx1;)>Cg#0PoRt`rN52fxaEO4)9a_2?T0NWIS!FzTvmUS zGLnXoO=j~&kkIUnkS^plaMwEECU`%vlkV!SQRalC=pQO?uY;FG8RrDQH=okm>Mkvo zsf<(qvf@WiS3p3y=+g`@tBRTm2(T9*WOiOw1)BRIF*{T_!!Am1w+2+S3y0v z7q#LVG)bAzuJvuTO&fxU!0xluooasp_ZgT~3z?4s09TF24+#6|lTBajx$7BV*aVE4 zFUDY$yB>o9>*E28<}e1+A{&7*9C`yrF<)LepaFB<3}7sWM=KRLc&- zFbJzuSfw4{|NnM8QbI^NX@_Y$l-`D892R@q?)q{u^ZPy!1Y&_@%6-HM!T^*2B#?1@ z?kj^pLKG`~R-gbtE%xcs6-Z(*3hf(*$QK99)lslS zs5Iw5x&TCfvA0Hl(Qbo83kWgsZpRy_An0+>bGPd@4jd759OSz^=TyKR>v0m<_Nb%$ zn=6v>Qj2}x^}qE|Kx}hH3<2Sj~BvVYV};eA*m!v3~J&w&gp==N_HuQI#+V>tz|Ps?Gv ewEy)_KdKjKycKSuv3f%Q0000NHz#11)Y= zEtEMzE(}cypn!H20mAmW%cRLf4dchN(9fsT9}J+2P($g*E<@VJflC3M$Kh}o6;)fN z!};!^q=N_s*#p6*=}--kEntI|WX-o$scy6<_x{;XpNb-@so}F66$i@}cNXG?82x{t zyfnXr=}>aMJ615u_wD2B?%9*12X*_5SfE>$@aQ!WTe2w9ZSUbSK`QG1#bq9K4B(KEZ**`6YB5 zdaOMS9L#CC9S2VpqX+{BCY4s!fx{$hN`%KMslDOQ-}}KZe-+;uRkU;wSo=c&0000< KMNUMnLSTYa8jFMg diff --git a/graphics/pokemon/bellsprout/icon.png b/graphics/pokemon/bellsprout/icon.png index 59ae8d037ed7e014f2dbe322d03e4fb411ec1fdc..ff6ca2c33716e1c4a6f249f313c9a099e2a2f3e4 100644 GIT binary patch delta 221 zcmV<303!dl0;mFz7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Srb$FWR7i>Kl)(-H zAq+%0K$jZR`TxJQWkDlQG@djv374JO3C!Vzu=R_AYUy88i$w7?;kL9ua1zyLM)Ct_ z0a48x%ufJON__&S&wx;j@k;cZfR?iPHV0`#e^un1h3zY3z8K^CD>5)_jt{^RutQiW zQJ@t3>+|A`qv`$9(e&Jow;*?Y3JgU7x|9d0FuGvxGeA04`@+p2dZK_sbvw=A)%NNC mIF!p6d|Z$tWQ#d`J0EZF)pk#lEc%Q90000Kl*?{J zAq+!#NGK90`TxJI1DRU}0$o(IYO@?0V+QUC;jfLzkA|~jXtxM+Tz8UTkeKccNp}MR zjs}%AAX$~Y%w!PBImN|+C9FH(cgUE4q4c3c0m^f*}-)2@&fVf^gE&xQM$U*vtH%PtLCh^B&gL82|lc~V>D8&74Luc z`pzj-xyR97-a2IzwoA`&zuP%%%z8q=^UIZ^0-5giCq~oF{tv#PGGv~B?%0w;^hS9yyB6-upoh9 le++@SU?UKltB{1 zAP4}9dV`Vw|F(eEM8TwoPA@H2Hh>uS@%YCS%r|*}H;4&YO9~(aA88^-FmXqikqAS8 zv=J91#HFDGaTP!^jJV|G^OSUiMj)?wEg^_91V*g=?U1bsAt0<1fSyrC1RDi{5$p)n zLKa|yx+cU)^N_WF1nU~+F492KnR9MEXxUT;QqG`2(4-T!Z=$-p9VPmzTpp@iU&^VK z0Dn`uDJk3+;Qc_HLZLh0_7VJYd|VK|VEboA+Ueo-{#!cG zg8^GT3_Ip)Wa-@NDpU0Z1ivvM68E5+= delta 380 zcmV-?0fYXc1I7c87zqRe0001qplF?uE zdw{4?c3t$WUK0hewk6Kct}ARJ?>x%yq=_MR4iHx6F@Fs6zYvdGnC+$NW+a&lk>f#9 zIDbkCqs9a#a%fxuWV(KDuM&Vxq}^c0g0wPdy>(-OkZHAq*A{tixQ41~tVqg)1bBZt z0-5L(W7}w#HFS*ei8R$$BEu+?m0d~S|!ktH{; zKk$1B0L1XY7i({)$OZ0eI#~3(*=Xe)+_~}iCGX=fuTYm;qk#X!pvlrie29Hr06gSp zo$~?&Z(&Ou7E7L>9kLAqixnyBatCNAEH*VenSZJXhBa9N6JjK8TQuQ?&2~-hayHv| zyU)R8@V)U>(VP>*O^dfzP^OZ8!@BiV35+sBi(7zBR-_M;L2_RD>12W3G%!N+b8u(I aW&HsaY4WVL_x7X!0000Kl);XJ zFbqVAA~{kHp8x;b^*Du?;2`Z~FI&?Jsu{*k3hy}nT>;~})fEQ{PVd7CRiG4C&>BBk zKmkKc)n*PX2Gf-p7SgrTgEioz7j$}p0T30a8C>^9+WTdIiWQof_{)Q=NuL2jXPu3j z>Cu2{y6}K?0_;kEr*6yg07d25WQ?$>H{RJ=JsZ&>2s(h;!Xy$6%sfmNIxt2NZyNu^ z${tp9aTHAb48btla+o8FVa`)+7TY(K{K4>6>XjNe0=R8k19#eVzeo+dow{xe=cYU! zx0peFw}#6k`-E$jZ*A*0{KxC*g3jhEB07*qoM6N<$f@J%rWdHyG delta 419 zcmV;U0bKsX1MCBk7zqRe0001qplF?uE7&WQTtt zkf!)^0g1i$GKfFE*G_hPOpb*@TL%O$;h?F&z5*ucYK?CIC?-!%LhsmB5TQenK2L{? zZQ(4@fIK^Kcs~rC)X6yBH+u_qc)46wAXCg`4LAw{tq&DkENh^zf)Lk0B99xOsDA(t zpXOhT9^-bEszY200~gup!;dhk!%ly!`4I-D`R2#j|-?xPb3>ZlHd9Py=?sedhkR4uiy0J3mU*1Dpep7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S8c9S!R7i>Kl)(CEIaHl4%?FdE28z=as2C>#pgF~^4bCh;t=Zq0{~z6LTEx+ zT3GIya1{iRs8-7n9YKr$RLP!Y%$`7LPzhU(c_COAKm_bS&SeCcLGxq~YhH302!23| zIN7JQFxka8 zte6FutA+bYXYiwx4kSi8KJ~3Z3K<;g@=X9M9U@Hq*#K929}%Y7#(DSTfGB!l(pY~z z9+nQ?+0}(KXGd`$w~coq{bj&aMy_cd9d{KXMQjNKBr+A6=s{FC$anind_U#^VA(Xa zmOPJt$@{jTQw-Qj*%U-WdL@+UOtgNrd2bEdxjdUKK!IDISqHe*0o7Iq7=P1Y6>&On zd=Re#?_*@q0cjT^P6wTJZ>T0Hd zr?7y!Y6p|`pal(o%nFJ!nFSVZ?V+Apyk={q8M?I=4#ASvI)~&w$^Y~%p_;7eN3Ao` zD}%wa>Kgwj*L6CK)Pmh<;V#(@o6qMiizS$fmMy>8N7+*U#}Q|zv;@d6gqZ+2Aq)Yr zBFqHHf-na_Qo=j|k`U$vkoeBL10*8MCqP1nivR@U6d;!u<-;8*S{R|o?cLG<0000< KMNUMnLSTY3Ux_*Z delta 303 zcmV+~0nq+|1NZ`v7zqRe0001qplF?uEzl09kzF%U*|gE>NuVO*ur zw%*3RLRyz@0y#t~;ov<)szrtC5P>eS&4NJ+mIz{v$958|PfObTOgA6%B#n4N{A6+2 zd0G}haI_>30mys;fmto}83nmM4Fb zu^eh3$RyniZGIWqwX*HnUW0?xx6|ignX!*gxKgqKLitm&K!gB+NGkMb9IHcwQQG7N#`l zEKFh0MHn>bLl{6lg#m-Ugn^0Q5r!MwSeQTe;{^T`&r>@VKmC+8v zAP7YpdGiwe|Gyn*rxmbEmcA?*4_h+MEDD|;$3MOc;J_!~E{OpJAi&JZ$TtE&(^Z07 z1P_9wi$q5}P`RZW66Vv$E8%OXl&%27t|CA_)2R^#K&6t4B8jL2dKOn8$v<-;joiyz zS72G96snR>Iobz*AiKy7$UzCM%%X%=5CifM`Bk#KSpeDzNsxTHLwFO~EQ*eC5Yq8_ zGcjXMZl~%WKNQai#FNt>u|QUTY=(OJ!{3V4AHlU+{o!k{{;+okfj=x@{b2=T{m}$6 z>+t?ybC}*AZl~5C7O?&ZfawoLU=Z!q=?~t#Eqb#nwiAOIIVR5vxFptG<6S z>_WFioy#>a&}C7*Xr!V^wIqNINI&Hg20maHteAy|>m1|+PI2}jLQc{A`LMHpeclr$ z?+h#&ZGgZZSn3Vz!oYIoc;tUFm?j!kd2G0k(@iBE z^i~CYOPy*Gcnx6IsY^zcMpn8g5&$whUg;`i=hpE%qAAiL#w9qh5}tlAQW$vd=51kq Y0fs#1kjArV*8l(j07*qoM6N<$f>UFR-T(jq diff --git a/graphics/pokemon/gyarados/icon.png b/graphics/pokemon/gyarados/icon.png index 889943b04f4be2d2e1b2a6d23462f79502bebac1..41ccb5aee2ad3bc30c2eb1562c50f6fac21413b8 100644 GIT binary patch delta 490 zcmV1hWK?7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Su}MThR7i>4lu>hp zAPj^ZF`aM+$^ZYi-2~L2)J~^w$IRV>`Pc+ycUeAhss2(=>l30XX-z)>wh{XiBF zuqyyq4?s}#dd?t!qye=aM@A8=ZMM}Pp6?7Dsz_$eia+%hi{@}z715MUfN@6ep`gz? z4)+Bh+nW?0LN(I?D3x67d?>A}unb#h)K*WL z#DF5SZRE4Y25cj}Kmf32gx$Q+2)y2cCpe%@<0FMHZZo`plLPpky*%6qJQZW7bdfuMGQzEj@_0L%U2ncuJLqIfpw}6;xgn*dZzxlrfM7jdO{}vE(6Bzwp z=EUItkSsee_+KswvrPRT6XxdsWf>D@x%&T>FjxP#A!5Q@{qI0Xn4AC2jiY@>{}VJq z!i@f>%>qP8VgQW(-}6Cf1YYU%|0Q9Z==L^un~xz9LeAfNx3?!m%aGfh=mBj0xAKpd g+x`E1_y6esZ>fDG)0R-u)Bpeg07*qoM6N<$g2F)RjQ{`u delta 536 zcmV+z0_Xj+1mFaa7zqRe0001qplF?uEy_^a;K)FTAmoYz+$uQv+VraGO%(+tl7N%Xd$5Z_?JY4A@bF919KtX{WH#m1sObc| z%@15Ih=jOluUluQNG}~`k(a(ts>%yG7K=?dX zLNjn5(Dh6S2nMM`v*+M0!9P#x|13DZMm`=A7Q7t|07N1mS$B_X0N74G1kCo>R{amE zXr&+fy=0ZDB93&hReixO3pF8$E(6$v#*a5;)){1K!qDi#EINZk9i|KK2GxJTAOUH< zz|!V}K|%*F7E62LtAjz$-v)@^9vRRY1XKA0Ikgk&3@W*pQ!LZiZw&%+CUd%y=a+u# z0}$NC*;V5QJ?p@`Se3Cn7$nLfbKRLc&- zAPi&WR#5!^f4e*>R84!FHZAI*!cO8um{NW(@PzjV#uEX(x0C@m0l4OXA;vYFvU1TH z1)+Dr&J7`i!RY$GGy_#5^nlNTQ3LZrXS`Je43oOfV=5Ikd?}(^koJ5=TW!m@qK^kF znnD$|DuL)o*V^2F(aLUh)1MQrlwI~I>Xs>lpj+fFJ9hnSh^Yi=0%+$#ioYZdk%g=v zNYyB2l(7Y}j$i}=J8jw%#X{uVH76HC(si!-0|Ltw4E$aZ&usZq$z7&K&mWBmR9 zasMkd_rKXc_kY;GB>q3_U#|T>*+23Buz%|RVgJeh{s4?BMTC#s|M37!iwYlkqCWuT dD)5C5z#Bz}C5#iMsign_002ovPDHLkV1nuLnpFS* delta 409 zcmV;K0cQS{1L6aa7zqRe0001qplF?uEVUj32Kd3Umj`AqgxTr*N6+eod3?7$r&ytl)>f67+s)q$*U} zl~j9CVqF#rU@2ad#l=pxj9+SVnY@y;N21w7a(SEsD6(|^)WxZogT-m#o_y}zhx`#} z4>OG@km;whnAu8Tuuh#b_eDmfdSib9Q9lR!;jEzde{6lVbg1l>kIz=?pnZo?8Zxal z4AD%boF2mWCXTi^IL2(d-eC6YhB$y;UcK<(zB=X_mLPFTi~}UQCehHjAr7v4rycLT zH`2!eE|h!AgLSbuxLRtKltGTe zFbG8>kPzPR?|<8V>@>AwyIIXASwWCDY!dOO4$)`Gsb;K z!1H0oeGO#pB)nKz7F!b}0kahV*Ehkt1;M}DCeFji3?SSs!>R;y0w8h5(TF*N)FO?& zVi69#g&D6ESUV_x8=+mx!AC-nC(If(@-9RI@A};cFh~BN5=@XOK0R#7zqRe0001qplF?uE4=xu97rE z5Gz1U3sDN;U^tI}0TBEcHP!%tbOEH|HlnMXOd4U@;UaG7)pcM8nX4RkmtJA+K+QhW^ra|a24kaSTI?+F zB?;-tcUG1i2oiQOc3sD#g%EmRcG&3WDAhH@3mQ)ZA>EK6_!RFe*xVVZLTy4Y~^>rxw;AFU&9<#u_A@FngK#6l)MV wVXnEFYkEShFsA?}Kg3+(;_gR$?Z5f)10Ue(SR1mX{Qv*}07*qoM6N<$g3^MVO8@`> diff --git a/graphics/pokemon/kingler/icon.png b/graphics/pokemon/kingler/icon.png index 34a72990600a16081c6ed9d6f3d700db1c1eaa70..3f9d0b8b78e41ed6730b3c0b2149a71e4a70d614 100644 GIT binary patch delta 387 zcmV-}0et@O1I+`F7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SOG!jQR7i>Clu>WP zAPj_qknjVN@BjbX`pig(OT6u+(lpenQGGcZu)pK@M+>&ncoUIK0TKOae5Zpn3<2yJ zUQ(!_@k1q4#%~lfWszn@ft4H*VG5cw3o>QM0`(O1w(u}pT~NEK=T=53yB`Z`t&CTm zmskR-?kUUyC@!#nD(qC^$pRg{^6ys72<{a2N`dX7G986?g@rpRH^YSym#Yp77uy;Y zym+r8DEP=E_U)qrx}bzQN}VOx%WZWyjS3xj?v`!aL*9ElO4Y2%;MbFOA=9*Px-d78 z%@$&@S@>_Rk52zSKBxb9z{8yW1P^oi_jtIb{|OIs`XBLPFsDDkgSGlE@eum;4G$Xc zCg7oMdUnObW-TeOK=c&5T*fcQ4{mMAb_4hF=^spQ!1TvVGL9{)e3{_BZs|6nm}1$=BBe3=bz z6ZjYu04c~Cn9(VYq<9g|82C(JOVpTz(OdB$mxs+Bcgw2 zDk0V5c|>n7TsoGvVLS~Ek;-(<=(T1nL&kq z%6Xq!*D1i3$_k!M+f%fqOj0DU-0>~Unp!(vO7Hi}-EEt3e~;b&Zy(6E9W`!8D%W2{ z{KCV{0<2Ov6I4hnlu1U@6Hp(Zq=tW4@O>DUTG0fshS+7Mpt=Xek}jQb0Nn<-AhF~H zg09t&uISL^9K%fx77gCZOfXF~`ugaQ7Nxc)edJ8TOiG9N>9A_*XxG9Obt zRcsOC*2sGO! z(qiQQ|Mn1+Rt%V_wljdE4x7?9{uBUUPws=h9>)RW38oK*_YX<{I3~u8AT9KL zD$y$^BA;+k1TW>0(UPemRXr4vJ?AaV`qbJr;g;Ox=^wNIJ}i9W>`j-V~dW(1F? zElqv>laSl1EU=d?{LngG=!K^~^CAIw5q@=|FVY1X3&C6_$qz?!}c1>jj1w300000NkvXXu0mjfCw05z delta 384 zcmV-`0e}A71J47H7zqRe0001qplF?uE<}Ggjm?s=PQx$|hHv!dH-Q00M&5}5Bs|(v z*LY&@01x0O89Ff3A}_(zR3(A|RgPrtY{yPAu);}glHdRN&i5JM{{)ltCjg{~g3|b+ zDqy;b22C$0NUcQ?n80Tga76$g(n3@K#*X$%4gk;l1}&ei=(x@X|uo&&!>}VN(#8`_S&>% z9-IEon3zLyboE>{`rM1?y#@Vnk>>PC$n?V|c;zzv zSVn>yC;F+byBw``L_ZyfA6~pC`so@L`qK>fiavI_q%UDjAMbvkKNBK-ky9dBwH)G7 e2#%ccd;9>x{^J5E(!ebM0000KRLcqj zF$mlsn1kT_|KE0WTk_a!pip{gJ+zBXMq_l2<8N;mfPGwR-6BxoI{_3SOX{lBZ6t0hX}@bph1v`#^KCDpW!$`d99v8Jg!Oi6QtEAfCytk&zUNU(k?|% z7^-AtaV{>#(z~*MVJ==tA<2_f^>I4ff|R*T*)@@|br1`mMn}~7Wl_`^j~@n^Ndn=+ z>*Y8E1w&Hu52ajRhrBGoiWz*3fTd+qWjSR?JL&dA*pI{CK4`zS{at*y{Y@V3w*Ms$ zi|scX;KVJ8nPIWWCEq&{5UZ+&aBA^%4WN%Ynu~x(9%s9^fSJl%ThzBrp`v`n^ z1i%j^zMHlTNWt70vEL=YOz8?d1;EC$O~iVhQUZ&hDqDe=cq(?rf>_b~xdF6}`?G(Y z+aZ?#QN8C}0GnCvzUcAPJ8lE(^7G*~aID*iWkRSOVQkRkLUV#sP!EO>G*brA0vh}v zn!fDcUJ&J*(m(I}3Kl7qUFdxg5aT+#I&Sy4+^0YBAU-tW0L1hNyg1n79QI$Q09Y99 zc9+F($I{hjY3DX8S^@B!GISPFLhyFkFl4Hh6+vSPs8!|dikN9~2~s$Twa?rY_1(== zzWNP@Vh^~Ip3{>6vP~GSO^@G`!=fBe99Y}p4a>w%xofMnCdO_Hazx{+(e!;c{RQhU o8Sw6pD5Z?>*B>#i@xS@w7sJ!jh|T2NQUCw|07*qoM6N<$f?ILFpa1{> diff --git a/graphics/pokemon/magnemite/icon.png b/graphics/pokemon/magnemite/icon.png index ffefd1a45b9e50bda43a7f8ef42018efe54016e6..95b81cae03d1139804566a9bb7958ef968c43edd 100644 GIT binary patch delta 244 zcmV1)~7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sy-7qtR7i>Kl)(4lmNMit{5TP|yZ6N`3 z%pVE}4^ZTsTgy&#?fqIUAm>h4j;+eevLige28P~XK{7(3ZCVugLBlzRnveV2)54_YnxRtm2zRbL^*|gqf@c6U4#H8N@t%)gU+B-A=g^{ zM>*56?*IS*07*qoM6N<$g3~T;B>(^b diff --git a/graphics/pokemon/magneton/icon.png b/graphics/pokemon/magneton/icon.png index 733049b1d68e18c9e21b0d5547e5bd3a5c813311..bde234ea113243d3d81d3323ca319a2a0107b0d4 100644 GIT binary patch delta 314 zcmV-A0mc640)qpP7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&^R0Rc%wK~zYI?UTWd z!ypVq14t+bnEC&|-LausTAWs@_O|h}oli}}a#1I(=&+?`mqNdN!< M07*qoM6N<$g6YzX;{X5v delta 287 zcmV+)0pR|F1Ly*f7zqRe0001qplF?uEFbqX`0u#PKjGmwa z*BUuXPT*^F%b~IgU9y&LlP(=e2@`fZ_F+ib+MMJ2mP zu<{pcc@cs5c1d+{oVKiSuvXv%1bQc@WAk002ovPDHLkV1iWqf`$M9 diff --git a/graphics/pokemon/marowak/icon.png b/graphics/pokemon/marowak/icon.png index a9738970562aeb62305736aa6dfcce3095e92da2..af56d377c599bc95cf1c497a0ffb7f02baa7ae42 100644 GIT binary patch delta 276 zcmV+v0qg$C0^b6V7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S-AP12R7i>Kl)Vna zFbITgkYMB9|7{C)nxr;y)uqZ1hAe!X`BAQvCw>gzOTH4842Z~hO&BqnO0MJp8#DV$ zoGEz^k?xTxv=_FZOu!C-G%sphp*o2&O$=2HfWVc!O;s5Q(|Do^`#vCS`U%7gm81Gy zKMKSeqqs&|=S?|t0OB|Yi|RauC($6U)*yx{(3b~TH0pqfOh6;VJQ*rB_K3DVnE1g0 zNV-7(ddMs=u=zD7wI^;IkAajs8c4G9!$7qCyCbq2$ig4m39kHMH;_wz*bHRl52vR7 a?hh|V_lLx zE01C5)^2!%x0Xn-K?G9Sa8ue4Le~xz-fW#?$GRZ+qu^Z*A#1-N;><^eI%5qRYETO0 z=qLykns5Zfk;zk6nBx~99dPL)OzIx&IzVNVj-i|i+ccM$=KulB+e-OYd;118!+-w0gT&bnfPUTcXqgry0m|o@w^}Dm7f3@$! z9wiPZOyvtR(dx${%Kl)(yv zKnz4J9wa7Y{{L?~iO_13RoYVz1_W{5PO`f=({$JOg)3cg3IT@66&Nva0|>Zx1ed`@ z9%e2*z}2#@qNG}Ygb7Or25jLT4rWTA8I%T45u0beK()HS`B`U>(9NU})Qx~~Bh*Ej zE+j(cL)|}#*eD%-xIC%?TyKKVQ$RI{gQo7egLZ`YZm!wGs=m48eR&*3t4j`HCl@~G zzAwMfN%*;b*PqlKAU_01O^{=NbU)A`K-z!+mREpOAOggfcYu@x*#}4lL>(axdkc^Z lh~~I5ALxzYh5lcJi;h=00dA~!UeD5{AAjkd*exqC=|C2ESl3yU&pRab`2SK>-$rIdo|g*SDRn; zuJz)9nJk_6x(8-4>pw8zFuTS0yah%8RqpE+7)XNt0t1xdFQ{u>w8?!TLxg;)o}Z5^ XY}nJ{D3}!;00000NkvXXu0mjfjgNr; diff --git a/graphics/pokemon/mew/icon.png b/graphics/pokemon/mew/icon.png index 6e7175f437391b2c2f68c247c255b6d98b14f822..d4b6ec9a72cec9ce5587d7f7bab8d189a3f7f338 100644 GIT binary patch delta 273 zcmV+s0q*|N0^9CR9gxJ zF$fzdltsbZ|F-L+^MI-cnDIBM#Egb56a8{a9;&;|%ax>u&bmWlq@ z)%t6wfVD}+fVWw2%@cy(C<}8m*hJg}PDKVoL^*L48GgQ6^EnJb{cRVie9~u|ch~#v z-xH)?KkVPcgKyEs!?LECsvh0@4DI7zqRe0001qplF?uEuvn$F zlh>gZ@FQ#9skjVW`nh*gH|FHJDo<<&L*nZY@%#-i-(Dn0hqLjcEBc{)W~4|G;COQ( zpe&=#sYj2%m~t>isOvfhh|XXWswvNy7Ba7eC{Al^sO?(bb7M4H`j`3zFs+fB76nH9 zy5!D&p^5{O17_rYw!m!Tbm_7IX5&d5Fq$!t1x7Q_15;`Dz(DyqFdzMX)kGcCi2e diff --git a/graphics/pokemon/mewtwo/icon.png b/graphics/pokemon/mewtwo/icon.png index 8463a04ddc33cc2efa1a315acb06bf6d7796a9d8..b0dc901658c6931d8024affbf60ab2706eabfcf2 100644 GIT binary patch delta 329 zcmV-P0k-~;1Cs-g7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S5lKWrR7i>KluHi7 zFbG6bvBk{&Z(G1gQ=4(BNR_%NQoNZlpM<<^`^WtNKInos7jZ)$03>bh*4crFi1?F& z>#Z1EQ#le)y+6gKk4Q`a}FzO za60l{j(ZV!ZN$o8VwZ+((cwS78u$1?`~yD-K?Z&>f(-m11R40j2r}@4|NaL*j3egc z#{wWHKcI^gogX_u2ti_<-vCnPm;h1a{n00000NkvXXu0mjflH`fR delta 327 zcmV-N0l5B?1Caxe7zqRe0001qplF?uEVAQ3;_9oi+e!c5V=Lm z+ap@C6jz_NNW0{S+_E@WcNnsL6om#cGPW^e%pWeuCqUV7+gL$)Vax_>4}=R|+JW8` zU_jU6Hcf%p0NgY+S=<}YfR@eKHBX@WWXs(gdZnPfL!1EEf;F0|cM4l4jrB4Ra*2QB zOjWQ(L`F{9NI5(?TyG=Cv7xie=oI4SkQnl{SB&z3ee7g?`#1yLAZWe_IC=n}U%Y@}kf-pO2Y`LK z#xMy39@orql8mAkVIcJoeh8ywx-c`4I(Q0GRgkAJvq75|VYEsU=0k)T;s&m97UtLe Z_y#ix&7cm(M)Lpw002ovPDHLkV1j2Uk<0)9 diff --git a/graphics/pokemon/moltres/icon.png b/graphics/pokemon/moltres/icon.png index 99affaa0b2cab8d2e31db51e44d34582ad672bd0..70de8545068fbd265d59066d42e2e26097e9eb46 100644 GIT binary patch delta 383 zcmV-_0f7Fj1IYuB7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SM@d9MR7i>Kl);X} zFbG5=)xaSV{Quu}7$-8eBlXh5YE>Vq1||bWc^t>@eDTDmyv2hkq6jo7DwZ`6qUz9$ z_mH$ZK!F$}8HnJosabV|LLmv*G91dsNdQTjXck9ar~IvO)OGxAG+VEPJOrLf@u#_j zXQLy(c^s@vg|S_K-2`aSo3!38s(Gw^x;Gqmv7DSvlSl)!|7tKlor7C1dY;|_0=6e< zVzmbHXBLPtm&pYA;3;zvDS`dcPodxWHz$cYX1?cq;#@aCEMKH2t>$+$DW2$7z(5|l zB9i_}4%zL5U;BfGb%F2$1(ayx!aqtE_t%^FD)A34iuI;m&i#;;=(A0N?=$Zkch^-0 z{$f|V%PcPZQzMpWPNN<8_gmXir{YgC;TJRB1OE=M*Il{b-%FMSvEknpql>4xU~_(0 d0e@&gyaCvL7G<@!U=siU002ovPDHLkV1k*%u{i($ delta 354 zcmV-o0iFKI1FQp(7zqRe0001qplF?uE&kbe)1dfUmqRMRnq>vwLMr@}ZZ z?}*|J!DnpDso1f${a3-c%j?gA_if@}wRF_YxLD}3=`)PrpjRL zWIY8OC=nE_ebYD{6}n>b&4l&)&Gb%?FhGr1goMLMt0x=)&c^1QMI0=I-R4;n4g^A` zcQX!Q+1K=L#vzne_6dhDbbMsPfs0oli2X|Z07kXH_q}!S<^TWy07*qoM6N<$f=-sN Ay#N3J diff --git a/graphics/pokemon/muk/icon.png b/graphics/pokemon/muk/icon.png index f56a9b367d8b0ec0c44fe6487af47ec60467a042..3168d1be464250b28d69e8506147a8f2fad78528 100644 GIT binary patch delta 384 zcmV-`0e}A61Ih!C7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SNJ&INR7i>Cl))0i zAP7WbV^28j|Nm`4NFr#`bEiA)C9JR-^S13z1<_-*iEb^R=DKm9eRqhM9}SwKEDb%r z{?;Qrz9%K3)>JX(CN4-(?qiCT;-@p7TQIxy*_Mk7?yGIAKfz++go8^5%pZj9<%~u!pnELAFb+R?cy(jV0SMf*s zaXfg+J3MUX2G@9q0GaU+0J6Zt0w8Hd1jvMk3=lg|!~r8;Kn^}2P8a~bFf0pbKPLX1bneHqNUA_R`> ej)}5asrLtb%_xS8SA1^(0000at()CL-XlhArYtmEq;IP z363{S5fa+|=^Y`~Qe!R>kM0)iUe7Hw~ zu+t}zLXdG-xuB*8lHL)(YBQz{7R85p6Y4zU7*Dkv~+yHi&M#x*sK z0+adRa~}eX@ByqI8JLleu@qB)8TlBu6&0AU13x}dU@{+tsI~wjXJ0I264VA1Ky=}P v2YLCM0V$Q8AoQZ10Wo<6aSg~7{{qMlmZexmK~?Dk00000NkvXXu0mjfgdnUb diff --git a/graphics/pokemon/nidoking/icon.png b/graphics/pokemon/nidoking/icon.png index 377cb6672e543b7717395bd6c426d7e5f679d98b..93d0b5f80e5f8735ebd30285daf5fa0f9dbb4719 100644 GIT binary patch delta 383 zcmV-_0f7Fh1IYuB7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SM@d9MR7i>Kl);X} zFbG7g;G96r|Nm_V>^M$prN^$+jZ{lD4+dyDrTowXd;;_&Rxlcn5!edQN+LplnJh-g7uFR=inxC^!|M-Cz;>k7j0<@(#M<{J- z!(b2FezA#LB!x<;f;uY#SJWmD#{(_q6~7B1=W77#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S#Ysd#R7i>Kl(7!O zFbG6F0F%r8|KApHYjxn6ZFdV#nD5)V|hO@u4rP?5euI4-U# z{pS_X^40rAtU&q_O=yqsQ>;V;JgSKFb7T`KSNjSxq*#!L>7C$&ZiXR7n)YUx!ByTP@KuE%$ z0AYa*kORdQKo|!%Ko}r4K>9I$0U&q>kWAn!`EUnFzYhue`adfG0000%bI3rn5vqTh0n||AiVkMv-6`z^mC=e3N3TXCFB>F=cYJFu#7k9aYDM_ zJIx3rj1G2`#&;>H0ZClI8F4;9Vu{D3cL2?Hx7Rbg5Ln=q3#D2eYeQibUu m@e~I7uL#5M!jS4G{dfQ=W`Ao>!^-^t00007#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SGD$>1R7i>4l))0i zAP7W*xwHTOw`Gw~G^U+)dTE?VbYxkTn73_z)bK9e-Y9-3z*-3D0-!aM0JF~K72esP zd52jbiikH?XmzoWFyaCB(tVKmA!uNjitaNA)NOrrM1NSoCpjfP6oHr%*HIh-Zw&Dz z9N449!q?o@W5P0j@J&mP+mdSQ?|US(a5;=UGMxqzr$=~&K)f#IC|Mh%Hg>7vXDKI# zrXEMU7KJJIWt`?o62H>(`rlszf+l>DLK z>R#WX-IX7MXvvQPnXmbgJHO&b!NZat2Oci?@x;RgKMEd6&it71aOOw+JsN@)KT!Cv z;K#^^B|q?rA50neF!7@U0we7UKl&M`Ke+H?B49aI4u1`Z2av5A{cVe_-T(jq07*qo IM6N<$g7{3Sg8%>k delta 419 zcmV;U0bKsH1MCBk7zqRe0001qplF?uEV1b)Zs0|{v9R$8t@0EE>zv2l^{NWp(| zPt0a)NXyc-)K3qmrTKT%P`TeZxdq}D!kP^nj#{!XnpcEHl0E{29g@x-atQ0b^&ybz z9s#Ykj~nXV&dh#9rfz9Yq_M>lT(6PYeDj~#((yLxZ^B~BFQ0bHx?YsfcapT0DB7<)DATSGjuhKoS3u5N^ob3sku78-^%0hlkrCHw*!T z9%<}j*KKUyk-Iwx$%f{S)SRCmK}H+YxN$uH>^wXXTlepV>RXMbEcnpDM|hrmr~}lZ z*U3lAYYIMS@QT$@~A`)`k!PCG^-F;v7B3n>LJdZ~dnL?E5*#9f2d}oHqngN-^yKQ9?Av zZ4}@DGb6`k6rE!x(tchMD6@uWR$Vm%KwzsvlqmD*-rD3nNQpTm>Lig52q1mF`bv-; zpqn%Y6dB*&;%Nte6ha9>G7w;k1V|t%t3cxt1zJ?00!%9$I@bEeE`G`LFrn=~E-d?R zMtI+MKjz@lCN&VFc63D3Fdbg*#k@( z4H_;Q=|H6d7asGm_-RHAHdGX_R~bsAfyGiITWTeH`BSGpzrl7=KtBD>vhO~CKVKpi z;BvG)@Z5ZIVBS7B_%^+bc~{(!KJK!AuMU^yWsOAAUJYB5fH)CpLi29Zr5;G#I~9M^ z<-8`juPVe8Aab;im5+D@ojyhP=#^`ih^VayPe{^X0@JxI$fH!2cky3N;@H z+-WF45%^aXi^qv($HDO0@W|P0ISA`w(-}ix!c2bT!pweT!YqDd!YqF1n=p$X{wB=q zN7U=G1C4%Eg!1YK_QDyO`URCy VqXB;aeKY_7002ovPDHLkV1igdl&}B* diff --git a/graphics/pokemon/parasect/icon.png b/graphics/pokemon/parasect/icon.png index c6aaff12d702bcb696d4ad28da9d4bb66d1e60ed..27b8e098932cb01dc43e5ad5b3c40b8c3f88f186 100644 GIT binary patch delta 312 zcmV-80muG?1A+sP7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S07*naR7i>Klx+*c zAPj`diUuO&{{O$-MQu0h%V4m5YCcHeE@z7RY};Mm6C z5FqUc%r5|`fVdFkc#x7YaWG;QGm?vxJJ%M=0$cyP5;0(ZE|j_g>5?&%Na(9hj3bpC|6bpgBF=>S5twcUCa3|J4%-QsphjSD zTl2;6Is$W#sJq06kA)eLCqBlX4rnG^#s`!-=R*XS^D!pnD-(a{7sQXlAG(A-_y7O^ M07*qoM6N<$f?~UrBLDyZ diff --git a/graphics/pokemon/rapidash/icon.png b/graphics/pokemon/rapidash/icon.png index 92dae70a64c0d8911ff899508ecea3a5fdda41b3..a15a0a18a2071cf16601f0011371b49237184d64 100644 GIT binary patch delta 453 zcmV;$0XqJO1dard7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sj7da6R7i>Kl)-Yt zAPhvEAqQnZ+W-ICY9+A2vD039=~Rapvk!q}vfK9O0@ybD2&kEULwJBAJ9EYvh;+b| znK0=Te7zHx-ZASc@gqE_k<4+P-S{TpL(y>|69g*vcBMikD%B)(Y=LTAUj@vWM`2(b z0kv9X8lQ1l0*6e0H6$UP8k$S7)QD0`Db*2AUPMZp!~{xd#YjjA^aPM-o~AKTq`F99 z;?uQ;T$#eAuYp`Wcb6ofz1A(y0}~#$l(ve)2A}Mvc(_HE*1@* v{b9Qb5*ptm>ytmc+0&$Vf4Dc0U-E}9tPvv;er#0=00000NkvXXu0mjfnwHN2 delta 447 zcmV;w0YLta1c(HX7zqRe0001qplF?uE^6BHKi@dsO4;rhSWwS8C)FWO0q@dtff$a|J>)h@6OT>;O|xs z#Z>6(Y$^~$1)<9dYiO7jstlABD(sQw_LEt$US1|d>j$z1D{>OyE6#@c_5 zD=kQ7O30e>Rij8JDdonLhP=EU}}sS7ewej$*;&^q_|F0gi1tiGdt%;X+aHe;0c10a0PF3yWRg zRFYKyP3E%dx@3Ao8{Cbt0V4;(&?fXD!@OkN3U^?Dp{OriL6KWO3k)Z!8F(3hX?g?9 zxJzeX#u0pAOdB7Vzz%W-rW|TUU<@CH_0SfdmX9hQOf@hMhK~(%ZPR|>gS#tVS0f+Z p>5=UVl^1*<_hQS( diff --git a/graphics/pokemon/sandslash/icon.png b/graphics/pokemon/sandslash/icon.png index a1d72a1ba7cb5d5908ba16b215d57bd361baa682..18970df1555ddbd1c641c6d501a9eed6e61c0155 100644 GIT binary patch delta 374 zcmV-+0g3*t1Hc227#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SK1oDDR7i>Kl);X} zAPhtkkdV1}{{L^+12h8TWOsY$sg`J@%mmv|zvKAEJAq#$6h45!2eFq>GXSOB7$~W& zNT&hSHb8}$f+P^FRZ%Nc#ljn!UcqH*ki=fsDqUw0#pM9MwGftA(0><0SHXqWjPAN- zXjW0G8f;+SYBs}v*xywNay+ZAhtTTLEKXX0I$L#6fVPD@j><4l^9 z41L)F<2X+;kkQ+Ws0NF>=1Ekln=rch2e6ML%fRu(+h)s6@**5S1STFg^^zxcMLaV1iDV2R<}{Jn&%<=KhbxY99H(V*km9AAI>5 U^#NHlpa1{>07*qoM6N<$f`#Lw0uMebswRzi636$dbO)b3Sp^Dpi=qmPikUF`A88iHmCoMAVE zunrIgsB??MYdzW__qdPi*!G;KfC<&AmYIX0kb8rV^*FNrGaOGnLGi4tE zOtXl5aG+16_i<1%aiFE~ zKD;0i*Pv$h;RS7d=>4?uLA{_22U>n@eK7N@k8jj_=z%BYx^e&j002ovPDHLkV1ko> BplbjC diff --git a/graphics/pokemon/shellder/icon.png b/graphics/pokemon/shellder/icon.png index 8d74f82624c8a138908183308884952431f237a4..8ffeb3edfa95cf44487ddbfd4c8f2cf5cf4b5787 100644 GIT binary patch delta 263 zcmV+i0r>v60@4DI7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S&`Cr=R7i>KQ(X^) zAPjTyfdt6<|NrfELo~-Y?(IGj7bTMxXw`1pT|ZaA*_`bYUP_y1)7!u(@a62JOc|<> zT19~A9#Eo$IaGl6h*!sJC+R@ouIiVOIAByk1*T6ZkjwcHWCFWVB`J2wRHPAfhn-SJ z1*WDGbq88R5GnnLU(bC*yJ9vpTNux3sMQdVrJLTkee>XR7fh14Q5_t7MwxNE;aamX$0^dfEE8!m)3z#I;`zchj{(7 m4)sxoc>R+OaUn+?eqA5UCd2+*X_OZL0000KltB)K zFbG6V3X2B9-2b*8S`#a6{VR8}F=3vxD9mwuu?^slPLBjYM2P1aLlqHbz=$&tuRtIz z*dqam6slK1lwl@hy|lLjsgSHYP;i!yYY5H2shdaW8HjAx3$wXy=?YyIMTrJ1>jMxv z-%f}x29=SZ5r8*;1?WH!-2v~)FQpw(CCY#+Y5}Nvhcp2}XfI)<7EF2rBBdr?OY#*u z(X#zhVbWWpF((#3s>7>U@foQe0qjN&4X}raMANtOv7gj0mhqlHw9JD)Tori<~ delta 307 zcmV-30nGk_1N{P!7zqRe0001qplF?uEW*S z@V)tvvO0?hbW-B9gvHWKD4<^=<=rn0uIF#s{x>dwAB_=))$ zgGDTjDHZ^>#f+#36MiqWnN}WOGlb7Pw@HMM=Vcmc|9DP%0lfZ%zf(W-gPYWkQHR)% zQHQ74k5Px%k4XpmrUR~ZNc_0y5ON=Ni4MV!s}BFhk1y*92zSmY-+2H4002ovPDHLk FV1n(pkwE|e diff --git a/graphics/pokemon/tauros/icon.png b/graphics/pokemon/tauros/icon.png index 08975b0bcedd9bfada576131ab88bf1dc730800b..de4bdd330d435f7d221310649a61c4b74b9f2a4f 100644 GIT binary patch delta 340 zcmV-a0jvJB1D*qr7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S97#k$R7i>Kl);k3 zAP7X`C~&j?|8Ex@ErT#QZ0%*MhC>eF0TR=FUElb10Q;E(4fBx|V-}|kfbx2`zi=d0 zT4NF(sEVNXZuyFL3*3gF5}}g_3?QSAV}huQ1qREwO`eN&(FW2<10oz&z-Yj|R%)JJVR)PFk6ss6-ay!sIx#;M=_ zTfjMtS3ghnJ0m>QFF`$C{n0?Y`V)U}>d*aQtDiX);8uS#?hhAm%V!b=uLFGY2XhcS m_=7dghwnoy?gQYsKaC$Ip%hSF?r+op00007zqRe0001qplF?uE5dr5Pcp!;_Y5?0TE z)6Ds2itl{_j6olZkg+krIw(Jd)l9qJ9GiCgLfA~Zp(>Fa>4d=r18@{J$o6~=x z9pdqE*CGLk^38YBq9U*>HmYiK0xjmU3Z*2_pmaP?jU0;rSDZH*2sGu#6~qMm2Z3T! zvk)8JP{nJ%5G;Z3yiS&2^*e8Cfm_8UoDAwWMhHy?!B%&r2)ASqMA-?eFw$huvb3ddp3mqVKY$c4p^k4e%1HrSa$7<9mbpQYW07*qo IM6N<$g6;&Ry#N3J diff --git a/graphics/pokemon/tentacool/icon.png b/graphics/pokemon/tentacool/icon.png index 5870f50b8ec9a40b8028accc708279f61ae62ee6..64a9ef364532259daefb064464b3ce3eea6c9226 100644 GIT binary patch delta 285 zcmV+&0pkAS0_Xye7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S=1D|BR7i>Kl*tOi zFbqV!fRGnF|Npm@RX3zTwl6I`G$spV9wXUg6;qvilT}{kMxi>_loCTOgFs6nBXT!; zBZecusm9ogyaVujAq*nvL0=7o@V+-DPtkn?Ut3VILk&X9ZMHbRqWR@7p#`@@u#f6g zE`-q5|6Uk7UzlwA`1f_E`^V`%h)KFn#3bDZFiZEdX^|%B)&YW7W?@8Ehl5|mALpa7 jEUtb#VmBV#XUD?>{(}_$QAcD~00000NkvXXu0mjf7h`%= delta 281 zcmV+!0p|Yb0^F$%&!5X=vjyx`y-pbyaZ zq_FW9a>7Ac1#1y4ECfGblj0yx$z6nyh-5uuVm8~@2DdqGnAu%sHV8&uXxV?C4G_30 zGvGW9CXJR9c$(ru0Z^uxMMMK9y^0nDs24hoj+Q7&qaWvO%qao3C&4qywC^0aOM{)k+`~=tSx=)ip&IirPAheb4v6S_}>GN@h{urpz_S zWyVBu%0%4gQPh8=-)v6PZzweV2B7Ktg8@g=chaASf4&VM48`yqu-OQH-$#zfD00F$ fxnuw^Nn0<;2)MMuG%&CL0000Kl--WR zAP9x4CI&6xy#Lz{PKV*=M&I!dK^!D5r8gykTbwccL>g`a;de_mOyR# znd&A9Af}T6XRX2$0%{3zt`=FC2Lg;MK{g`g%*1^sAOlDP`3mM4V2}tE2Ws_fJy4X8 zWL2=!?GVJ04bb*~vFfc2(=D`@RTtvol6C4Iq`wIu2&hoe(9I#}E8-hKj1mJ-5>m45 z2r&+Nu%(yfx^Ex8I-=NOFD~#3(l@EqE7>i~R?8Z|oliZ!GqAfA{)o|Dk+A6fE}NxPP$!L>xcBul;BH z+L7G;y4&rK+28)EU3xpVeLr>H%g3=jzW6h|0Np|%9Hgt1DF6Tf07*qoM6N<$f`zcA A9{>OV delta 358 zcmV-s0h#`+1F!>-7zqRe0001qplF?uE1pw6o!2R;T*uBK7cb6 zI&{fxG-UBLYzTO5LLoyT6bI6+LrFU$FR! z&D~^@>rl}Nuz1to4X*(m4^9EIkr3kV;I3J;F%Yk%Yt)T5I%Tn_vN%BGmm5 zZAA=XqhfRl3Jel*Z@5f-Xt|rX-1AcJb#U8nbpV~|(6gIqb%^}-TOHiQ1YQTX`~fMe zL+JddkKm{S`E64T@roGmfE{!oMRDD!jFCEPnf)opH;7ChcY&$GX8-^I07*qoM6N<$ Ef|aKl*4>1X=v{g)Njl&my7EC{#@nPZD@1$05ShA=ur)9(mLFHz z>~+FY2pd?yhJiYDQFH-s*cJ18rz{1hP)f`?%zW>K;+C`x4G8oXr9k+*I;QJPO`V%SXx;=)}VqJHv#(@XGJ=b$`qSV{^f* zQiy{0%?|l0UMqIDFpLp0)Yb#0x23#fe8MC4nGWm6b8u*fm8;e h;fG?wKIR0XJOFJ54y7i`LJ9x?002ovPDHLkV1imZc4Ytn delta 271 zcmV+q0r39j0@?zQ7zqRe0001qplF?uEtfb+sMOKTH~Ja+d4*cX63{l|Gg0up7DXHcG21=d`^a#F_~|G6z?wHe!c&0Q0TO|F z77SW|4c!D>1FYzfORznrbYkRkt*LO{Ll#$55X~SPhpZr)NF72}5K^mQ2Lu>3V(Ds4d8ZQtT zC)3GwlEX002ovPDHLkV1h1Ud5Hi3 diff --git a/graphics/pokemon/vileplume/icon.png b/graphics/pokemon/vileplume/icon.png index a3cb2b0b59a050075baa9bf7fcb1d65c6edd5092..3dcf11ce3912894ffc6924c219ac0521c7b60985 100644 GIT binary patch delta 318 zcmV-E0m1%{1Be5V7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S21!IgR7i>KR9z2* zAPgfx793{#|Nr(nP@{ZZa=F~g*#{)FbZ*f)_n?Iqj7d&JiKV9j>3t#zK_vOawL~ca z;F*J9?>*lX%FF^RO9;ziJK~!{K{Jd^f*s7T-YvYHT9Hy9aa)2jAw|f(DuI&TB(h%z z=x#yzkcAIW-KUy=hIS!!$7!RC^I=mg81b8cq>%u=+a|X36}qnAGGbhN7I-l!0zA43 zXkxw}11;oG{dg7*< Qi~s-t07*qoM6N<$f&wy$Pyhe` delta 325 zcmV-L0lNN(1CIlc7zqRe0001qplF?uEbEG@rFn!5fevSI2SWx4lC5|Ud5Ka8PPrHgCTR;-BVF4f? zqCZv4+)mo!S{~W;tK?=zl^hh2sr3t9WmRll??{x+Qlj~z6=)?Xr9zPvM6A@BvMPVU z(Na`Nqm+#8M2B&)Q5O<1x0X3#iG4i`*|@{J7ju_P@F~dN0l>oR#SU(LL9jl4*5EAX zrPjK>bAo7JwchEa_sB`tu-9&c@At4^F9rbfdAh>h<>xS8g@S0K|5?G(g#pG};hOB00000NkvXXu0mjfn=P5M diff --git a/graphics/pokemon/voltorb/icon.png b/graphics/pokemon/voltorb/icon.png index 551dbf281c4b9ff65c99f66baf812fdd2050fc82..f0113355b0b81df695a1c5886fb6b1819baa5a22 100644 GIT binary patch delta 169 zcmV;a09OCz0rUZo7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sa!Eu%R7i>KlR*l= zFbD*Tf(HY;|Nm_@>7@{JEfnWEV~~VgSMysK9JTxKI-!r@X68jfdjhk4!I)isA5ahq zbwTCyKoxifgycEfASaco;bp%B)&eMeEFnlliXaMAk=o}~Pknxkqi&iv{k!{jf6fg# XdkVt@hYAh=00008NkvXXu0mjfdtpLU delta 155 zcmV;M0A&C40pDE8T__^_t9PYk zeLxcU1{6rkM;6Fhh9bbPmzI~7mWI&7Z=d!o?-{bd`n30t((;f5o~79vr#(Wl=HIil zw0HVQwtUum_f82}fZy0iNeS6u4F8ps&^?339|dS&H1=r-0B5;bM>N2xnE(I)07(Z$ JPDHLkV1jQwM4RM~FC zFbK5bNM>UP{{L^w5wF2<(@K4)v`DK>V1hZulhQ{Tzz^})t3y2W{mgMT=urRJF9DoO zo{4CEg!zeDtBUc)?-H=TS{c#;f-16K-4Ye65rCJQ0UG6Bj)?AV)N-b*Pp(9XTW-ma zIgZ!?)|ddYoUf&SNVtyp3ux2NvwSMeU>;rQ@L)U7%7)sYLXfWU7=Z9RkK@RAFba7} zd;s{NllT$0%sFu9sZ@f#70X1WGyzouu#wxAj7(7D9wmw8b@Sg`MuY~y|nqg(}mb8ti--w-XFxQ7=lGoQGi}`Tb+7Ls z`Hg@B_s#i%Ll`~W05I(aI#bsP)Jz<_FgZG;bQci4z5gp9J^r1548U4ItcPa-;d}Kg zAd=!qKvW*?0+QnOSO`d@%tAoo{{A8$rUza?IN?OXARwdnJK$o>f~6DXCV^Pokm33Q YI8-JoNgC1(*Z=?k07*qoM6N<$f)v8cTmS$7 delta 420 zcmV;V0bBm}1MLHl7zqRe0001qplF?uEKb05eFQ8#WaJd@l{&SXQx~N}BE=FtADEDI=n%z&1;60<@8^TDYku-< z&efSxDpicjcrglm5OKU5)Zw2CxK8+Ni*QWz*1K5Ii@tH*R<;RqVR{^E0H~wT;<$gQ zz``o->2VDG2Y5H#Ie}+-g`&z{3Zf!j*b@*Sf8&htBcA zzk2?9d%1fx-@Yc-SVMQ+O>1VR#{J}c_ozE*AJ9CRCu zO7XCp+q(7I$21Es{M0e&$9S=_m^y!%Vy47=j5&qOGGV-#kZrCM?CRg2Gs2Z;YB~5U zmxCfn=EMg@sDfq5qEM=150dtcO(HNv3~_V|8I-{ O0000 Date: Sat, 1 Apr 2023 07:34:59 +0200 Subject: [PATCH 053/131] Forgot to fix Venusaur --- graphics/pokemon/venusaur/icon.png | Bin 493 -> 489 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/venusaur/icon.png b/graphics/pokemon/venusaur/icon.png index c841ddde4fe57b5833b98dbe10868839264c683b..ce3b2290ac95bbb4a77df21b7ad9513739f06424 100644 GIT binary patch delta 415 zcmV;Q0bu^^1L*^h7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SXGugsR7i>Kl;Mtp zAP|JR6@pC{=KbIHW&o{J+T7*Rf8D56W*jz1zsu!YlLDXO1r)nN^rTea%p}96UN|M$r5# zaMMbJVKs0!loCUKFv`@K_SED3jueqc0aOEV{dZ-h)+qmuYv^VAo@bh*-E5`X$KR6eDU)~zt?fP&1y08IczLxrT z3LvitQu)yVG9yUk#{(c|f}nxn4L~pgBn^9R0+4h92%6pjLV}zCLLpUvlx>GT933DU zy;1)pK=2WOU<#1(FMybrkq^%RIrCuz$b=6^fV|?v{(1h)haU-yCp!A$RptNy002ov JPDHLkV1mvdzz6^U delta 420 zcmV;V0bBm*1MLHl7zqRe0001qplF?uENVj`1Gcmbn> zYZnu`mNY4IALFplj<6W#F8T~k4z~$$?oAo%(!s$=QmMHOCSZT>1qyW1PR6_O@t%ejD&5SI6Xtv z=xl2kIbe&ya4=E<7H-Xq@jTiL98(5nj3Hw)%6YVLk`gdJe;jkpBh_>_XY3)&_=3kV zS3UDL3DU0ozXvajg;z5kcNXWD#pHh%^E1X}1vjh70o5*l;!(XH0LcgE?Ip{~Zubyq zfc7sAq%iGKK|$*J4bcOV!cb5@FQt_dh8p0}p)h(SOzBihm=Z`~Y}rr>L!uT2zKc7x z+9INa0jBRq3WH;WK_g83gD{ Date: Sat, 1 Apr 2023 07:35:18 +0200 Subject: [PATCH 054/131] Fix gen 2 icons --- graphics/pokemon/aipom/icon.png | Bin 380 -> 407 bytes graphics/pokemon/ariados/icon.png | Bin 389 -> 421 bytes graphics/pokemon/azumarill/icon.png | Bin 417 -> 419 bytes graphics/pokemon/chikorita/icon.png | Bin 314 -> 326 bytes graphics/pokemon/corsola/icon.png | Bin 315 -> 346 bytes graphics/pokemon/crobat/icon.png | Bin 391 -> 404 bytes graphics/pokemon/donphan/icon.png | Bin 479 -> 401 bytes graphics/pokemon/entei/icon.png | Bin 488 -> 461 bytes graphics/pokemon/espeon/icon.png | Bin 348 -> 382 bytes graphics/pokemon/feraligatr/icon.png | Bin 469 -> 492 bytes graphics/pokemon/hitmontop/icon.png | Bin 473 -> 463 bytes graphics/pokemon/ho_oh/icon.png | Bin 558 -> 539 bytes graphics/pokemon/hoppip/icon.png | Bin 342 -> 366 bytes graphics/pokemon/kingdra/icon.png | Bin 402 -> 349 bytes graphics/pokemon/lugia/icon.png | Bin 517 -> 523 bytes graphics/pokemon/meganium/icon.png | Bin 431 -> 425 bytes graphics/pokemon/pichu/icon.png | Bin 266 -> 288 bytes graphics/pokemon/politoed/icon.png | Bin 399 -> 398 bytes graphics/pokemon/raikou/icon.png | Bin 572 -> 489 bytes graphics/pokemon/sentret/icon.png | Bin 320 -> 336 bytes graphics/pokemon/slowking/icon.png | Bin 401 -> 402 bytes graphics/pokemon/steelix/icon.png | Bin 442 -> 483 bytes graphics/pokemon/suicune/icon.png | Bin 538 -> 533 bytes graphics/pokemon/typhlosion/icon.png | Bin 441 -> 446 bytes graphics/pokemon/tyranitar/icon.png | Bin 458 -> 431 bytes 25 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/aipom/icon.png b/graphics/pokemon/aipom/icon.png index 43822f098048c30c6d76abcbe6506c6ca28f80a9..294ab74eb43d491423a0017e5a39e4e63d0ead98 100644 GIT binary patch delta 333 zcmV-T0kZ!50+$1j7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S6-h)vR7i>Kl)-Mq zFbG7WbZfa}9 zv=Y>#Yk^>`HUV}POmz?pk|&^|p;x360GTlnn@Ru@0JkA<5+MSy3J1W<9>_O9q6i6i zNB~PRZNy`Z;82KvllNW4gE-z_PuGO~J94k_6b9b=sWbGO76YBOGv<131ZDv2slgFV z=r{pzuh++ZZ3ox?ygeB24%MgrO8rawUx;r10qFK0fNuW*==PsJwAud{ywU7`WJv8P zb=tr3AqMR!b=rUJ5-R5yJtUU>-3wr0-%_OPugm;Mjl3@`5y_YKe`Ukvr=`NQ|J!qO f$+ipe1Nra;Y!4V2<&_w<00000NkvXXu0mjfnZ}rj delta 306 zcmV-20nPrG1N;Jz7zqRe0001qplF?uEb>!3;^{5KBkK^^>JMs z7>I^0;gY_ihygyp0{nJryhu+F?ZE_F0QcUEOrbczBdKsK zd*HRuRZmtO`cLtzI;0#?hYX?)8AKg2h&trDQHMO4r~~*Undl&!ffmW`Iv5!~qmIgm z4x@nW&P5Kl);X} zAPhvSf(cwa|Npl;4oM1&DN?ms^$;JDsxz6G7~bP?*C&OQE(^!nkmKn9JTG#_A&VPE zgTg9%x@AH%rKI^x8seF(s^aQm(Ho$V@koP%;p$x20b)D)9Y78~ zOaTI;1`dFD4YU9;J`ATqI)IFh4j`2eGk|z}=mB!^p*`L@4L~M*cmc%a15f@15SI_+ t#|03d52!g6AX7eE1exuMb6tPThad8=7f>!Itjqua002ovPDHLkV1m}^lIQ>c delta 315 zcmV-B0mS~L1BC;S7zqRe0001qplF?uE3G@Oo^q|uBZN_ahf;=1Pc;)^RGM0clx5}j~@yHt-cHF z-MJ55Pg`H@J0JPvHQ-_tJ z%Pi^?BO*Bk(SFfAwNa5b+>e&_VbA~d`~nzK0hrFm3=FMGbYKvGNsAGTc3@;Z2V-n9 z12g#;!1O*`;K2AkdN7`k*B*@LV~-~@7|#cFMF@PvDp(0V+tC+3-T^ZE%8iZ4)c^nh N002ovPDHLkV1nsWk$3KmBEg~ zAPhtimLe;)Jpcc<#RO6eF}>_zrCm!^5i>D1bzW2YV*$*INf$v|aNyv}aXVMXVG87k z4X-Z-In3}nf*LFZ`azL_u}ffmi0%?djkp3b)hy9XS_X<8MLti#U~s<)Y5}LTK$@-` ztRy5d7~txy1`DcxUwRpMXb9zS6U&FW9l^d~Wg^pK0^?OTeDR zl7Vr_xs+(?GMcv4bX(5{d`#g;-tFjK|Bs)Gh%kLWAdC$$wuGs#%oZSMg!#Pyu_@jG z#NNX#K&oK?$Vw0g5Pcv>8UUhC1W67cJ%J<02oOatY^d`%1CZSJ{a_3L$@ia=zbX%q rg&@EHkY|FV1`yd0#2!=q0+1=*kN_D%rCf2*00000NkvXXu0mjf5d)8j delta 343 zcmV-d0jU0?1EB+u7zqRe0001qplF?uEVlBg0~4OaM0!$u|86k|fCEJV(Y82>a0mi;+uHUZEk6Bw(>49@B(BRQLDMyzK8xd$ z<+j^t%>?TVBjYU*^OB5N>#JhQ(lcYRe5s52w^a}{FFPk_LM{n{9xGsY|Led2Rls;t z0pm>shT<()fswO?)E9smrDsak5tu_6sUZpxn2{7jf+8@F^T%}j5txVhEeQ!2Mav8h pzyR=?R)9GZFl1ZAml~KK>l%Q67#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S#7RU!R7i>Kl+6;t zFbISb`RTz4y#L#ZNv%C((ea>mrhDBl6w+OkB~D8tNO%i?77_?(^w1WH&wx2%h|#9lbQI??L||gm5~hK$_N$%( z_j_1>1pqE}wJU*IF5LsEl0Aq@$y*piP3=>Erg!!qEq8hB|L1;rQNIUB*5L?{#Q$P| zfW6uR1Wd9E5EKwwfXoA8A0YGFc6kQK95`-1+yIf(3zGOF4`BcR002ovPDHLkV1gwP BY#jgq delta 239 zcmViY;P)?An z6;eIYE{Rt*j>b{o1at(16h=Y_L%%a3F@QHe+26ALmHPS6@hbB`gCK#3S}ZWsiJnJ) zjzYnWgOCi&j19WkJ1fABH;XNT1Fx0>cs@1`$J`CGKTRsyrYWWe+0i;r1R!u)1;Jab zPI(1D$9g@8WmF}vq10@y{yAbSa_YnZG*R(gancN0k!w?&Fd0S`d}tVa+{-W?=DZEl pgKjnqU8ag`7+fY~!vOfYKb}}9V72%=#>4;s002ovPDHLkV1nWtV|V}n diff --git a/graphics/pokemon/corsola/icon.png b/graphics/pokemon/corsola/icon.png index 9fb51a0b146038411c78300dc5d07de33ba9d74f..e5ebe6c08d6adf125e0e9ee9cbca9637b13c16a7 100644 GIT binary patch delta 271 zcmV+q0r3920@?zQ7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S*hxe|R7i>KR6z>E zFbr!5^k4_;|G%A_l(uV}48{%{s}Ai!ilsQ9Wx4Tb;1#c!N&q#PDWIYUA1NW)6m&u! zC+0)nR4r0UkbrwyeLVL-!D!dCw?YJqqM#(0TH^5(PN=VBDE=G2J7W9i zF*p7J-_kG*!-i=EGH94nfeaevTp-o0Pk9uGEAsPx@B$f<+n7231|CZz V6_bnuHY5N5002ovPDHLkV1kn2aM}O> delta 240 zcmVr9LId5U(y?0GCRw=Eu)i(wbrLkx!LqbQpc5(D^Oq=t`Zy*XY-i^^u#Y$k} z1}3S7q6{MIVxL4HMeUJ|aCr#RQXbJ!05Nj$k55Y}Sw9>vFnc?0J%(wfVA$Ge-;Br^@Z)o+04{&P zwgGSNuQU5`=Lom^hZp=BD&^=t?+~T&i6J7MJARP27k6YVsquKV%t!&N0@7^VWByBk zrq23WMg1->>UVkE)UT2JlGU#vry;A~4X{&IzYgWoRMcO01ms73YIYFJ>a(wgG1(5u zq~7lT&UU~nk*~{S+aePU{r=ZE?I$Gt!g5JSPpO%|VWJQ9tM~@rL&kZ+e=Xqv0000< KMNUMnLSTZAl#Kl)(~% zAPhtWE;%^a|Nq-&69iGQGo7|4_oU>JkihJ+Jo-p5-G()1oiZM#Gz|!9T4=I>6G++# zUt(G$iU?E(f=IILf#@dei=?Q|ogOm{gw;nSJS^)f7=czi!W0fgh*&)3gtZbCfOkTK zVec{!i4-V^?h*BW8zO=VlfhFn6~enzsmdf`snX^ z9HcwQ`Yi{Mdk1lUc;g_=A0`gc`#d>_xPy#M>>b4Y0hj(J!1%R4bO)LGLvxV1Kjh!| Z!wa`uAvdSamec?M002ovPDHLkV1fesk*ELw delta 406 zcmV;H0crk`1K$IX7zqRe0001qplF?uEb>!3`KndK{EYLU}rNCS&$QIq6D(&kjZ(>U?%{6pUE%)sD9?;KgA()$t8_gZKCY%ZVXEqMA*b0 zU>LvZYl)?|$MZ?{wp>1R9%JM2b0vxSrnu&p8snSz@vs6<}Y zG0{|sAUWy$S*jm|_ncrH;>C>>%-J}f{iq6w zZWC`>fJ+891qpdWB+d<}Q3s5W*rSgOgJeH!0Ei<<@gp9L=XAJVvPl`JFl&E^)(v8- zADFrCE&N!1{D`~s;zw3UR(|CFVC~2D7k+#LH-8%dYcN+j00000NkvXXu0jG}g1yVS A$p8QV diff --git a/graphics/pokemon/entei/icon.png b/graphics/pokemon/entei/icon.png index b7707797f0cb9261e12a1af310cac50f0e75d636..eeb80f46047d49d661461cd800c4b0e3bec4d48b 100644 GIT binary patch delta 387 zcmV-}0et@G1I+`F7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SOG!jQR7i>Kl-;g_ zFbsp2R4SB<`2F8@ZrVZ#Fddz1Dv&1Gb$&Fy&*wei0QGrPKPbS~OgBENrC{5jNU1&- zeJy1L=u0Un-w=YTmr_ldROzq~0$117pvu?0%49*Rs@ldbD4Q~ft>Dm^D@f)JG5%(T z>SWMG{eHDT#Dp1tbDz+hd7%~nB{2~TF91?eY h02T~@ynOfvAHGXM9ABY#P;3AI002ovPDHLkV1k>1t#kkY delta 415 zcmV;Q0bu^k1Ly;g7zqRe0001qplF?uEn= zu!N^B5f8ujC5VnJso{t?8qYJVEQ?j5M$xHvX!KHuar?}bD=V_ce{Tv zh~n*Y%8ScZI;0bvSDSyNVsR#yU zP_;Dn?4Fmgm|zN!^OU_+Fc)^ad?tTbdj22&?9<55G2sKnjVj#6xk9wWw1du)IiOf`!_iCbV?)O9?CZzKR6!2J zAPDTHo^}ZQ|F;Y1c13Btbdw&+p=q1}M%3B1CoT?I;aD&P6GOs+yn2FRLL`yU7^0z& z5XX{Mq9uB&lR^o0L7^=Zd9PMC^NCx;KMZ6bOa?L&qJd1L(Lm}Y?yHUl;xFyoK-w#mV+(_U zh&w=6U@(xH8WfBMk_;*sNcJ?Nfn>A1)IiSsL3P~HA3i!0Dj5Vsq)-(|K3c+s$S6cJQBMEARvw-nLm0`#o zuu~629yrgyNG#`@hd#M!xEyHc_Qr^tIsmW3flgigmU#lgoqEepjicE@=(x9x8n}G~ zBPU3Lt|X4P^y6K)y+9RRAU3UnMYY&E;B49GQg9=$wh+9y>9x%?XIw0?-!4tfzt#u9 zl&Zi~Ap=vT0!%bZQUykJ4NSmUsK9_rKd%B4<7A5hObeEPY4Hj$E$X|#Ecwv!yL`L= X&Ar$}EUn=}00000NkvXXu0mjf$&q}P diff --git a/graphics/pokemon/feraligatr/icon.png b/graphics/pokemon/feraligatr/icon.png index 2fe3556a84094255dacedc86769420f89d31c720..74aca6aea47a50f18c8729bcb8e37dec026c5b5b 100644 GIT binary patch delta 419 zcmV;U0bKso1MCBk7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SYDq*vR7i>Klu>Vk zFbsq%45?IX-~a!&J3BzrCd)KwPuuc<5O>(l1-{$ucP)IS@0feA7nIX6a?;?{fUNc| z!wVN`uf6n!J@n#;TQ8p(T=gt9bWo=w4TBOMdRSmKG^m@poQ{F6rh1ok4F|drAZDVt z>$a`RTla_+Z2=K~zA9@PY9l;@jhHx}DD^EQ7E!~sS#Th-8V2a83Yl+A?=S=O$@t-WB3g3Xu)FRkIQ#Uxw?7f1y67DgB>3^563@jgvD zn8L9W?e!%#!@YX8>c2Ypf(2Nqn{&*8Bh!zQ${sTL#sT4fUgtkSf8u{-{R1QoKLwEb z!A}4ZggF56LXZO>DlI_TWD_8&k0i_!Af*KeWvPU@0K(id+6s{E5%1@Jc>?4lNCn76 zmwA}yz delta 395 zcmV;60d)TC1JwhN7zqRe0001qplF?uEj?ft9zR&(INut`}#hV2TroR-K$+6_F($hn*0s^~8b@-tyPUcNhOW@3#(d zgIXykh@#87I@E!xZ5bX}a49Lwcd7y#t-@RdCvYo;;4R#W6n7Ea4x}bn@nzKmhZz1V|-T{2X2`iL$ zDn#~4R}JtY<)zRSR{}`~z_Y1rMQ&Ep6SqYy_az?!bFYvPce5E6Y77d9S53q1dTkcG z=st;EW+D!>kYJY~Zzo)4S!pXgB)WH*gze?eN8fi|1JV22^RK{w3uX=m4C#k6V75IN zRaI&L18W)>FcllXz@rvqz*HgjU~bo1P!FcadoV`O0LB2(&qKNq%r}q$jIY6r>$DCS pGSOfh9|u}q`oLxG_(1%rk1uw;NuW8Js+a%(002ovPDHLkV1i}>uH^s# diff --git a/graphics/pokemon/hitmontop/icon.png b/graphics/pokemon/hitmontop/icon.png index a2af3bd2484a06eacafced25d2941540a84f1751..7f8d63f91561d6e163204d912b3c7cfdaea7c560 100644 GIT binary patch delta 389 zcmV;00eb$~1J47H7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SO-V#SR7i>KmF>>M zAP9w*8sLWs-2dGUP^(sKw>R(4nQZCGk&o8%?DhJs|6lSHPp3k31%eFHqztf1B%_>{ z830y=P)otAlC+jlh2In;Ris5B?1?oKX_28*zZARAs0t$gISiGFGLwcG2{N?6p1d31fJsH5{=^4EHb)Ezv8nazL|I7BGKo3d-4Py59UMsw?0{4*gy7v zxBtffgZ(%D9~`sue+R_I{|yj}|Ic^@gxPoWf8SpLQ8{yD8C!d7fZ)sCMi2*tI7?=K zH-dPPfDnx!1rQ4%PJ&Eju)}%86kr9|F zlzc%V!v!LW5CA{cJHyj3720qS^DqvVa9*9)E>V|t1mbF{zs7v4=WiW=d_L(Ab%(^S zcG3X~mMqAm1E}J~H;rq9wE6IYfE;_*Sp>}nmH=uB09I_2=mZdfRq0x_%j?&BEqm(g zMUd~;ZK45#APr+B8S;X3aZ?zPqQrUEKzGDVhPbr2Uj=SaDKv`?+6iJ2cP97%B6hx< t3t}pMtb#!fF?_@6e2_4-mxBDmj~|*$*qLG?0=)nL002ovPDHLkV1k~jw%h;! diff --git a/graphics/pokemon/ho_oh/icon.png b/graphics/pokemon/ho_oh/icon.png index 7a7ce8af61360888a36885de5b855797a87c890f..315683cc5e8ef1b1d46983b419bc998ef7fcad88 100644 GIT binary patch delta 466 zcmV;@0WJQn1e*kq7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SnMp)JR7i>4l-+K_ zAPhze&WenLzxRLJ+585Ql3i>!ORH3sPrewEt+XBAW--T?)Yn*0R;l0Y-2P zknjbr<<$47EkD33kV^b|y>+1*qxDn*NUx969kk03L{cE#_~i4tXF!*ZR(L7;DRn*av%h-QBUvKw_i)U;;5 zzM_3X;7C>fVZR}v4FHX(`gi-60f4T5wZGQ~Q1#FDn>5RSK-WJ57=n()H~q(am<2!U zU&_mXSoF6s{CU94`X{fK&jV)FAD8;1|7!nL|LgEC=l`q!H|laC8>S6{^Z)<=07*qo IM6N<$f|fGg0RR91 delta 485 zcmV-7zqRe0001qplF?uE5I0D+i!~oqf=ROrc2`BSnU_16w zqeRpX^};IHj&?q!)%b^n>%nkr_!_m^@p*z-)DQ4G3BXGZANp%du(}Bdwc5*iKrJ#@Bt1RM;qKE*^h$Um~Ppr_IL9;}v- z_AZcJeprl0Nh95VNC2b}|7HF3MK0cvK}`Z)J#Q4A<)q~RSLQ_X0F^n?*fGWgXd@7Q zuuT&Q7sM;CPzNARgD?cReWuvuXzJJ|5yn7kjXDJ8!Wp9vRrJB*Iz(ercMMTYOc%Hg zkv$$U6h;+4;5yi`55geeIz;@Ns`0&I9W`6pHR7i>Kl(7zj zFbqT)65C?%{r}(Amw;Lt2bK<~!b2tG=R2p6Tb8GOT40?5RpcCyDxVsI9z@<6(TwLK z5);(eY4WAuTccD?0fp^hCu#)I-C}y&c_YB-0LL@I=+cjq9vKSS$B%pdm%xmSn^_9L zR_oXtXV=jQWv71I7SiJRh19}dOJ4nlvmNmH@3C2?d#N=M=0fNM#U0(D6k^I0=Yx#AX q0Ll7?0Lc4icOi+f!*^);sUa)~|o^r)je6hlAOz!DKdos;6WTl8zE^WM71- ziolw(cuQ*K;AYCD7Sql_xVP`Bz_p@MyTuHSrqGs>Idq(}zlu)oJ$pQ+GaL|c=md8N zXBMMw%L4X(+7Qz1AY?o=W1 z&fyj;;4$zC_s9=SBh8s-nGloZ&()0#k<%r56V2ZNp@vT!msB~j36;|C)$u2vs46t( zx$aw!+9WGXLnKmikWH$ZBBnBvLA6yIice^5ab0Z?!qQs$BOW)20tYLDYXm#K8$BgZ z1CK6e%m4NDs`L*CYx+meLr*__9`^L}=i#6JjTL6&^w-g-_|tU1E&e)MiHiR?-uS@$ Z-vQg=6O3ITXTAUc002ovPDHLkV1j2>ddL6( delta 329 zcmV-P0k;0#0+Iue7zqRe0001qplF?uErQ$b3^KoFcC^dHs-2!{bz>g>tDI`&wx53Fd$vMv@&~9;;F%4L(w#*8oZhwvqt8MjSS=WD< z;e^4!Cj~_49!^4>9~pY8v!UQtV%2ZX_}n$R;*>jEUDXS|6IiZFDtV9RWf|m#Ui-!f zK&^>V5r*_7{sW+iQM($0Vp5Y!>xnFig?aEo0e5MTQ}K8digbZ^!+VU_?Re%0tNW^( z32HlkjdNEh?39Kn9$$AMO4u)QV3#$6_uI$IDDocbej~2`yErsD4hOk3h>9?=R0PN$ b^aFeVBNn46KRlAbJ zAPh@P6)GUtWvg^dN*N6kg%6 zuYBlO5vt8%gHxZzihy!%2(qtk?SvK??6U<8mY?F9SzCu%Y8`TP5iIl21uNW>QoZV# zQ77oXi=!|^HKz`Lz5++zGN%qE!&$;~l2@iiVqnLsoLE)P4R=8T(i9NrLjh3g7T_10p^86!r?$2_GlSAGV~+p77zbNv!UuNmM;X z+T3!flT~b`9~!4r6MF_6!54`r$eS5o@c;3P0j%qY{v?@yy=Uw=y1T>P6F#}y?L9H> z?zZPC-}#5T@3wik`S|F)lBW#mQZF! zI3?VD7MeBSZp`kUB>KCa+>Oi_-`U-RkQ+*Jcbc@06l%@gXmK_tNAnr(ZvDjnD7n`) so_vXA&^mfO$KkD_g+PB|W&uq7hWt+lb=fG%l&Wf6b`L^d1@|_*?M9!% zSbP(G8q0H{uSQN2eKnBG^i_;{PXB|8G|uU-8E?ue^fl8rz*ywLdK+cc4mG9(kkH?{ zu@5|0Nc7tzkaWO6-=@wWkq7!Z2}59_KL{Q!Wn%i)$)-0&5}3Z-avpBNGWjUuY-R0O mAd_1zI#Vu-Ae46{!ht_m3gfJY!Qd7E0000R7i={l);X} zAPhvS7z`!K%>V!G+N7z9V$#FzN-c+6{J>+9yxZ-o7Wt;$8m}NWD|ToO?9g@nDgoJW z86mZM(ll=YZAop-CZX4pA(E$fn;?;=xzAgi|eX-hjJODoc`IMEFdkgr$dag^Mje%AwbON-E+}b1K zsfFF)R!Z4=Mym%I5~>Fj5#$h1h}}^Ftd0oCM!*Ni;If0A(gTl{lB`~dK-8IoZVL<#@^002ovPDHLkV1meqnVSFr delta 357 zcmV-r0h<1)1Fr*+7zqRe0001qplF?uE;SA;`<5U&b{!0muP9ryj(+p}quw_oR7A71dcG-FJUY{qOCB*kF7Aok4S*9?*wu4cRzjr`qtGUiV$N200000NkvXXu0mjf DX!WE< diff --git a/graphics/pokemon/pichu/icon.png b/graphics/pokemon/pichu/icon.png index 5e3de4b990dd7ebd579fc7e16967388d62b3ed2b..d29fa7fb4a5774895e43e3791ebff8b16c4344af 100644 GIT binary patch delta 213 zcmV;`04o2A0-yqr7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{So=HSOR7i>Kl)(yy zFbsnQ57Op$dH=U{9UFKs_97@h%QfHDwH;ZOsmDcTKuHLegrMP`AOQB)T!Iy_uqbQQ z8o?M$0SEPvF|s{wUpZP4Zy>i#1GFCyzNo=^o_!L6aMG<|qS4}RZH%f$ zv+ovGD|q%PvTrps^(UGE()~{bh}y~s5SbsR08xV&0U|fwrkt$wg?u;wLA4K;vDh$% P00000NkvXXu0mjfI2=^% delta 191 zcmV;w06_ns0*V5V7zqRe0001qplF?uE}M002ovPDHLkV1h#-PqF|2 diff --git a/graphics/pokemon/politoed/icon.png b/graphics/pokemon/politoed/icon.png index 8ea308aa35561da41df3bbb6a96292d8734c5beb..ffc6a38a4862c5af1e2b0eb16ab7a97faf349094 100644 GIT binary patch delta 324 zcmV-K0lWT>1C9fb7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S3`s;mR7i>Kl(DkJ zAP7Y>226o+|Nn0nG+Ql@ZfD-SrAP{nf+n2f_=f?Y&bQVo0!mrVt01JkQ46?k2 zO%T~Vd74!vA(U5tsO=LH>NO0oW}_`&E18WTPHuv9kg!mvxXGbT*fYCqBL@5+oPLe{ zD;SY~^1D=(ze`oX<8=IDk8hc;1+onCpqPdyKm2Wh;6Whfk6sGI{Lz;{=3D~#oIUdg zVa_>Z8{%`i-5qel{qW z(2cgC;iQd2VYKZ+3q?Xu)CPj;F`IJX0}(TB`NVUB*DQe;kMWk>vB2*!%c#m=c6xuu zgjElhPfPGq`}Ip+=(!hELRLew_ET*N09C;(b^ZW&!-iClUl>-z)@QRx$`WN-loQ_l zt0vOHW897{1PgGnB;1*c3E|Jz9LJHZlmI5`npg<2U9b2 z5SdNi-|jV3gN2e^zJdA5SE1GsWY94q)bD}O##gfr7+4HL-AC_%3HWG=Qt&}^Kt6r} XtcRuKF!eK#00000NkvXXu0mjfn-rF` diff --git a/graphics/pokemon/raikou/icon.png b/graphics/pokemon/raikou/icon.png index fb0d48a5fd4a85560d166f6b4798e6f14022e100..77cc29d7e9f273f9fa110e59ebefca17e72ea8bd 100644 GIT binary patch delta 415 zcmV;Q0bu^T1nC2i7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SXGugsR7i>Kl;Li} zAPj_q4HAsV_x^7?+msfkDE&EUo29C1?>IXIzT^0#1$@xY^UeX)?;JSM)gT+k=xq7@ z+;ssn%!6*~dj!BF=IPSUE@p}rBtX<7I;3Wpp&%xtq#h#jA$2{nI$klLG|Kc2nTZ69h&q&Csf3ZFTi>YeS z0X=$-m~-(!5?gPcvGlo(LMdxk)3w}n*#-#dV@YZi&7MQQgP~So2y8mv9Z;pk;R{sJ z;PI9~O#CwFi}H@}>HQzws5L-;TWp=f`%sq|J(t?;X^ee-HwNo_d*bowLi|^#U&W6j zp1F5^M1U;(I0rwD2#^gw7J#h$fb*m2@mv71@h4;wsO?&*)?;T!I1AAJqmEGPf~002ov JPDHLkV1g?G!nyze delta 499 zcmV1H1%~7zqRe0001qplF?uEbBTsNMuqqROhnJ%C>e|b7A0ALRS~*MHZ4bbfTFkE zkN?O!-bX_IX@DFFDjw!2#J~b^B+|F#AnN#RDO@DAil0sb6sC=j(W8n%3r1sYaixD$ zTpm4;QJh^zB9=S<&<#u}rL|ZV?(VhoV78`v{Dsxz=4I=(LYY%zVIgHfIxjuHt@uKV zANHCBT$Wg3>-c2++!h ze|J+Bf`kv($42?RtXMmHZn?)~cjBZXGt*1uP&kQ$f_6EjuImN5+sQX`)! zA&_Wb@|G7PTA_^xU;ro7xW^^(q{V1)?WAUz+@xMbg**KZgl p$*)H5cX>Gyl63S(ar|fB#$QG765Ki18?XQX002ovPDHLkV1oV~;Ise$ diff --git a/graphics/pokemon/sentret/icon.png b/graphics/pokemon/sentret/icon.png index 9a8040833beebacffdd0943654e2254839a3a85f..e95d75ccd41ee47c49b7d235e0371f4c8ced1ed8 100644 GIT binary patch delta 261 zcmV+g0s8*H0?-1G7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S&PhZ;R7i>Kl)(xE zAq+$nA%;Cn{{L^A*sZ-dku4P3(p=}ENp^ju{9c)D@;V5P*->p`oVa5z0>xlF_nWPE z#ldojp$EYLL3hAZbxjyNf;s@K=k%yG9fjo~Cas;s8t@tB8KeslCp;FmC?}+MVRHuI zn?jPutY8hyOY)y&#_|hdS9F5WVy#FBtMMt30P28dfW#8BCS#GCA$JewUuS)SVTM3b z1r334!)yeCD*{>H@DvEq!v%pbU00000 LNkvXXu0mjfdvI-t delta 245 zcmVA>07zqRe0001qplF?uEGc4!kgYsuxBq_J%Nn{jnccCa;afY#@4600000NkvXXu0mjfCZuI_ diff --git a/graphics/pokemon/slowking/icon.png b/graphics/pokemon/slowking/icon.png index c4d5bdbe7aaea3f343ee08fd1519be6600424d68..8527e8982de133801ba193d3ff892fafabecbecf 100644 GIT binary patch delta 328 zcmV-O0k{5<1Cj%f7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S5J^NqR7i>KluHi6 zFbqT+=d*Am&;4)9*rk9}r-&UAxN5qX7spPT*|uK{#B-q+2;VgVn<^$bz*s_c|C%l%0zCm@?8r9}{?_HS%tBoYk zh)k}N>*6V#z{pE~lmSly)UhB21#o1cNDn1Caxe7zqRe0001qplF?uE`Kpum=@#jSH2|ojR40+w|$~kbXYK{<5sK zqccnw(-DF5n;`(~_3^bK_ZQo8z90=rQyV_R2quQlO+uDjIp_15M*wxrXNCagG$wzB zY-PR_mkE7`T)7Gv1|fU12!mh3kez%G#zjBi zVGu^7L=Tmr+M!*KLCI4 Z$0yk{#oQP6d}ROt002ovPDHLkV1hQBl#~Df diff --git a/graphics/pokemon/steelix/icon.png b/graphics/pokemon/steelix/icon.png index 2cceec69a9d8d9c226c867af9b9af1f441ef2c62..defe78d7d6f53947f5eb7f13cd17b0a6bfac85e1 100644 GIT binary patch delta 409 zcmV;K0cQTX1LFgb7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SVM#C;w=qAF#4iw)=X`r-mU=&fOA6}lVHY;8d$mN$i2xm%MO zVZgP}xy+b`e~{}&Y=wX1VWMsk8e$(;fw6VCvr?x$^hCllKYHy99m@qX^Q<11Oyq z&$E|5p;W1Uk<}@&A8)kuVE@WWwBd00Aa_BFqI4Ya7DoneKNY z%mt7sKqgEE$dWJ_AWy<1fIJEF4v=@kh#(0di7JAibA5FmR4+eHvSyt1Gyi{%wQ`B2>Nzu?0!&{7-D_kEce00000NkvXXu0mjf DU8c7* delta 368 zcmV-$0gwLU1G)o{7zqRe0001qplF?uE9^;yXB#>jIBIST(8$+H_@0MO4fx0Lj_l%MKI_?1y-U02sMGVYmsG5M@ z#A=q7EnmTeQsq4I%0|*^K>nm)3)Th0s>;MOgIg?dcOGPVW@IPb0-702MV zqsjS3Tp-OaB{@@oE!Sn(OWWl0T#-zeYKkG8Y8(U}GIW7)t9Z+n#(!bAOv4$PDAQaa zPp4J7Jd$Ute15?`j+=5&L%>MhkAZ}o!+*v17{%}a O0000Cl-;s} zFbITe2seia@Bg-4h$cjB@6Xguwasq$$;kJ5{oG}^&L59DGlyiY$%DgK3mYVB`~F}s zu5OT~vbWY9IaAlG?E+nJ+mS8BaXkV+k$%H>KMgRmMgWnJTMLWL{fdw4u`aFKBpaY_ zsy#B2i>l;K%ymD12H%Q$%t}cucnQ1_9+8;XE2g9q>85{Fy$ZuWJZaI37NP>3xYioF z=KSQl;NaMaK+tQ=5e!vOoCAU>)mm`NA$lKGUH21512u;@jshw|N1@)>#eqJ(6a?X8 z-L3}zZ0d zNc?O;Dq$N7#oofq5d|b8wfZonn2mBVItIG5 zEm*}5F%3r_Z~*K*oS=)d7bi^mZuKRP!iXj>ZWE~r?^)(IYkzth(}lr(&~82M&e3!h z+-aTUCE%+cxOqtO;c;g_klh;Ck{dr5K{&qkqcQ_Duj$8MueAr>gBia^00000NkvXX Hu0mjf6lB@9 diff --git a/graphics/pokemon/typhlosion/icon.png b/graphics/pokemon/typhlosion/icon.png index b69680648cb83e16a1c3ab8fb2803ec140136840..e5e5ea51c1b5912ac01717d9c2470cfc44b1e6c1 100644 GIT binary patch delta 372 zcmV-)0gL{*1HJ>07#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SJV``BR7i>Cl-sU^ zFbGA>oSIZx*#G~x2dJ8{rJ9-7A^OCUi`um;zZrPSXC*MD;DAH3$8#3FV*r5U%vl*3 znrL0D8j0BQLk+B!c7`%(nV~?kyi-h>hx}rhEp7Ks3hQnZ9lIgVg~S~OPMV;I4z z%im^zE|F6TDj>gqibpO|BB0hPQjX{dSQ@CC6Fy2`0`QO69!Egz+}=RR@Qb5Ww=NhK zaX=?IW=Juy)!Lv^Q_w`$02*OSMML;1&TMx-ufLJ|zZ;YHaBcSEar*}FAc#W_Q$c6~ ztoKY1i)C0q6Tk#QcJRmz(w&T5Aff^xH^{ZfyFiGEnY$)a7lCL#JpZRan#M-p5Quwj z7~x$YZjkS5P3HDsN=yfTm*P>8!FtBRqxY6uSQUadD$!R}kGP^Th6#Z!w zoij`$Zk=IjP!L+DIt08IO6*)s!H6d+-P#nG;H1PXOKc+;Vp-xQd2$_aghM=??>v7% zJi9&@!j_bX713C^w&m#Jm`H2~K0_Z7-P|rbkasU+BDO%@S2LnDEo~Pr;FD-c6pX+C z;-v?W8<4-n9>}%%$70}9-lai#>;SA-N|M14IpRvL+JlB_)|os|cNHA{gMjW)7Z6@l z7xfncRxDaz`uGt7-e>AEeYLNvg?U?6*-kXu{SoGB^PrlVMwq!N53$BQ{TeSfiSrj1`dSbT9{R9+eVmKRKb>n zFbI=Zz{B|9|NnLqb$3QfJC{Am(O?K^n`L>bugsjoX0rysz{ecGH6n)`sip#s80kn; zBS)&14HRHajxkjS8YCM@q^8Iq$Wj?-$VML|EUeO*sgOrpOp77ZuE!9OEbyi&<_;SI zD*6rzFyCITw)?Sv;}_c@D>wI-<9ASy0j6JVPv5r9v4W^zAy^+*T+>mC4!{~%HgZm}71b1;@+#}CZ*V)zNtolZLc-E$On+{I#r@q&d zAK&r=&uW?<$E#V_JwK$-naqcEJ*Q~l1xU~QATE{6cYXjw-rvRD_P_j~+GUa-Mxe?M z`^^vJSeYN#hw;_=|9toXOF$K=1B64K00000NkvXXu0mjf D{d}i1 delta 384 zcmV-`0e}9l1Ih!C7zqRe0001qplF?uE;f5fRlg>OqB<#?V*-&hdp*lg9~$D3^cZ z7|74-ZDo`jDxmYbJ@-7EwGTklyln+C3%U;gyTiMlJ(H_?m%G#((^1KIFZfHtjCSlu z!x(Wc5pS#=$Dp_&(^EVm3kt=Q?!G!El6?qRq(WwG_8%5K9Fs5=05v3vS0^6}z*kts zUBYdtHliUQ_c~Xn2q`Z+jAE00000j(SW From 01a12d81c78df92f38fba3b721b1e969cafa7526 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Sat, 1 Apr 2023 07:48:53 +0200 Subject: [PATCH 055/131] Fix gen 3 icons --- graphics/pokemon/absol/icon.png | Bin 359 -> 382 bytes graphics/pokemon/aggron/icon.png | Bin 450 -> 489 bytes graphics/pokemon/altaria/icon.png | Bin 432 -> 417 bytes graphics/pokemon/armaldo/icon.png | Bin 398 -> 424 bytes graphics/pokemon/beldum/icon.png | Bin 256 -> 277 bytes graphics/pokemon/cacturne/icon.png | Bin 307 -> 328 bytes graphics/pokemon/castform/icon.png | Bin 242 -> 255 bytes graphics/pokemon/chimecho/icon.png | Bin 282 -> 271 bytes graphics/pokemon/combusken/icon.png | Bin 367 -> 371 bytes graphics/pokemon/exploud/icon.png | Bin 411 -> 421 bytes graphics/pokemon/flygon/icon.png | Bin 432 -> 451 bytes graphics/pokemon/groudon/icon.png | Bin 414 -> 437 bytes graphics/pokemon/huntail/icon.png | Bin 378 -> 391 bytes graphics/pokemon/lairon/icon.png | Bin 377 -> 392 bytes graphics/pokemon/latias/icon.png | Bin 360 -> 368 bytes graphics/pokemon/latios/icon.png | Bin 371 -> 379 bytes graphics/pokemon/lileep/icon.png | Bin 353 -> 371 bytes graphics/pokemon/manectric/icon.png | Bin 309 -> 339 bytes graphics/pokemon/mawile/icon.png | Bin 424 -> 410 bytes graphics/pokemon/medicham/icon.png | Bin 320 -> 336 bytes graphics/pokemon/metang/icon.png | Bin 420 -> 416 bytes graphics/pokemon/milotic/icon.png | Bin 495 -> 478 bytes graphics/pokemon/pelipper/icon.png | Bin 391 -> 406 bytes graphics/pokemon/salamence/icon.png | Bin 410 -> 420 bytes graphics/pokemon/seviper/icon.png | Bin 375 -> 397 bytes graphics/pokemon/sharpedo/icon.png | Bin 353 -> 366 bytes graphics/pokemon/shiftry/icon.png | Bin 438 -> 459 bytes graphics/pokemon/slakoth/icon.png | Bin 349 -> 364 bytes graphics/pokemon/solrock/icon.png | Bin 293 -> 307 bytes graphics/pokemon/swablu/icon.png | Bin 320 -> 336 bytes graphics/pokemon/swalot/icon.png | Bin 293 -> 311 bytes graphics/pokemon/tropius/icon.png | Bin 426 -> 442 bytes graphics/pokemon/wailord/icon.png | Bin 362 -> 360 bytes graphics/pokemon/wynaut/icon.png | Bin 397 -> 353 bytes graphics/pokemon/zangoose/icon.png | Bin 430 -> 412 bytes 35 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/absol/icon.png b/graphics/pokemon/absol/icon.png index 681d98d1d9ee147ce1156b4d82d37364ec483805..d58d208a7bd322beb9e549793c41994940842ec9 100644 GIT binary patch delta 308 zcmV-40n7g90{#M!7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S{7FPXR7i>Kl+6yq zFbIPikb1=L|F*+nKTV+NZJV^Ehpw`R32DD=`?UpNEw{EZP`=Vr$ypzI@WjzzfT}(% zQ$?6j_9ZA2-JsgKJ=s?`yH$G1WzkppqgPNw1fT{a#-O!$`Op~&%3oDck z=DIE|CXx&rW!GJQle$9eQhFIqELmVN2jQvES!6s6{<|=^(skhwQR)5PQM`IR%qV!T z5m9x3*h|sf!PR=9g#osFwd?Tzn%4UPG8{_=$V89?kf~$>NI{qpAm@evNFqo9kdYwY z2#}HwM}TlQ#pnG3NGC{fcz1xD^WhGV1s@o{<^w*$ha0LBC>14yeVn=g0000V>>3`TteE9!otdJce! z_rq;^?{@YHW27!|lk(598ddd*BJBx!%sfP^O5yY6pK% zlvp|t*piy7t#8CTlXxZ50yzOl1!%0H6{MakbWAn%Er6Rrv>sY+M?S$$v0gqW5LXxr zr$6&g>i5FrM5-{LX{QQPGAzP0gR(FqIE2BiIhKUk^6AeMrt>2SBh8N_40e8;!VG?# j!i;{1PJZB1{rCnvMYHcGBn(Rc000R9NkvXXu0mjfvp0f2 diff --git a/graphics/pokemon/aggron/icon.png b/graphics/pokemon/aggron/icon.png index 5410a384f66a11a93a0fd673bf3011fba516e237..3eaa0605429f37a3e12194d559d8ac7ee5835fff 100644 GIT binary patch delta 415 zcmV;Q0bu^Z1L*^h7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SXGugsR7i>Klv|d= zAPhreGyUm@z5m^gBtnV_(=!VQr_Wf(kC1yD&l)Q;_13T437TiNhM+foZ50-XS>y7Z z!iOS~in}Bc){D73?s<~d5so6<>D7vY+nB)2U2(VBqKDn==Y8L&=BZ&13K(%H)R|oZT$MrzA{0rR;%p%Mc21;qgOVVaRxQv8irL^S z2Zho+I1W@z@j7leST-a~R)T+ZoF)NVZ2TQol5k$S$}DL^TntcJ$QXBw+oPmFAJ(@r zjyub76ay%NM-u}2FkG7$=amxUiP@drQSRnMtzO^a&-!zIJpj4f{|%7$43L>1CqUja zKo){f@h*Zw5MD#rA&l`zO$7N62C+ErM=>B_^h|}FgwdawL5d3?oiO46zkC1y002ov JPDHLkV1jOLw6_2N delta 376 zcmV-;0f+wS1HuE47zqRe0001qplF?uERdMw}RrVNVne(V?3#wEc>xdv`?3`+m@$R!4SQ$%+m>zN}AX@!JXJ=v;sA zvzEtkJ){LI<^y0IbaPCU0NSqToqK(B;7PpiwrV~ zv%qb((!YQaL9~NWxCwgjF#_;f^d5+h7%x1~4n}+km`FD;;zP0cDCrS|`1k|niH{#P W=JXOj^Ebr+0000Kl)fJb400rkd(7 zG!qfdw_z+|UdSXgSQF2WTcS(TnLp6+QhIP)-fGoh5Uqg)dR6R@x`AkMcmg7{2qo|k zIfz`~aie3Y0s|?3Vyr)isx3PCHh4IeB39jiB-m%97eAw8*>k=$cN>H{)_UR@nGBW(COcehfe=y zJUr-6#>0vJcs!iwPw;=zALD-7zqRe0001qplF?uEWrrY`=u z!5GaUgX%&hF&w6s+KqVAI!Yd07Y}79tBwGOW9*0!00*^zyq2J)}3HWcclE24mO#lD@07*qoM6N<$ Eg89y=U;qFB diff --git a/graphics/pokemon/armaldo/icon.png b/graphics/pokemon/armaldo/icon.png index 5dba6557dfd99f42185a3475fa7890203035ed36..1277dbbbe0eeeafab82fbcdfe199d901c8640db0 100644 GIT binary patch delta 350 zcmV-k0iphm1E>R#7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SCP_p=R7i>Kl+A9# zKnR5GEJ(XPFz^4ioxzdX{mJG~_0(|4A&gulN0e4?Y!2ESZI7;z_0RGIESmr5EeU^_G9S-$&Z><95S}V|$wtA1Nd1eW?vD&f( zIM1j+HATx3n9T5h-&Xm&`mh8&X)B${bP>_Q)XKcuDRREr_!}@(DSkF!N4hd?!a^RX z=nb$NABq~RoNuG{Bjn_)sy?}~Q6SAj=EBpyuU`5+Jur+ns^nJ{UMi?5=4JbZZa>aX z{4)M6K&JB_0WzQe2#^JfdVq}QfAj#sc>WVWhV!2Qf;rDU6iVAm wVTl_clR|qFA8vqb`QUp#2q1et;1Brl1-P9W1cPm{Qvd(}07*qoM6N<$g1*?Gz5oCK delta 324 zcmV-K0lWUF1C9fb7zqRe0001qplF?uE-%O;WdsO5AO$if7^~hNfs=Qf${)#)g33Np6V)#t66`i zgk843YlD|D{bNf&=i#^&JzKf+-@4~-Ed}T zUH-g|kEzlRa>gP6N}%*r5fBK+_r@!*tdu5g3DvB+^=ckyZq>i5-v*O72$;k{z$6X= zCUF?Ruy9CVgoA)#BLgMo1Pxcx5YRB?Pa6xpTrGkz6u~4P9DUetK5*e9@WO}wfsZdY WW7TG6iTiE<0000KlQ9m( zFbG4-!W8WL-?k>opF)_cuXu{;7elCco~sXvQtQVUqa!FktRZMpL{mmB2oQ3zvjrZ3 z*2_f++Cg}5QYsfI30SYPO4NytOUXkCa8!2^1D)?fPJLQ zNorPl0V{tZoCD7(CYyhFVEg*Z;16jeKqWU;LmE^Olf~H~;_u07*qoM6N<$ Ef>!xdTmS$7 delta 181 zcmV;m080Or0)PUL7zqRe0001qplF?uE=>YOI(%^ymxAQo1gAZwq#?zUm|+8&$ww2??D3q)FG*eV@Tp-A3^JMgme)* zHQ>rc_PHP)Sg3>LmeYZ0JwaVw>?&hEGqyR1GjIpK_`rTny;UFxNgmdh%>pKUPjeyZ ji<`^*s{Zfr!FPBAu?m|lP^s{a00000NkvXXu0mjf>!47O diff --git a/graphics/pokemon/cacturne/icon.png b/graphics/pokemon/cacturne/icon.png index fd1bb1d5fef7ac0963c678a67a2ebc54143c0411..8dd74b291de3ba24b86975590a9f2f23ee92edb2 100644 GIT binary patch delta 253 zcmV}c87#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S#z{m$R7i>KlsgW? zFbqRI$U`%T_rGmLxkV8`l&36djBI?M^>H}HEf03O^#she#73Xq5r75YH37=httR5` zkQN|_@inmQq;@gqN2=@wl(0_afK*>NRHI-U?ng5Tu!K&J%DmY{E{d~&7$x=TlcywD zAySn@)IbB5M3~H64^VG3TA&sS(N!3hhq%FQSu~SEmeD;+aNF&>&0Rm|36MVt5NrY@ z=hOuV>=YnXm!|+x|NqQUod-Hm;y+onf5tn+1dD33UsWl7KC*{<u+a{q QMgRZ+07*qoM6N<$f>IqpjQ{`u diff --git a/graphics/pokemon/chimecho/icon.png b/graphics/pokemon/chimecho/icon.png index f5480bc356735faec3595cb18fc51559907b11b3..d4d6b644855a35c3824edb6c48602090f8d41492 100644 GIT binary patch delta 196 zcmV;#06YJh0*?Za7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SjY&j7R7i>Kl)(zX zAPhs5*o)Nm|NnOF*x1EZ*l7a;ddaia2rXsnjZ`)F8?}rupE5!rRzVOE3P40`4+v#k z;whmZ_k2ZwS0@Jd0O0CPa5v4HFrrrOV+6j($fhyB;6`*Ac6R;(QsN9N{Vps3CoG2S y9dIH{!ihM^hgd};u}EU;BiaMxPXlC6kU$4pDht($A3YfW0000KltB`M zFbG8xC9uoC|7}Z1#;PH-n|9GDI&OFpQ0Ardn*kuoCWr(8MDr5VfUwxTBEV88$SYB( zN^k;-M)Z1*Wdr3cfbtq3&FdI0fEHDOT>+X2R3e>ExL6qn*ct)uO;Vi*Z0(5W95nq7 z99^~ogK@^>VyD!9fy{GO=3-syM6}-lFxwz{X*<|A2T-Cfgc4JMPN1!nZJm?PxpfX% zZsiyZHAj2hzFMC8yH|?y|FHNAL_00008NkvXXu0mjf5^H?A delta 293 zcmV+=0owla0`CHl7zqRe0001qplF?uEzKCKi@yupE17~#QN-SjlOSOqf)4L zW$j~7T34x>YtqCCh5>aZ0GTTI20SV7hIAVN<_<4gD_v=~I@H-ZjG>3sCI{?Ez=D7M zFvjvd#~WG$39yl>YnlSbo=8HVM|`0)Xc8JZDpK{$go00000NkvXXu0mjfeCUL8 diff --git a/graphics/pokemon/exploud/icon.png b/graphics/pokemon/exploud/icon.png index f803aecaba4454021e3dd855ead8ce245332fbf3..3cb142dde2afcdf4c9b5a440a7e9c5c73e685f72 100644 GIT binary patch delta 347 zcmV-h0i^z$1Em9y7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SBS}O-R7i>KR9%n5 zAPk#?BNZg@|NplahkgL-`gBisOSM+3UB?8H*X!>E$!C1a`GG;UoE{j=+#Jsz)6nQ} z-uOX;t(jTiw*+o51%h-(IB^5J<%z}v^?MVxWMb(!V6x(v>|Uw36G{n@oV+5Ap9EhZ z^nGC`Y?&@I6Z|!QiGTqL2L{~q&Lf3ailX1RLbq+APzDitb`kVnk5+4?mkBM_J1IaC zRUvgW9Q7I`c0z-KqrzTRClrt734(xSM_jo?$N+6t2oa<@5*7i5uToR7o?00000NkvXXu0mjfDwmpC diff --git a/graphics/pokemon/flygon/icon.png b/graphics/pokemon/flygon/icon.png index 10788b2253f8662bd11c6dcecee0d9b9806a1e9b..f0c4e165ad0abe88a8650002f43c6e025399f79a 100644 GIT binary patch delta 377 zcmV-<0fzpt1H%K57#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SK}keGR7i>KltGq+ zFbG6_uR&%5b^qHAkf;Q8cC%|-blUnMh*I13jfVhmte#ae3=!x1eAfrS0R-0zNMcBV+0)lDUMQl{d-_u!uk~4vUJUL{pVZp{EzdXpFOH#n z>vT?KHIVKwIT+PIdMeLQ3?x7N)nQN##N}PEI!rYXNK77B7Kf<@l6nBE!(0Y(0*l36 z1~T+`rggec14$r!qD}8%AmI<`BizUPG!V_=?!ac#KvK?i%TNr&r-%MD5T>tz^!k4R XSMD5N-7zqRe0001qplF?uEArWj zjxb-0DJx4XCECr9C3YQc>j)~7{oTG??qsp;D`Z&MevF-nG}v8I@n8rN|1m%$V3zQf zfmsRihJjgd5uSk|?UO|j7|_+22x3xTMpaEr5Ca46!AJx}V4}fgAObTgWtK%pU`BPY zLoy%$LzjaAxpX!I(-^xMF98^`Fv!2a4EO*{@l?S40)J=pXj+Z*SO5S307*qoM6N<$ Ef?vO(Z2$lO diff --git a/graphics/pokemon/groudon/icon.png b/graphics/pokemon/groudon/icon.png index 1c237537b6e80268033616117c154b238987cf41..69326145ca14df7079d5b2fd4884aca7ccb0b988 100644 GIT binary patch delta 363 zcmV-x0hIop1GNK?7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SGf6~2R7i>KRKa$G zFbpI1>fG%A|JzC;9V-NS*n8Ur=N2i7?0}Z#uB}Sz0`FR%2w8Q)sSqJ5a!#p%gV6hg zG8_~xiSRslsnB{r!_(alPFBL>D?3rE4!08qF6d#^h>Ng|2GTU(fU1cA`rBx#S@V{_ zNJzBfBqY~hu$l;e#Z7vN)T-g3wU$7Mb6!SI!IB$K4jHP@NGfO?;;>`lED@3|Kuwq6 zytx>*;;`wo$fH(8jT{Qb3$TGnCSFdj@;c8ROjfW1oRdUiVyqyR#W<3A^E z{2U;jNq@6v*XBB+IQ{;p^P1oZ13qm3;D?*8@Vl<+4v^(a{{p0bA0TxI5axpdgpMZx zqQFpqaOlQgbQd5o0^~a%b^*eCP=IXtun!PZfPBaYCCFdr!xM;9Bz2R}+P(k)002ov JPDHLkV1nCoryu|T delta 340 zcmV-a0jvJC1D*qr7zqRe0001qplF?uEbkfsv7$QeD~6?eTbQ#mCOrl!t2v}KKf?0I0vt?q}Eng8%0trih4-u4zYiI z8y&;l!^sax&jmHjoFm}ihtN#9>$)xqZaA1E>6JUem8BIV4ea1`6H3WoD<-YAjR|wO zC+t4kl3DR&jp^je53ef_0BRR2H$7<>;5R$y?7z+l>d2^@h@$f^|>7lB#$Sb-sP mIWK%*1tyc}Eg$$vK0W}U7&xn8e>2|z0000T7#0Wv0000?P=%ZT0004VQb$4nuFf3kks(BXNQv!KL9&BT28dR{ZW1v>UT(KvT^4W-Z7AZ50s~YL%E!_ZJFc3U5h@z^3!7)FrhM6te}3#2@xKGfpBraE>NtD=0000< KMNUMnLSTaK%ZDle delta 299 zcmV+`0o4A71Ns7x7zqRe0001qplF?uE<}Ggjn$H|Zo?oDhIxZ~n{=t#hp_}pgNI0F zvE+x#;DxxGw<|*=cRGwzDJ*el-2{yL0#87IEp}$O}%C2_N>n zqcMA%Nq6>CW;ZFr_0+3ui(_yRneZ#BhOH|&_KynI)4BjASD@h&kB{;I28;dO5`jsM x2uwO70+UiU0w(+c297f@w0zZ!!>|`M4&SJl>^qAptQ7zN002ovPDHLkV1o5zi-Z6G diff --git a/graphics/pokemon/lairon/icon.png b/graphics/pokemon/lairon/icon.png index 24bea9dfdc19b75eda89cf7eab1160c64b737ec0..27cb6edaa3edc97fb4879a499c624b6cf7e6129d 100644 GIT binary patch delta 318 zcmV-E0m1(H0*C{U7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S21!IgR7i>KRLc&- zAPk$6?y^Jt|9?9N_5#9oowOmLR@gCw);^v7<68&W=MJPhbJn;3Hw)9O7{ZML;W-xu zX#zxWhhx>CmPIhh2o`(RP<`UoFcQqSL7)*LEV}>#gorPM$P;L(<06C}13>~=Zz(Sv z=F=A0TiaNLv0g=g_Ndk4u-rflai%Wv2nWxWr*n$Um4GIkt?JsA52p4JL8+s-=YH3% ziXOiG+z;YA{6BtWeEJW1EbIfMxu4qrxw(HEAP@KN0_4U0Wq=IsuL5LnKZ^hv+>ata z2KS=~kjeeXPUir5y1&OmEN$G}j}{A|D<-?n_=Xd7A6``3Bh!OOm QNdN!<07*qoM6N<$f=n5bbN~PV delta 303 zcmV+~0nq-41Nj1w7zqRe0001qplF?uEb^l5JmR}Xx60onfO0`LNm7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S?ny*JR7i>Kl)(9w3EuziffQF4vdSG^rJ51cgN3OYucK6u8 z&3#a?&QvzY#W`PA<(qLS*ynORomYKW|B8Rdr}6Iuv-oevP)y_B{~%`Z&*@ypKXEs> sZ}G4BH=Yc;_>cIox#E9V{XYIrI?xmpZJVDo00000NkvWtM6N<$g2Wh&pa1{> delta 286 zcmV+(0pb4e0_Xye7zqRe0001qplF?uE_YWyJR_H+o z1^pC5AeJnfIgYMU7ivPAZI2+iA`dQD%N*bJd3CSnin>)p_G5l zP0U;`O=+Zov%Ja}%0NN2)lK)gt>;v)ck6^HA}*O06@^7wLdH6UfR z+*RfFId*-IOo~FXa4Kz9!vvVAP6qoM>mwcPjX(zrybe|vuLA)!)d6HL%%}rM`~OY{ kP|OPBbQojuzdF1Cj&rAgQhtX!000UA07*qoM6N<$f}(DB?*IS* diff --git a/graphics/pokemon/latios/icon.png b/graphics/pokemon/latios/icon.png index 95590eb52d691e35fa7589f62be39556394a1423..d63fb4710ea47b6b753866887a8244a9edbe6765 100644 GIT binary patch delta 305 zcmV-10nYyO0{a4x7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S`AI}UR7i>KRLc&7 zKnOID7)ToC|NpkIt6jPeo1VN#^q@1sfXr^&6MqMAfyGU{WPq@N*8~t5z}yj9NvN`o zxSY?hm*_xfxL4Zd;00000NkvXXu0mjf DxTcXS delta 297 zcmV+^0oMNe0`mfp7zqRe0001qplF?uEjok>or|C2$rgY&TmZ< zTwqD9-QJIv<~ej_0ajIZ(&tsSKpfA#ai1xEKmLG&j|2x_5pnS52@W2Zh=X7UOvGUr v_lN@<|EMDl=V96&2QWHL!Qo*4Ar2KE6b-iBKvW{~00000NkvXXu0mjfO^$(g diff --git a/graphics/pokemon/lileep/icon.png b/graphics/pokemon/lileep/icon.png index 0f3132ed4324b7ba57a130578d50298868ff7684..034453bf99a581d3296221cf8b69cebb7edf5866 100644 GIT binary patch delta 297 zcmV+^0oMNE0`mfp7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S@kvBMR7i>Kl)(}#3EuI^rHxrRYZzribB}T?tmVJKm`1! z@01M;gY8D7_i0dnr{l0=ILmTfvbSIYDMdJr=#JKyvCzE^6`rjF0pZ|d&JU}2>bL4} zm^uPvcX@AsgqL>&NN{RQr_1-pe0Tu`)fMJ^$>K)<00008NkvXXu0mjfpyGl~ delta 279 zcmV+y0qFko0^tIX7zqRe0001qplF?uE`OdZu6fZ>@sswQBn`58>Wq(Qu(ypSfPKu~_FKv2F6 d0r)B(FB)9Ax(fW5l>h($07*qoM6LruV1h=-ev<$I diff --git a/graphics/pokemon/manectric/icon.png b/graphics/pokemon/manectric/icon.png index 5379bbafa1a5816567134eeee8a9cec1564b2420..5d7f3e95085295a66da64031dfa1d0b694f7661b 100644 GIT binary patch delta 264 zcmV+j0r&p30@DJJ7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S(Md!>R7i>Kl(7!O zAPhvK23H;|?*IR`XCP4p4lEry;4GEyaW*#faqJiZSm+{i0+MC`XfOjHS<;mw;z0ER zU;#mZdL<&D88kpg0!0-T0+t&AuBti!fvWZd0ezq9IdY;!-&EJne3~bM8MN;yn`jKy zsY+e=^@N$KpQmnT-qT?$K)FaR1`>{qiF0lSA;HpJZYjcXRH9rm94o8vEAq!{=+kXc zl0O*mAlS>v!{k8{i)Xod*gJj`dx7i)@(t7lg2%B{0`*@U=-$r%+z%g^%M?*AMLQz^ O0000C^u&>rVA)GOy))-*aC@&KR6%mY zFbE6D#dti{|9@LBb~2&hnI76+mc49NG7+q$2&K^3$+uCQM}xwp(+M~!M!-e#rCe1&#{j8FYfw-d^rsg= z^iKt&l<>y2^vqy?1T%~sUD_1mc!*=-g+0UYHgOq~-|razf-O&nlrcJWr*JI}g0l|l zT0GCX59zVFSiR#7zqRe0001qplF?uEB&9- zQCDt%19VM5dkN4m5LT{dlf>!RDk+DK0j8OoZTMLY-P&D48G949DSIIgOedP_RW98 z1iFeVh{%J__pA|!=8tH7ha%eI;wpF`4f4}K;s%awZb^9 z;LO~5#qDZ}KgRlR7o^p`Q%k}=EOY?Lpfu*ZTl&F2S0k2Z7+f&SwcwoUIdU5!gL)H5 zw%IDU-_^(1v~~6al)Rv6o)D&DzE(<)hWbwtMlg81Ni2*NDF^WABiUTZ)_x#Zn*FF? w2;77bDfI~)y&eiO`jLgXuECGRjDF$AH{YYAwF{lytpET307*qoM6N<$f=#`tF#rGn diff --git a/graphics/pokemon/medicham/icon.png b/graphics/pokemon/medicham/icon.png index 9e4bbc27cd9c616db92cf7c00ad1f3646cc1e121..79883928382f12697a7bf1a61a362e78390a600c 100644 GIT binary patch delta 261 zcmV+g0s8*H0?-1G7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S&PhZ;R7i>Kl(7!O zFbG5=2n-(J|Npj!ld7o#v|TDy4HDBmgADd9%b$k(3w?~9@S!c>*6NN1)&P(ZWeFUY zNfdzVEFfhG06JwY31UUCmR+2g&6&zs1;9*X<+Oc-Uf(j(YaK@;nK$wb7zKhJfgqC> zZbH0@Z?{R?2(2+>ZLqnnDibKTA*w63Athj{hJ8r0aEt-#=$?!(^{DPlGJ;c;E8d99 zKz_hL=AUQ`WOtC=KvKXC29iQg29kfThk@h{b1;y?VZLS{ANs=${ZJ6B-nDU}00000 LNkvXXu0mjf*uiay delta 245 zcmVA>07zqRe0001qplF?uExpBhc?P z=!sN>cSN!%R79?BCGf8HG85+I+LJtjS!XrCbjIphOk^L>0$aHsY_Q1YmANLiOOavm znF2mdmW-JwbDlb4aSfC!r-vyvlq=9|eXi#Zmr}nFgX(NZEh1nz20ya?R+#&*Xkj4X vK^Os!4`Bovg~3=DVbCayH0U#7-uB}L1*nB&s4Sd$00000NkvXXu0mjf^SEfF diff --git a/graphics/pokemon/metang/icon.png b/graphics/pokemon/metang/icon.png index 3916b65310dcfb481570e48999f2224376698704..8d27afff4f3f024b87a3046a24b7bb1bce7105d5 100644 GIT binary patch delta 342 zcmV-c0jd6^1E2$t7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S9!W$&R7i>KlfjOI zFbqWNMB7KnKjbMNTc6V*-r%-k&X6GaGtxYvd_PC!?gqn`~ zLabTaMqv{3M{5j-i&t<3;mLqv59%1~NX#X8=_LXAR&)5W@49d#=BL8~uB#zw}P^m)@!V(mT~Z^v?7(f9bvIe@0gQN4+ogpN}%? ozv?~df1&rN|E1oC{{KzyABol-SrbkFW&i*H07*qoM6N<$g7YM$bN~PV delta 346 zcmV-g0j2(+1Ed3x7zqRe0001qplF?uEV%HdKV9EmD*Z7r63`W=k<0RB}W%};j(0gY+?AUN?x6r$SC z7@S2alrWJyahVpW5Um01ro6c&@zw~cGE>qk5?|&kkUW!0GGCP&@Jp}urBbR6mmYt- zRXhr>T9ucVw*{QKA&NiVWgR}z(nA=XnyYTU1KWG1W*$srL5uk|D{oSf=~nd{fSzl8 zW?i2cfIVl7FirL^Mk0cdiQ`fLM!_tAag$pCoZ{93FkI{_fC&D2{i*}GI#iAhSh+e# zTL-vvTLKl-rJj zFbqVInu}zmp8x;b`Vt^c!b7FiKGmhr%7bl&XjSA}y6C?{9 zh%=f2MK6-D8fmBiGpM+kI;AL58(k8Qx!RMcLi;DTbSP0h{C!9p9V0%Zg^sDgJS`mb zbSZ!-mSy8M6xgEEF2@q+Ci~Ad|BHW$zXwRf!wQfM9wI<AoAf0Kzsl$;~}c)5IO_^0000(S)peRr|#CVy}>fS;Qr(1W9$!CWZ>3o zFbrB$ZxtN7wDWf*jBVP-9FPDz=}_=dc$a#NjWVHUUUWPi46jyO?V#`8s1rzg(&&FJ zUhI^FJE@+nWAJ`FiexiN8Bt(?mwgu6dmHhL7c>mW=F?8)+-12;UE6Tr4ocb)ZLIB3 z6dRy1pi%wK8h+pd?YLUKm)68kJ{r25I*qbX4hluCaF!AU6M3OBGz z58Dp{=sfdbl^Y&32})-^h7Gx1Pni$h=YZtGhgl-5i4SuNG7=xF6j${Hsk;&%=YBR~ Q4FCWD07*qoM6N<$g1a}gkpKVy diff --git a/graphics/pokemon/pelipper/icon.png b/graphics/pokemon/pelipper/icon.png index 43ae7c2760806e5b7a62b62e721aa0c4937f5644..49debae7177426b50540d81b8ad7e7846d70283b 100644 GIT binary patch delta 332 zcmV-S0ki&x1C|4j7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S6iGxuR7i>KRLc&- zFbL~HI?+r0|9?9IeFTzb(zHoC)IIcI*M$T;O*ei56pZM3o^!rb7@bnOQivcY5?ou9 z&j-8+2$Ti}%tBvSl=hZ|8KgzTUIAVV{8R<`PLyUnq$e96S~X5!Wl(z-;KEB8B9JnW zI5;fWtJFHt8d!yYya}keF>r-PY$7U(MSG=KPeCHNw&o{g5RAt7X;13nLsZBFU{aZWmKr~?GZZf0Q1a0E!1$}n}R*aO7oIus-8b_59NX7~iC z0wifZ1Udvr+J%hCvX8m?*gO~Q9eMp6Hz`u%7#xX5nh3wVy*d(KzrQ+r0Z~= ehrFh5ZvPAKY!sn-xZkG$0000b^l5JmR{nIbnZ2e8Cw zYox@z8(gPbrQ1WSv|=mT<%TIOTN~jf6Kog+E|NN#?tk%N{QVAxKQ=&A>&MWIr4e+~ zR)!X+s>n-&RRmsVQ5pUsL=ho!W=14FLpSH#6%o@raC4UE9Z|M9@p(EMiFp&Sr}KYe z6izl73(;~n7AL;cJ9jt1P;7wN=2_;|{ASG9=fyu(V>;@b(S5k%OY671`$#l`9&#p? z(vP(PJN<9wXJCLBm~`sVQ3Qs%=)jD$0`sJYR5PGjfeE#9snZ4wB9|J05!kX$z{vDS z21eDu6h;IF_rP4Rsev)F*#ToX!N4gPpT9Q(V@+8=(B7ASe+349X_e<2#XPQ#u5eU@ P00000NkvXXu0mjfISGvt diff --git a/graphics/pokemon/salamence/icon.png b/graphics/pokemon/salamence/icon.png index 16cdf981f4926a7fcc1de42ea6db07a4eefafc98..74b4ae776abf62bd8932e146f73a39b7d084fc95 100644 GIT binary patch delta 346 zcmV-g0j2($1Ed3x7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SB1uF+R7i>Kl+mt( zFbqRkD@6&4;{X5K>$FhHCN^DZZ^I7*;j=Ueo0sL*{{-sN$`7F$^h!b-kw`eOQfCC( z2o?!|xtHyhsQ3Wwq~@N8OQ7*5V^f1yn$w*46+W(d{KSzm)zy zNkrckpIMn&#J&>FyAxMGL2SUaP_4cNu8ZILitYe82M9hn1_(X`$dM0IfUK*Oo(<=G sIR2WY^Z>cc2i|E5koWlz@w@r(2X0O#d0zv)&;S4c07*qoM6N<$f`03ka{vGU delta 336 zcmV-W0k8g~1DXSn7zqRe0001qplF?uER|oE3z?SfUCpzb|E~QS)-E{SM09sCrNkK zShVyzQ*9HXRDurOK%noErB62D);DY(LfO513JAJ})433{Ug|9OVEsM6v}E{3`-tM4 zp**n^tKzZCWVc$mEc|^+5HNh{@@YH-2L1o0rX);07KX>dct1K}qHD3E_ruRnT%@~! iAHdp<{dhf0&W|54S4oiKltFI9 zAPhxgb%U|wfB)OgHxmX7$yBP;MXPak@xvGk-f?{5Hv{+%sFwuLSEB9&lfroZhin9j zidYAN$N;qPGw}gr0xfU70D)Wrs`iCyisNh)k_(7gt>y}%5>zJO1l(OUdSR!9q|HE$ z5vZyQG|tK@?ipZz)65f)HVqyp_t1(ke@3id2UVl5hC~rhJDf$>tDS&j%O9^illulw zpdB^xdVL+xMnRz5T^Ft`z`N@-ZpMIW0VR()(GCVliq z^6Q`U(e$wTVb(_pV)4VQ4^`RyF!bT*&p-KL(#PqK)el1=AGdz!`ndN))5kyd!vjOD V7RotH21Wn?002ovPDHLkV1oG}lLG(% delta 301 zcmV+|0n+}B1NQ=u7zqRe0001qplF?uEZt~5I|9GFq$@z)<@a% zQAO@RD=j@KH~(?0IMFKRa2^nbbJ#f~F9nC>v3`7lr zDKDM>|J$8H$VM(@lifGB8e^QXr6ru>cxV6{U3>#1e`nYy$k}x;!KOl9W`MPiVvy-1 zC;_6TGbRoiRNgUjXp$IHq^hbjLt<2!k8!0)F(pf`iyGiZOF*5kW3MQ`CF;m_OW!Nb zP%MfIf>{-uB{YM5m(>}j1zJJ~HY%Ih*rrY5vY=_PUpOhViiXvO+B$%+)Z3OihGyFs z{_$Bn8X(vKq}28RVg?@|Ja0Zg@Oyw@)b9Z4nw#L#BSAWVOle#Ja`^x;eRcjD kVb*-8gz*4U*LGjv3*r$J8c63G*#H0l07*qoM6N<$f+je4CjbBd delta 273 zcmV+s0q*|p0^tIX7zqRe0001qplF?uE<}Ggjm?rV3c^4TMRS9>Lk^(ef~8%+0~oNj z$Vn8wO}2F#b2mXTO$-UjZnY+mWU~XJl{(#g=I{JjUJ!h>EbB=!L1%9S+LugFY(gtG zVY~@jl2M0I5R>U#0nTKOXv;;T^EO(dxH%z?n;tI8Jz68h=n;(-t`b8O0(Pl97|4B2 zp&5`qw03)HAr@J7gdIHfEXTgNl7fKwS9S`aLkj zfoc3cFr+vzh67_i2BzOL0E13(!1Sgb7&&-4VB9$^FdGI;GMV~;2i diff --git a/graphics/pokemon/shiftry/icon.png b/graphics/pokemon/shiftry/icon.png index 14b4bdab6ab77fef9955db78c56ac63f9cbb6908..3d2be13a6852587ce145da424e68055b05aea63d 100644 GIT binary patch delta 385 zcmV-{0e=3r1Iq)D7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SNl8ROR7i>KRMC#Z zAPidq1nnjH|GzyO+6}tG-Rnt zmmrJ?GY`F?95^?qp{g^Z%R@gUH{x=^bME^m5m#586_D`Qf8#Il?+xU@mj?3M|K31gj_KVP2u5vdAk5zyNE?Km zfpmqPf%F;UIratubTW`ngW=c?2119~8A#3?@UfYGHIO`gvet;Jf!zATU?An*Bi;tG fynDYG$OZZVIAI$m;pI8u00000NkvXXu0mjf{S~w| delta 364 zcmV-y0h9jA1GWQ@7zqRe0001qplF?uEbsT(VRgu+abAsWOD|^kDTxB6tf{+!i#?} z$(LdQ3tfrHG^lqLAJklu38*{9&d@MP$D+>+Rm^U5)v~Zd9J>9!=Zx`9 zPm-42qCxtb9)TZ7{z3eOFk~al)L~d9j6MHG7(DsH&}<`&J)19#&DaQIpMEP$!<;Y{ z%)%Ha3}WC5lNIj#)GWf}ZhGs-BFxHPbXFR7i>KR6z>E zFbpdV$dH5e|KH9|mo{;dj$HXahYj@?Sz_Tc|O@}3rv8wnu}@DOiS=HPJ6FVso?v<>;#%o1*L_CIjp}6><+aA z;vhDJAZJ%}Te(VqWMi2!N_W@TRyswtYpC*Er)?!R0m``bISrr2OShv%{=tJU5PqkT z9)I+X$7TO@KD_O}&WCFMRX&{dU*tn$|7kw7_MhiNV}E!&#C+)NKZ%Fl{+Mm8vHvt4 og8e7)u!Zk6iH9iv!2b|0;ztt7x(>cD00000NkvXXu0mh|f~g6I9smFU delta 274 zcmV+t0qy?m0^I_T7zqRe0001qplF?uE5m z?lPU-ZEizB!KIKWD8fic;|{NhXV4@iq5^k$`i_61*EHWXpsQ!$B}vQ_8;CC|2HGe( z#=ODw=r$u0W&#-CJcWeB!9gEnV3eMD?~ydH&1i4Z46bN^kZz^N8F@k$OJt%KI$nO* z>&){wp6&-yMQZcT=`e|%)NWgL`aV3<_gLDiAB4Al)(;NoQU~*cVhz%)!@`e0(_!I< znhsL?@zkOA!*!_qa2+Z?Tn8M=8E_qhLuunWSe;NJvkscLD-qWL(r%>#wCm4~Yw)T0 Y2M{cy3}ioYx&QzG07*qoM6N<$f^*Y+ng9R* diff --git a/graphics/pokemon/solrock/icon.png b/graphics/pokemon/solrock/icon.png index 4a0410cb55d9afd00e0f985a84ea7bedf5bcdfd3..07a416c283246b82975a468c69a7bf27924f185a 100644 GIT binary patch delta 232 zcmVKlQ|N_ zFbG4#3`>XZf7{5o`yuu(Q&=qznZ;b!Q7i1?wjp2(0u|R+01QD@7C;dd2O4YuqXfKG z0+ld{KzaQJD=|u9`Y>QJ{lh#WNi>~c_)}>{qHSav7!}esF>3dKBVES0x>r~ME!=&S z)YX}cr6*^J=OeR64-zi@v>`PKN%qq(bnc+`VX7TbeUv>GE1%z?AHxK;e{u&L{i}2S ipE>_>IOqS(^S=SoY7gW9A5hi+0000<^TXR;HGLlNEI+_TH)F}r5fj2+>eCJyR_-ut;kL@0qLV~d90>lty2^1;- z3Jff5;5I0S%14!3g4MZ;&Xc2{p&OmZFECbaG&j$_u{MJ_*ThKU`{|%JLY*_Vm#0RT z3(Cn(*Fag3##k%r&0;2)?~yG4pK0`w=htA-GlF~A3BGm_=9tJ06w0G U<5S@u{Qv*}07*qoM6N<$g8B+wZ2$lO diff --git a/graphics/pokemon/swablu/icon.png b/graphics/pokemon/swablu/icon.png index c1aa25e996421e92170246dfeb4833486e3a8b7e..46be1f4033f1585999dd75f3f8680e96850c0187 100644 GIT binary patch delta 261 zcmV+g0s8*H0?-1G7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S&PhZ;R7i>KlsgW? zFbqQ-aZvz+y8mq}scmW?mNRt85U!;4G3?jcqdUs%!dJCr%4}D&-WPRD*{vu+G7{x+ zLWJH#S)6wt@cunVICo+Cs_%s9xeR3!0~8+M#E&7}hk6$lV>H9IK|6u>MzaKVb>AgL z!pEdQ>V!v(QA4U^z_HQF|6co}M}O*yAMNwwRs>1HtN@aPSv5++6dvQP*8mBE3;>z> zG5};wm;oSj!VCbZ2=fC-vE%`enhpVw;0LPj9RNuNm5H49c7%BWb(IU{H_d7_00000 LNkvXXu0mjfDlc%V delta 245 zcmVA>07zqRe0001qplF?uE!LbD6z zmI_i|uq10AD%e*DW^s_T&?Q6R#0d7TlZ%7kjeq_mH+(|;_^5FeWG9dX*rDg8d`A+< zBven2V-?WSg3)L1`{h|#L2kWA_pV$wQ+@Kc<&qqro-YGk^ssGXlSnchEr1E6lC5FZ zu&0+WfuTY9EAT)j@t=zQ8O6qYD@!$P_R{(5`@? vf(n>Go-JS)k8CRdT2UAQ8n&y{UljBJz%pYq8hqHC00000NkvXXu0mjf>i1_Y diff --git a/graphics/pokemon/swalot/icon.png b/graphics/pokemon/swalot/icon.png index 3611b27feea1fd75ad4cee5839fa44005d0ed6f9..09f7162d2a3399f4659bcc50c7a391cc9861267a 100644 GIT binary patch delta 236 zcmVKl+6mn zAPj_sp4^1w{oi);qp%RiUKY9w&LM}+r%79#){Y*MnzlBZFcNkkH$Ecn0Oc6rLWFj+ ziTMQp?ex)N4R{OcfY2_v!yu?^p-SXK8p$kFfo6cqT8a5mcW_sN@G6DScp5}hDNSsM z1hTHDNXHiYz{Q_SZ{lm=A9rJWVvhbt=kkB!^5<7VfZw})I*fRj>44*5rUQ mW;)<_h>%&1>Br?a^WhD)br{LC*g|>$0000 zWsg`8g?ZrXv!SQt}Q;1h;~UNfzOe$Wizo~mK4+TTX0 z0ql1nAFh91SFu4TTHxTU2YmEU8@exk*JGO?@z8@+n3{O#fpZf-q^fhOYrpm54L*O+ Ur#U^KBLDyZ07*qoM6N<$g31nD*8l(j diff --git a/graphics/pokemon/tropius/icon.png b/graphics/pokemon/tropius/icon.png index 647767ca3de1b28329db67c794779eed76fb908e..9e7b61b531a138941fd2398b1c0ca04525a639f0 100644 GIT binary patch delta 368 zcmV-$0gwKw1G)o{7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SI7vi7R7i>Kl)(90L*ht8_>FW z#UEe>REQcuMr`l7XTlP zn76$sksT_z>nqDn!AYzd=%~X-dP}_fc>ZhqJIw4bX)G{LJIpEGJIvWYP7X5}$k|~Q z2GTps+CZAa+!=^F%$JOI&;$QaX26E{S_JKdF>}#OD^oJ*vb|9??h;h;Y O0000DxTHBye|DwxrDK%cA@r}MG@#wavCvGOGtqKl*1*h}==}rzKiEAj!%qKUx7|;6Tlzz}YwJG| jhW^SSQ-8gS|E~WFL{uA(?SW=X00000NkvXXu0mjf7nXzQ delta 288 zcmV+*0pI@U0_p;g7zqRe0001qplF?uEt)S8lfX6cx1}ce#E4_}jbf_mPX(Pe)j1gWNtXFi+c0C$OET+ z6sAAjce?G}gCU(*0Muz7H2A>yI8@I5H4e`05QoNf{t}0+`>=I?SlkcXxgX+SAD+Zv m87;)&W$lXM;3oY?9KK-K^x!41Ghhq=0000*Q%z2WKn$H5^a7usw{u}) zxEG1ufqkKI^R1}Ftw9(ztUA<^2y}4iM!Oi&m;Sy!LikgrG4}zx91*PVGawcerG)AF8G|PP(%YF;4gbP^%qew_7|*BU zw>6*i!Jg1HBpIjP7n;!PW66&nfF#$4*saIv004We+Gz(=a3REMD`Ha;%pys4!BB)- zQ9Q{u8dz?6EQ{2+KL9>n?D)&*)@Lv>eH;<%sG13;xePI7au_%!zwdPA2st6Y(8m|~ WLf$zUu8wX10000V71Dpep7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S8c9S!R7i>Kl)-Am zFbqU(39_KT=>Pw=BPCgOWxJuYr?R?*d6peHd98iw=jC^~+z?N|=b+00xZ4WoVB)sO zn|D>^auxgOE2s1km@5!2S;cJR;-B3qT_FFpF5?q2!!G z9MLrT2V2JKTx7d{WbS&G4f24^sI=+i_tbnxI`Xdr`CxmfY7=+vpzri1iZ_v4t5Kec*i zPm`a3Mqo5RpD+k|Dsj#L=~W(31aK(x-orrc52QMuS1>_$Ya%qGxoh(P4U26`HTkOit> zU{zeapy9?l9VvwX)nrng)0s#epxvJT$)YY8-9Z*WaUZ5mdc`2@$QAoSeb6#TCnm`D z9Qk5E;lJVt5En2Jtrf=O4;OwSSeQ`74=l`>Eq)+j=GBjzFuN~5Heu-MM{>KNB50lr zu Date: Sat, 1 Apr 2023 08:02:14 +0200 Subject: [PATCH 056/131] Fix gen 4 icons --- graphics/pokemon/arceus/icon.png | Bin 397 -> 423 bytes graphics/pokemon/azelf/icon.png | Bin 429 -> 425 bytes graphics/pokemon/chatot/icon.png | Bin 384 -> 337 bytes graphics/pokemon/cherrim/icon.png | Bin 266 -> 280 bytes graphics/pokemon/cresselia/icon.png | Bin 474 -> 482 bytes graphics/pokemon/darkrai/icon.png | Bin 474 -> 481 bytes graphics/pokemon/dialga/icon.png | Bin 450 -> 480 bytes graphics/pokemon/drifblim/icon.png | Bin 389 -> 381 bytes graphics/pokemon/empoleon/icon.png | Bin 368 -> 384 bytes graphics/pokemon/froslass/icon.png | Bin 366 -> 376 bytes graphics/pokemon/gallade/icon.png | Bin 360 -> 378 bytes graphics/pokemon/giratina/icon.png | Bin 442 -> 465 bytes graphics/pokemon/gliscor/icon.png | Bin 458 -> 492 bytes graphics/pokemon/infernape/icon.png | Bin 510 -> 518 bytes graphics/pokemon/leafeon/icon.png | Bin 399 -> 408 bytes graphics/pokemon/luxray/icon.png | Bin 449 -> 462 bytes graphics/pokemon/manaphy/icon.png | Bin 351 -> 373 bytes graphics/pokemon/mesprit/icon.png | Bin 455 -> 441 bytes graphics/pokemon/mismagius/icon.png | Bin 379 -> 399 bytes graphics/pokemon/monferno/icon.png | Bin 435 -> 446 bytes graphics/pokemon/mothim/icon.png | Bin 425 -> 435 bytes graphics/pokemon/palkia/icon.png | Bin 437 -> 461 bytes graphics/pokemon/phione/icon.png | Bin 332 -> 345 bytes graphics/pokemon/probopass/icon.png | Bin 399 -> 408 bytes graphics/pokemon/rotom/icon.png | Bin 387 -> 395 bytes graphics/pokemon/staraptor/icon.png | Bin 446 -> 432 bytes graphics/pokemon/staravia/icon.png | Bin 388 -> 381 bytes graphics/pokemon/wormadam/icon.png | Bin 374 -> 374 bytes graphics/pokemon/wormadam/sandy_cloak/icon.png | Bin 423 -> 385 bytes graphics/pokemon/wormadam/trash_cloak/icon.png | Bin 406 -> 370 bytes 30 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/arceus/icon.png b/graphics/pokemon/arceus/icon.png index 155bfc35bdb7bea870e2a37805ea174d55befe79..6141c35e8c926a862374753d37273d70b7660e5a 100644 GIT binary patch delta 349 zcmV-j0iynm1E&L!7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SB}qgKlu>WP zFbISTEDsy_U-0N}Z)B(Y<+q;PO z07stg68r=pnCJdD=|@8@4KQ?+A4`|qbAOK=m0l|~0|qM*e&{*^`PDS_$8ljrY}I6X zZ05{EKLzk70C&}Y2(twI3=sBi?D*N>kC%@PV@l9-mx#IogT*wkU=-k--9p4+%Shpp zkdUGRttwX!00h~x23qyH5mZT92CGh#6XnpFgHA+H0-TRS_y>-_Kqd=JNQm~^2=nLw zz28sNZO%_l~ zIg-Ep?33+}v0p6GcXPZ2 zfGcleM~#aK7|lpv<$;K>Fg^%SU_0zd-RB9fVCY4N1(N+qW3L)*Y51g7k#qsr^?-jh zuM&9=Qp7D*8a8U#x3b`6D~|h1ruYcr>dbkWmhv?AZb@;JlIM{-OehqJoD1$wOcdfg zJLbzN62@6s%4e4_CP+^64|NShvl^rQM!k&*Sj>#j?OMLOB@M-ahC|*=U}u+W0tWz6 zx1Xzv{tf_pQ2nJaeR;yTj!qc+VvH~O!cgbQjW9`<_z%J~cfuSzKL%mEOKyJR#~0)_ VR7i>Kl)-KT zF$hF0IbGoug8%>94kpbOgI7KDQZ?kZGaihCUTgoa6m=^TYU^-$Z+OZyHij>K7x2>E zkX)BO9h!2K&hgCwf1Foo^dlG!64qciPMcsLXAlBT82Cz=Um$-xx;ezIBz*7{qVssy zM@Il6)B?`X#7=g9=*)1KUzx)w_Rxdn+1ch)US?GlAr^lq5+tmSX5Wa_-ytO+*>tgk zf`HtC1y`Wyutv#XePNkrr3mm_`X%QK)&GtR{A?O2b?;)YEc?AtnyY!U+x7~#tN*Sa z)t>^$jlMz50+6(_D?k!rR)8eL6adMHSpbp{69Li+#4G?l$%qL6sS$Glq(n>rNQIaM xAks2}B0#Duya2K%hyz3|VM7pcPX8`JJ^@~tAMfcw(W3wW002ovPDHLkV1k;=mDB(L delta 355 zcmV-p0i6D+1FZv)7zqRe0001qplF?uEPtw^d_O2eUD#fcWO8wyz+0}@CS62dr zT5kmog54P|g5Mg#3@9dkTP%PQJ)p0n@MyXu+@n5W!%v1558zop9~$k@e2|YrPq%*u ztt}5=bu zMp{>9DwxAi4xd>Q>3bR7CKE6{j#Y|c8SCH$c8B<{@7I8-43`;Dgb0kv8E0S=TS-C$ z#`E3ayR;-= zRtgtj#IFB?f&k3yHUz0Tklt4zv7oJT1}{~;z8_>x40>!3e)RwV002ovPDHLkV1l88 Bl%4

ua1JMGI7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&^R0MAK8K~zYI?Uca| zgdhw=g$gkwO#lCHx9ys^K*8I_gFSGWM>`74w!P&S-|2zZ2#2sn6cA*tBM5>8paU3l zf^9cX0NKkn-ghY?a5Wzov#$W3_+THV1H?A0*GmSnE+8QWmz;};#H4_TLx&%Lh@$fq zT;%uI2omUU0M6NFEXF8=1DJ8squbzQVu*-1rohG(b*ZPl*19-r^^x{;bLDQXlod+QcpLx# delta 311 zcmV-70m%N*0)PXM7zqRe0001qplF?uE@l08nuFc5`(gONEvEJ7b7 z+$SfXqo<=tk#lUvEmF{MB39a1TBX?+8^j82;UPlVtj9e_Q=d<~RvZcuE1YQItryz?AMnT4S2?>)^O6fJX6ILp|CK*2gnAzI08E+OvNE z&fcz5=ry*TtH%pCc0g$_KoMgo@tkh{el?5&(002K$9~?wiCgC`506R)d-ZQ3KZQ(2 zNM~gJO(Q@wT0U7Y450~=iU}YNUL`K1fUI5@_{lFt1PwSp3zxD}x9{N^=4CLoz59Th zHq0rocVBDY6VDQx*nyvb;igXPz!4*5HKv=;bya2lI2?Y{AK$>%ob>NwqtO5W002ov JPDHLkV1ispi*5h_ diff --git a/graphics/pokemon/cherrim/icon.png b/graphics/pokemon/cherrim/icon.png index 145074d7a3b26085ad1fb7b7b06110a2c24805b2..6915d775b4e5d11b6dae57ad782bb3b2f6695dd7 100644 GIT binary patch delta 205 zcmV;;05boI0+<4j7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SmPtfGR7i>Kl(7oH zFbG651r6By|G%x8c8j{SLm;=lhb9Qu+R1N0#()Ni4UEwtu>f>8VnK9;k60^UWeP=t zEmM$!&mp`rOaRE9z>xqZQbUEnAdgPT1qy_UH&8L4;C6}2ar6gQ{1%)Teds++Tk|Vb&InGXe3Nu}&B(DvBSw3+!ScJ!^6($`mW9f8z=t4;^#JhBIhEHGe9fk<;e#LUnx zDmt10+NTx^25(w+vxAxY2!IWs+v+#Fg9GScBGHo>_LG$!xfFYmvmUVF)|2a=d{HY) t|5Pz;5C#asJZgS3$O{Afv@rPGj~AJwqb$^$SEB#`002ovPDHLkV1jgjQI`M! diff --git a/graphics/pokemon/cresselia/icon.png b/graphics/pokemon/cresselia/icon.png index 76b9b36390deb598deed97a45d4f3f6cf7323b23..8189ad7d1658b3fbf8f4af24065a026a71f8d583 100644 GIT binary patch delta 408 zcmV;J0cZZ&1L6aa7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SU`a$lR7i>CltFI9 zAPhw#6{N^P{`bFazwH?U4w_(Arcm@z1m?3Zm`%)&roxiy;IIS z4&8Sr<~CZGqY@Aj1w=5#Imx%`1r&HnObJ*Lw3ZU-{Y=LcQL)_!>$#n4I*V~H-p0j+ zNSpHOaSKGMr-$@k$L|{E<{;sC;(fmbvKN(0 z+$#%#*p_7`B0(3(!jtjp2Z5~ha0=vB4=;iINDtqgYarZ28dVtp0000F34eNq_wzx>UoEQFfUm)39b(rZ zXZ9RIs|Y9-O3j87>Y>lX_W^hSm;i;&G6W%@&!9KVx9FM)+&gQS(*!3#D||5w!=`^p zXPEl!-R|`asAYV^DH7M`G?25~ZNTPQGPCt?Q9=!$rF^?P3B`C$44qMf5?}e-iBZA# zag-BqLa9B-Lp`=BK&aNTQJysloj|MauiH@~@#&w?7iy~7ce$2yk){p63?7jUw9lLmN-ZP_Grt#-gmKWVUf!~)^ZEgAs27=3D&r3T0000O@O>Hq)R1)Nb7opaVyQpvm)P_%Ph-#UO-0^}gLAD|Qn4jhA*l5-G%y&wiy zxUUemfLm#$2?p({Rnf4EE`c$=bKpP6pXaQ1AfGh#XQnY1RU5jWC#3$;9e4lgw84#C|I5^FM zE+EKhQ#PGDhi#h$AQK+ie1h#nh?0*pIXJ6e+36*~sPT9KTN+ac+wlS>n=uQ3Wb=P9 zgjQD|Krsu4b#&}`%ENH~vF_sFSChc)@$=F*IN)^k?m*Xf?;DWm?-#+J7w>8A!?(z; z>sNF2{I$RCpBS?sbbWh#W@3tViIxJdyH4l65s~!q=q{ZWA>LxE2Lv_njm!ll_|lOmch)i~+I) zCN-o017lNXV3J$`WA+zdv{5EtEmXjaP8DEi%DXKvW@ZJ9Dm5^%0Ao0er5P})C@^vA uj{`=mfMEk>;XiW?jM6|PH4%S!S&Uzw9Zc+v_Zjy90000KR6$Y$ zF$`;L=fc7I|8J3;v`sewP7DLX&USi`BHMCSx7+V}0KN4)!Ux6Fx~2yGObgpyC21twu>6WN2X z1g!dXadK(XBU}}Kx(H&JHCz3VId39Jf(;SB`|&WTW?&^CB1owMlfx!$%ov?u{bens z-w6Pc6(Ph2k4uUEuxhwRLTDG!xs>2$;$Asy; z2O6I>YSa^h{xrxfkz?zDC)@Ob45J(_=aWVoCc(pFCy;@4p-o%-gtN}n#(r%v@8hO@ zb?d6VF*fZ#_WTFP4+hAy$zy=jMV@0G1B74UJz{RB0EtV290FwfdY1sv*MGejuK{w% zhc!UX`LG1Y2l=oD$T=S>Kt9a}diF&=;2ZMc9mO{uWGhh#bpQYW07*qoM6N<$f-v&5 ALI3~& delta 376 zcmV-;0f+wJ1HuE47zqRe0001qplF?uEn)g(4d#^V&s-S-XObEOErQd znBvq{8fiOag>2c$$|IoJa8rQ5UbTdyOS#P^i@COibQqRr}R)I9wxXbMbDu%`t$e?z)VFK zz##C?!1(d}0?hr~4`9+QBQQ1h>6Q_g2Okj_zu;p61}*p)CSaC)m{&eLdF8|ZfRAtG WmIue5Afs{s0000VqCXHXO9=0aF*rY3W%$|On?mJjFe^sQm&Owh-TFwJOU;FwDf>6@g5*GQ86t6&}a-((G?ift(5gvGu_^=jqf5DHcQaAdv+IYAHMn@laW!C$$+|Bn~?feR6+y z#$Am&+-(5uxbzSb=E05tXU07)m*Xv6s~XjIIS&Zm6?b#H!%p`Aylxme^Vxf)V0>KL?H63Boaa;r2tOf|Kj{BVK~3M4#MQj!zZ&KltB)J zFbGA}LQ*#T``>mxwUdmM>Sk6(7B0#YD4Mq{4-DMp^_qZO0)VQ@oPe-^UX*|cS^-QL zh;v5AY|tnm0n7$%1%!aAr^Mc&I-hKlAng(aDl53vGr<{nN3*I-C;7HUEhwsao^4%Y zQ7xY|@R*L9W)H-FGRC}_@!a-w#E8Vjuvsl-^_@5`16u%Vyo?E8)k-63N(8VKF99@S zoI-eB)~FB!cRp?duS-i{d~AG)DXXfb^60jl6LiuRtCk5R3vD^E8L~uRs!i zFb)Dq+6)3o{csS-KtK)x$qaH7NNNy#{eg)=g6V$1|NQV30mB6vY7rdxlmGw#07*qo IM6N<$f=#Z1H~;_u delta 294 zcmV+>0one51MmWn7zqRe0001qplF?uEX7is5*1-0w4~|O! z7S#d_16E6*${zC2z!m4U@HSMO*TTD1jJyDjEK36F=sG0Rrw$y=r)jcNaR2(DQ>%YW zC8B9kf*8xTnPTbK%GvLU0s(F&}CP@u;jpe7vv`51hyw~O$4BHQ4s5|E@Z^` zMshmMCjL+cmkkTn-v>y3C+X)OYCVrI@*_+D(6)RRhU3eM%);<5VKP5vVS++%n1z|5 sQ!)#qDa-~wPb^xeVddtB{K=0i0=g39+dMu*JOBUy07*qoM6N<$g4eBv%>V!Z diff --git a/graphics/pokemon/froslass/icon.png b/graphics/pokemon/froslass/icon.png index dfaec88ceb5d4edcb9e5f6db4d0447f26f6adea3..2869fb8de14d36f3c07b30086270477dfffd0a59 100644 GIT binary patch delta 302 zcmV+}0nz^M0{8-u7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S_DMuRR7i>Kl)Dnc zFbD(_ZlaOK68Haq8<3nw0Z!7SGKCv4*QCD#{pRPyt1d#I81WjEHJ^gXeG+0z*p%e9 z#e@yXq0p_A7!V787XwNRP-J-Dt||zsq&dVf(Cq)G3fR;A??IQ@#l#5yVpeEflZW z&Kw<=SwVa?y8qYgyD*l(uP}B8O`KluHi7 zAPfZqm?gaX-?sh$QNSddN?kPGw2G&Wd7^V1|5pGWfEe!)1{iq)ZU|Hb!j1qDcZqg@ z_K9-d5s-eCA{Vd$3iwAAp!I8V5f}i3#N`kM0Eq#cFwa2{prqJ-j(i1BK^c-$)CtH} zfR`j_@rQh!j%)pY1BK+VAoGB#jZ%umFc0V}GeL=?MyBj$k%%+|Z2ED8POx170000`jm^j%2o`$PfIN`vEhI8 zYch-n3vAqD?bX7i@d5h!0WbhI`wZ)}GuGMY6027bTn@2B)J}0%$^*3ppq^YPcAqCL z@CIOj->W|m<~cJ86JB?wQ5Xw-di}dF7Ly-%3WG58^dmm|APiN)k5L#Ib`YkY3Bx2N kx`I2+;sEi;__-f9UK5X$tJV2A000UA07*qoM6N<$f?}9_Hvj+t diff --git a/graphics/pokemon/giratina/icon.png b/graphics/pokemon/giratina/icon.png index 7a6ba19e98762afcf46a6b8ae1802e24f70539b8..235ea4721e6cb91426e9ccfd9fe5c6f68d5ad7ab 100644 GIT binary patch delta 391 zcmV;20eJqp1JMJJ7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SPf0{UR7i>KR6%lt zFbs=B%+dP)Z)+)GOTt1=?ewsQSr{Zawv$yUpST8qXE*{kG=581cp1D2Z!Ys_@7;^_FcNl%)89fXzyV8_TKeGRj)QAJ}5=FO%Z z&$X?wRBBV)JWt4UVuB-7rbaPqS0zI6ol%#d6OzAt zToVv)5@sem7p6r%fGHR9+M3uhp8$Y!5#Mca&09wRM`S{}Pv>lO2zVOKl8e_LuBv~c zbASx=j0CV1IrsW<8UWQ894ws~q9g9qWh`>Q;cSW00L7&ouRTx|Z3y0I59Rc*(8Q(+ ze(PyBy>KH~ z%G7lpQK}jtH@39P5G9k++V+0Xap7FQ`w{Kl)-Mq zAPhvKu2?l#!vFubof(G!2}FD9X?-9l9t^hOZQIvAH}^U${3$udm4tpMJg0?30{Duh zWKNCCI==)8k)+{h#XCU@5oVUN`4|BU^WNOW+7?{r27&FCEZkaOj{ybz6c~^B-c9Rq z%;bjvUiiyT#%zCo{~FgTHyad)^P+^oT5dKhKxTyL0Wu@Z2#`Br@(7R%VI}~%5=PboWF$;H ze-}UyYC@PGIThf8mpfsO=Z{i|4>!UnMwClm7t^lyh5$ZW@Hr&@04EbBm9c}kDgXcg N07*qoM6N;tV1n$4w^9HA delta 384 zcmV-`0e}AN1Ih!C7zqRe0001qplF?uEX4v|FEde9o^ny@YU<_Wf1A-n1Q(*fc1ajoXQ>!RL zJtmF9*-e2RaM2~BfMdH~-^=ch5qS=fy$=sVFB01d(hcMs`T=uSaB+gdDCycGMzWmN z)=sU$Z@k#wk6SQR&=$-j=nhP}0b^``g3;g>j6UcV%p_<5Q-da`fia69%wSeQ4UAa@ zH8887v4L3xS-dqci=Y+EB1kXMz|4Y_gO}YguYzzPgmWCOf|Ns+!etSpC3+O)TW}Qv ey#(%ByNqw9#ZY^}4PSQv0000KmEDen zAPj}&r&PV@dH=WF7El2@yUAWplZnZkL$QT^ZreA!z+ZX+n&*0sB2>391xz$Ks#tX< z*40ch>kO0ZM_leaqd^K$2&$7fx*AfTkU~&hz2)_WW(X;%MVRGXfI3nS;lt|%N=mwM z)%Uv*m<;7S&te9DM*D}EF&N6J8BR;_=uat{O?8m&(G!Dt*aDQTPt2Ntvb7jfBariP z=n@u@Oj#YXzTwc&ghDY!(Owo_4&rF7fh3|Vg7NkHJ8n%+IVW9gXX*8-l$fGb4?VcI z0}>-*D;}AghNE67tyLe#zWcXRm)ctF_+U_}9u_`dZ|63Df8!r9+;g|1H$Q*{4{del zhl7WvUi|RKA2UDR<9`Fh@bJ8kwgn)j4_km%fGqiS z{0D##Ry@?{e*jYXFyjGY?XLjod{|1Xr>p?E_~4KK$OnJ?A3pfwKk-4w|2^I#A9j40 n|IUXEA3tv#oe#gndYgX$5f&M4y+&I900000NkvXXu0mjf2u{p8 delta 437 zcmV;m0ZRUc1pWh%7zqRe0001qplF?uE&ARgQv`dv!HVu#^Dwc>v- z-$LO66|Z{4lHJK4p6Au?cXQ}pP;WU=0Yn?Pd+9G91%ZI+G@#G)sm=+JY@`GDNjLpV zm7Q|^3p8cGyhTHREo^-=WAUnS-IKPkd^*EL?bL6@_TXGqv^{UGQts|f;Pvb(foSeZ zll1t6;h^gR+uAz|$-3jJ2ZUfK@^OEuvC!y3m6|j f_I&KM{Wl+9M-thOfd7V^xT(w#0*Z7TI;swfMO^#>q(MoKjdx{;U<0ZP zUK{=BB`G52b03OK3tiLQn}X3G6sz8Mx8WrYfwCOV)BIFGPmh*2d{TX_^DO!s?-{QG zNV7BoBuUW-dVusFa1W5w(J4Tqo{Qjhqz0mQBV;&+z- gnV*gX$Vd3_2k<=?h`9dUCjbBd07*qoM6N<$g74IqQ2+n{ delta 325 zcmV-L0lNN}1CIlc7#Rcu0001qplF={000DMK}|sb0I`n?{9y%=F+YC_Nkl(?T$iiV>=_xpW!CT-kc-OE!a-SK9yMj|^gFL%jm zEAlBKqjzcwFJ4ZT1b*;`?(pVPi+#wEzN*R0tthCPWLCc@XqwYy=jNfcl`V2s{Ezw- zF#XmE7*OAwfEms`00ZM}4h-k<{t+1BNK67|#clyioEU+zYXc!;OJHC>fYBK+SLNdy XFg(Wv>jNQY00000NkvXXu0mjfcrT6a diff --git a/graphics/pokemon/luxray/icon.png b/graphics/pokemon/luxray/icon.png index 20d02d897a13ad9b7658faddba1f47e2ef7309a7..9514dbc9b21280086cb805e914a149405341a8c2 100644 GIT binary patch delta 383 zcmV-_0f7F&1I`1G7#0Wv0000?P=%ZT0004VQb$4nuFf3kks(BXNQv!~%dW#93`Bzj z5s@s<|Nm|M0O9~`cXv@;7L^(ggKh9Rj-Ok=mw5UtK>8q%2zVBR6Twh}#JGb%i2{ZS z)B?53?3vgBtcfs( zR+28URYg?`>wdgBu9dA(Y(gxrXVeO+iPnc9j%K087tu8K1;)9Lx z{$_x{GLF+f0Yt~w0PzkWmaF)OwoCv?ZH&Y82Y?JdJn#?z()sY5kpYmK5A$_4fV}5} dZ2e(Aya3^m9QO*T^Edzi002ovPDHLkV1k#Nt=|9u delta 370 zcmV-&0ge971Hl837zqRe0001qplF?uE<}Ggjm46&PQ)+_K=TKdca(e$8)BkNC)oIw zo9N2M&vamjbl;E#bwG_XoODR17&~cmy%Q6|k)f)e65DZ}G1pss5rew`=^PM*1pw(M z0$M5|?+ch1kwEf7cUwSCh@4RV_uaFAL!ZzhY8rUx$iSOyK$oI|Cl=64jK`h)5oCWk zSAg?(M2SoRS;4U3C~1>ckrdVsn;a}txr6NZ^j|v+7ApXZkCW5V(bQTm!@ZmeHfEm6 z6^`Cx!VyEB>Re!aMVCD?EOX)@g+Fen&1>39f^Yx606Cha;roRE=;{}6K3}1B+Opy%SxE)%SxEy%UT##Urxd>xExl(aFlMe!$p`J zFjgIAVN$?AMTbQgi>~TWg~{s26iZ`881;j>K9>r^>PMS~2y^ZSk5~8O2eKl*tam zAP_@y2$3U=@c;j94WtW!nMl1v;q%dPK4GPVH(5!qRSm!NEua-JvTn`s8l zyO5Tx8O%0xku5#HmKrDDnqG;)Pp8DWK^;B?fm$G!h_m1-A8CbOqI6)wxZW|d4#(1- zhV2d?^@ia2?OZZ{wo=DSP*ZH$1LoZ|v8S?Va1>M*&=0iC)gO23Z^SEj;1V9~<@*8F zHUVC^6#fK%wnh9o03sP?i4TBGr|1E~u|y9L4sV=2K!(Fm(;grL!rGGy0fIL`<~LRu xlj?1_9J2}#c+XpWC;$-wF8C1sGrwTN17*Y%Njv8>bpQYg002ovPDHLkV1hm~fT#cf delta 277 zcmV+w0qXws0^b6V7zqRe0001qplF?uEg=(8Z8m!$nEE%p&w#wT+XybR%Y!|H+?8CNIl=eqr2bHi<**oY97NB2FEl zS^&mdhkh1QJ4P+tv(9P+5qa#_2sN|O>6X1TsZoe+ME5+%b+3)N=qYcN0aV9a-J5@y zab=zG=5~R88I9p=D`=-ItR!tPagcOAARYPhMO$3_2QKglE@U$DV`A*wkjy>wVh63I zL#W@GCornW0u05>0t`g}@B$_>M`i&gGRGglmKl);X} zFbG5=MT?M)nE(IV9qcBJ3F)z?(kh3}cuY z$>D$^>C#(h9wq?|dhM77m7U8)!qFO_qHZ|#Fi7j7X4B!?Xs}lb4H#RfsYWxyL4(*U zguXa~Zu+2nv=@pyQ(I7fbC z*tNdR!F+sqfAx*}EfHg z@FBz{$dbH;$gZrnWpNh0iAZQ)!DC=clVjK|9kXqdrXD@%+-CUyB=hHE><<;tw5KCZ zCiH;#ViUdZ5#JaKv%?-SN3H|az88P$ zq&Yn2tL=xt%~FeZmBi`0$nANtiVU>1auysb2 z;kAug5b#8yRHa%$K>$Tj38f4~hpP)gg=yl-;16Zax-kQ%HPuEYnF!5mo`l3mIzA1S zeg^$t>({`93cxTJ1OXT}WE_F9PIhTWkHEOA>ZD14d8|rGfvI_Q-F;>RMyRKr!vPr0 zn=-7@0Rs{y!1(`c0%ScfE-C^rU(qrE6B+A)AqgWO;DKpPLJ(^W7djz`fg>(cg8WJ} b>Bss8cu^mXAKp_O00000NkvXXu0mjfjn%C@ diff --git a/graphics/pokemon/mismagius/icon.png b/graphics/pokemon/mismagius/icon.png index ad707f8cdd931b158300811a4d57ed8f62f00d94..07e075c1e88c9669bf184b7fcaa763b49d068453 100644 GIT binary patch delta 325 zcmV-L0lNPC0*?cb7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S4M{{nR7i>KRNHFB zKnRTFrB!kM|8MIh$thjkz8+{@0s&{ejP4xA`xy>k>sLQ}fU0c};ioZ#r&n>r=vP2Q zR2PFOQgO1=6`$p7mzLO>>gc*rh5Cm?E+`apv~#7dPUK1>4f+`_!LuV8z?H--2D XoX8tnV~ldZ00000NkvXXu0mjfMEsB~ delta 305 zcmV-10nYx91N#Dy7zqRe0001qplF?uEs7!!Zlz?v8N>BR4pC|em^RxhnHAtxiPKAyVZraH+QI=52h|q50I!O!H}G>9)&xAhpqDQeVC{^w0<)mCByCI61#e@N5|DrU zbEWJZ=a1?wJYVY9f}Mv7Tr$07b07#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SJV``BR7i>Kl+lib zAPhv!B~nJKyE`A2`+x9(6Rh_i&4ru&Z@<(#_x~GUW*C{` SfqQuX0000Qi-C#hXQ+==`Ta|nPbm0d&bVQ1Wd`;B>DR^lNM2d0Job9AcEQlK-`Pn{S?jFG3 z2aZ9df=x37s1y5{`@5R#X5~O_h)e)bY9dl7M4tl-yQaiUr=0YYR!{V{i6TCcJ*IzI zEQ|e&b7aqH`jUG9A1OUpfRW3wOwQw6fo6a=#YI~P12j@fa|M|2Pg1=u&unEqKoU)P za=Dnf8?Oe1Jl)beziI$?cegQdijFmOKLCJv@l_1^X;i&|VW5J46XR0-^nU`aFd^uK zsg8tU9eQCq2 zFs(2P@mIe&@%If{s}~=6W5r(E5S-pr=NGf#1b9uZ_s8gH}f400000NkvXX Hu0mjfDNCWs diff --git a/graphics/pokemon/mothim/icon.png b/graphics/pokemon/mothim/icon.png index ce6f8f0f6f33146f85ab39cf5aab3e706b528154..33124586818efa1636ed2f262a6c27ef6b4f39ba 100644 GIT binary patch delta 361 zcmV-v0ha!$1G58=7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SF-b&0R7i>Kl(`ZE zAq+#84D7qEe|^0Gw8dV|8D$Z64)~%o1|hr~aCZa=!9Edp=oFF#6Cs+X6 zJBO~vI2bGdYM{=4K~x6D4#EI4=$u8Lr*!VN4yo$vSup|-u_2c9=D>v{w@1=L*xn`$ z6eXk-g6tf)C8eYX5hQI5{JUN#G-=y{9znVCgKj%LivRk-I=!bR@x$1C+}8sTeNlVB z_^Kb?>;#alVFbv*FazY>&;io)F=+u~Uf* z-I^t0Buh`-=zA!T|^MURLrgHC_0 zwr%e69e2Qm+*C<{t~`)3tCD`N5Q%>Z=c~F(lzPHLct>}p^v|=cyoBP}2v~czCX!6$xP}9Ot#w(j94LSyN8vk1XeM`nf^EzQn9sw&16claH z3ljk^ObmiB3t(Z~wPCYCn4qVah0#ky{hkf-!sO(HQSOWvhBH1hU}4Y-5;|Cz(HVq0 xKcN#Qb9q+E3e&7KR7sKp zAqvU-;QJ;1?eoOxn#zN6luw_F`(P+J0tT0teR_?Mb5RDut<(?hA2WqXpstz z$ZTOFilA*qW+3=iNf3~SEFf03%eHVaw2(&G>^ z*belqah&GcxfIS{bl)0glwxit0YZcmuz`~Y&O&GqB=?{K8KWr==vVwT19wmwCh|rBg!iu_ zKRlj45&s7A3kI^L^U6S$f4nr1!#}1!>;`h;l%YTD2J+w^(;qeid3gSIF_7o}Fb%}6 hk7xNqT7I8D`~akQCj*!l<7$|>z zz3f{;;}7i;8Gx)VM_UZNSoz+-Rlw~iaOjAA73j*!gOWkTih}04U3w@(fsePM$(639 z!?VG1d{M7VUsF!>qDqFwns(&8^&&mhdF^kU;Mhp004LwBH4>6Sap0=%8$Sr9bXpLV z6bqPime<6W4o>$JEn7-#f&K;>W9(P&S57XRxCvzFkEcKe{%`^r z_`?ar`vb`d#QVdR`za7VDoTwikjSG|Ap9S}_R>4#OY}M!5kOt#XMj9#FYJr5+|r zB3a}bsT4Jg3`nkt%wN>4TU9omK8(Rnso!5j{a%l*M|#5z$=7{!I|ZZAF+M zMKp*oWq4$hFzqafg`wCQ5{K0!F>9+x@$APJI=lhBH=$sq;!zF&0000KluM4o zFbqS36tHE$An$+M(I?G}Eqhi4x{0=AMO9YbaXgiaQF|Sw)>^Q2utx0+1YF0a1uF`y z3f4U|0L2QM5W>2{a@H9v_Y7rWAi;9Yu+)2puE=LFZ~D3Fq8U6XCm=F9D9sw^8j06S zWx=>_Ggt#NK)ULG<{ur=K*v|j4Sfm$YZycg=?y`c7_8eQaS7 zHI~plqfd9E)5n%PqP6@O>VTgcnpNJlW+2MKSC2`Li8c%Q`me`77yZ;n>j4NyfaI%p zKHLDA@No0PKYu@bNq89fFcIXJA8$U)1aW@+;X@|K&5!skcoziWzz4|$$$XdylK8M9 g$iRoR%Wv}G2QY;nEBHV3B>(^b07*qoM6N<$f`nI;kpKVy delta 325 zcmV-L0lNN}1CIlc7zqRe0001qplF?uEnFpL;>4_L1l717-H4v$MW1I)y5}2lA^xD;i(Q0-P4%$;-q(i z5TZ;4GYEl+hZQ+uUZ#$o^C1<60#PJYS^it&xW#6+HTYI^RWx%>(LylJ`sEF!Pho#& z&{_HQDk}>6{P;m8qm=>HL zp_#hS28mls`w>SqNMvre&uu*h5oNu-g)uaGzhq*&@L!#$0EQee6z^et08@u}ec*sH z0JFS%KBT^TVRU>{;QFwOMI@klR00000NkvXXu0mjfWAT*r diff --git a/graphics/pokemon/rotom/icon.png b/graphics/pokemon/rotom/icon.png index 354b6fd3dc9280ca29a0d15a14eb1cacd8c6ab45..e2ecc8b804e0284cbfb797d6c81613a316ae8b47 100644 GIT binary patch delta 321 zcmV-H0lxl&1B(NY7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S2}wjjR7i={mCFvq zAP7ZGNwfzf z98b|A>hUCmQ6B`biXa^)M*)l!Tmcw3PKX+S2&IRd;XD+8!yM-#6rm<~WVk*NCy6;z zNv9O3eabc5h_VNN5Fkne?ZngoUMZ+FfY=_$`LU_Ha4+%bwpKKWUUdg-i%f6s5#E6K zBlOqnrv{?3!$5RN4S$$E=PF78RzWPXPM4}zIf%@=fheLBF?R!b=tImeP-kfado zZM@yOSg@`qQ2SwSl5}=saO9C(AdoeP83)q4=*49vY~v!(^3k-MB8K(*5g~jv>vJNlt3!zUxxGlOP}~I zFxA}!7*Vk%nE4>-Kji|5K&5>|8w42GQaHuG0+Ys31VRR83oK1WfFV3##isy+xLqRy zQ)Qfisir^zOr5y^)AX8vY1&-7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SE=fc|R7i>Kl)-WY zAqYf8tMmr{|F@yRWMl^2J#1ADiMzLM5Eyx-{JkUcLS{ZWR6ZJ{_kMCrT@9N;U=XcB zge0q2Ah$-U+b!me29;YSG99YkwmLMDpfgvkg6A(5p|WtTYz9wpt8%p7DjGqdbWb5X z#;CRN;#dtBWADv>b=>usyGU*5!wqC9Zj)k-*FW-`;W1D_c(Zt%r>>&)w$ZIjB%Y4s zi%m%_xn5jxPpXfO-ic}VXb`6#_0fOKf_Jgkkz|}-{;SRSKgGs)p7I$FSnfCRaMri{ zz(bM9j}mGYU#uT~B*07zqRe0001qplF?uESHT6KMGAWV2+teR}hDg%1u^-K#khvE^cR+5MwUUz@Y z@IDPp{JHN~jAEu>=K{r8Yv<9=of8CLng80H#TYXegbLOOECs}3)n`BzGOIU6Xmbh# z+zRL&T-W)EFpS6uvF6y9dnX*LGS-LrCjqQ-F5N(VUm7O*r2wK|B>&wAKzsz!7IAS8 zh#Oo^d375TM1mbsd*2$quPEe6`(j{pD})m`d1`#yH>~iG$y4-o*hYWA>ZGdNJLYgr zTTh~Najpq~vGX6*ojc^$rwlxBql|S&i{`dyzT;k#@ S123Zh0000;xA2Gh3&t5G*)!sBtj z_Il2G?*Iq}{dNGC3i#iW39z?I;8K1HJ}vR zqd7302`FD4s?&CV@!(C(nrHp?xMs*xLt<&n&4x|q!6Gs;9gBIfmma>HCr?)nKTNe} zXGk`Pt^Taf)<59k$NU%w68XVw5fFhN%+?bm@WbU!5ByLW01^4&^#()a2L=EHezfbq z<_C{E=fj&Hi|dcZj~yRW7{BHNtH72I*31JRtblLu;RQt#+!ehdg5F{P0000zl08lXF%X6K22Z|#DORFH z3hup!i4+ciM9SPXD?#^WHU>$k#&^?|z@1no1}_>t3c&jy{g!!suxLoRjR50OIS3c&rA zq}_b5^DZneyuW=WLhL!0ek7$p|$2kbX~d;$n$x6h8Nms0=$ N002ovPDHLkV1kzhi~axr diff --git a/graphics/pokemon/wormadam/icon.png b/graphics/pokemon/wormadam/icon.png index eb622fca237ba80cb52986b29f1014a02c3397a2..866acd17ba6425807c2609c6e7bead681929f53b 100644 GIT binary patch delta 35 qcmeyy^o?o4G{%b)r=JkFw0}1-KHx-U$2B}}F&Z$8F zSSk)vbxdBC0Z*tSta!4z+;E=3q{eXkxkE4FE|JZ_jnMdg3wYB&TQ4hxkl( z4+g3Uj)r!O3P4+ghuoQ+JF|N6p%2jzR^pyLR8SL$)s2fXp0gT%gO)}B4_JR z9YjEortb!mbF~%O?b*$a`^W3CKfNFE;RAlO-@MAuHp+@0cFa0IvZJkf=f?^UogZ11 zfgcORJn+N&8Cx0oVKW6hO#GNm{~P?6@eueCmMich9rSw_`Edh;*%#?^PXgos0000< KMNUMnLSTZB(1}U_ delta 350 zcmV-k0iphZ1E&L!7zqRe0001qplF?uE1R5*>zQ@d`%Fbwn`5JdI}{RDq5 z0Z00dLJ2wtO`ADrjLcpvtDOk9WtBG8Yw6f>gv)Kp0dhD;5h z%jo1L_L+pWcE(FWcpQyKHc7&RM^s~4O{5I~Q53Nc45yvk=D^0cxI!UE?gm_f;!c0@ zK)1ns@PRQua0EIwBKBUEvA{gr-OJv@he00g?yS>l4b#(MpzIvzH)L`Xp(j&1#8f#3 zwdw!3>Q&*ld7kh=3kO7R8AodXSKY6f)2T5kE7VK+OWrf%()=Q|k4~a^8MTr1($1B6il1!i@iOkl--NYDc`)&U2djR%B weol9OrYu0s$LT~e6#$hcL&5(ZTYtG!U-$6I+_o@yFaQ7m07*qoM6N<$f+Aa?8~^|S diff --git a/graphics/pokemon/wormadam/trash_cloak/icon.png b/graphics/pokemon/wormadam/trash_cloak/icon.png index f971e3fb59a5b9e2fc726d298ad46fac50e30af5..6834629e9ab3f4cfe1e0bb744ab5201f6b8e0a06 100644 GIT binary patch delta 297 zcmV+^0oMMO1M&ip7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&^R0PsmfK~zYI?Uca| z!Y~X&S9Z&!N#j0U|EQo|9J1+qNGqvxVHA8eCr(+M>g@PH4&vW|@r{ zZR}&>6{axwpE1Q0j^-n99SIFZ8ej&oJspuiA`b7KdN`!U*x`mf^gT1A#F&Hw0k@n} zM1?v$A>u;U-r$*kaS(5QczH;<(l~~=rudCh!h&xhE4eGQNmId1ll(Y8obtmG4s(7a9t8ZLe7IgK7T2bHIr%|fea{cF8I>Q^!}!sy vC*em~-^z~wNHO&MAX8R;3zlTB`fFbsv~29`DZMm+*2 z=zZTvcu%C^J|MM8yE9T<&kTf+S#;TEg&)s9I3K6e-yUn@aEvLpLP$-@lY>9%g5Dt~ zDt!nr%Soj;z9E?nsd8lIP)%m?<^pzQ$?nJsTazf}j?Zp^JQTW&p79zK{n|)lcE^7* zVp^wDs054A`mKoSa*gvK`>g(Y9{PRMlV0Wls5U_8C#jc6WrmW2W@FSY{U4upRQin% z Date: Sat, 1 Apr 2023 08:18:13 +0200 Subject: [PATCH 057/131] Fix gen v icons --- graphics/pokemon/accelgor/icon.png | Bin 387 -> 400 bytes graphics/pokemon/amoonguss/icon.png | Bin 352 -> 349 bytes graphics/pokemon/beartic/icon.png | Bin 370 -> 386 bytes graphics/pokemon/cobalion/icon.png | Bin 367 -> 366 bytes graphics/pokemon/cofagrigus/icon.png | Bin 535 -> 553 bytes graphics/pokemon/crustle/icon.png | Bin 505 -> 447 bytes graphics/pokemon/deino/icon.png | Bin 261 -> 291 bytes graphics/pokemon/duosion/icon.png | Bin 310 -> 324 bytes graphics/pokemon/dwebble/icon.png | Bin 344 -> 333 bytes graphics/pokemon/emboar/icon.png | Bin 514 -> 516 bytes graphics/pokemon/escavalier/icon.png | Bin 401 -> 416 bytes graphics/pokemon/foongus/icon.png | Bin 266 -> 280 bytes graphics/pokemon/genesect/icon.png | Bin 421 -> 395 bytes graphics/pokemon/golett/icon.png | Bin 332 -> 348 bytes graphics/pokemon/gothita/icon.png | Bin 333 -> 277 bytes graphics/pokemon/gothorita/icon.png | Bin 388 -> 318 bytes graphics/pokemon/gurdurr/icon.png | Bin 378 -> 388 bytes graphics/pokemon/hydreigon/icon.png | Bin 506 -> 532 bytes graphics/pokemon/karrablast/icon.png | Bin 253 -> 273 bytes graphics/pokemon/keldeo/icon.png | Bin 399 -> 407 bytes graphics/pokemon/kyurem/icon.png | Bin 595 -> 573 bytes graphics/pokemon/landorus/icon.png | Bin 554 -> 533 bytes graphics/pokemon/larvesta/icon.png | Bin 408 -> 367 bytes graphics/pokemon/meloetta/icon.png | Bin 312 -> 325 bytes graphics/pokemon/mienfoo/icon.png | Bin 372 -> 362 bytes graphics/pokemon/mienshao/icon.png | Bin 386 -> 395 bytes graphics/pokemon/minccino/icon.png | Bin 329 -> 352 bytes graphics/pokemon/munna/icon.png | Bin 247 -> 255 bytes graphics/pokemon/musharna/icon.png | Bin 355 -> 377 bytes graphics/pokemon/pignite/icon.png | Bin 379 -> 396 bytes graphics/pokemon/reshiram/icon.png | Bin 529 -> 551 bytes graphics/pokemon/rufflet/icon.png | Bin 325 -> 336 bytes graphics/pokemon/scraggy/icon.png | Bin 304 -> 282 bytes graphics/pokemon/sewaddle/icon.png | Bin 250 -> 272 bytes graphics/pokemon/sigilyph/icon.png | Bin 432 -> 423 bytes graphics/pokemon/thundurus/icon.png | Bin 6946 -> 526 bytes graphics/pokemon/tirtouga/icon.png | Bin 330 -> 344 bytes graphics/pokemon/tornadus/icon.png | Bin 525 -> 530 bytes graphics/pokemon/trubbish/icon.png | Bin 316 -> 332 bytes graphics/pokemon/vanilluxe/icon.png | Bin 372 -> 379 bytes graphics/pokemon/virizion/icon.png | Bin 417 -> 359 bytes graphics/pokemon/volcarona/icon.png | Bin 463 -> 471 bytes graphics/pokemon/watchog/icon.png | Bin 435 -> 414 bytes graphics/pokemon/woobat/icon.png | Bin 321 -> 333 bytes graphics/pokemon/zekrom/icon.png | Bin 473 -> 506 bytes graphics/pokemon/zoroark/icon.png | Bin 460 -> 433 bytes graphics/pokemon/zweilous/icon.png | Bin 416 -> 423 bytes 47 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/accelgor/icon.png b/graphics/pokemon/accelgor/icon.png index d8538bec1d870cbfcafbaec753b868eec69eed5e..5d971a97b24cb4a2b9798f8fecaf822d847a5928 100644 GIT binary patch delta 321 zcmV-H0lxl&1CRrd7#0Wv0000?P=%ZT0004VQb$4nuFf3kks(BXNQv!}L6*ZH3`2uc z9;~GM-?p}gv_LSs&dj2I-852!2>j#t&L@WCUaqxnEGE~QbL43HqeKqEb)c*btZI1V zf?@`3GM6C$TcE&n5z1_^gj|XRFp16RV6h6iLQ;d!GHwyIWSmUY-*KzpI>3`iSN7;( zvJIYq#rr28Yf^N7f4UKWN^8imrvBBJwY{zH4w3QbbO|wofLF%c(gL(0Tv;5vwt$Bq zJWh>G*5Vfaa?nfeuGLoj&ackD!hdxod;B@y`D4WYhwdHz!UYy@{EhC#Zr}K~m!}pT z{*Xprh(8pf586}Ezc8C Tr8T_#00000NkvXXu0mjf0Q8>X delta 308 zcmV-40n7f71A_yQ7zqRe0001qplF?uE<}Ggjn$GdZo@DPMRfzBIzSBZ0Ok#{<^nA` z<_sMIZ}Czix@O&>nG{JK;>oNMS+?XYK$mba^dWwW{7;DID&W<5(4{hH{butET6epB zE}ZqNY4eWr=lf497*gA4y4}$NdOP3fn#MXrnuM$Fjvv-DrhkJzd^@hh{FdQlen)>9 z43eue?Y3uPF}XtBm8UkMHpXWih|Q zigO{f7sscrf5TzfNyGt=OB_P_B@W&v8X^u{%>YFlZb2uLI}RHPP!%|M@+tj@!;*f) z0qm0g9S3i-^lvzf`E;W}r6>~sm82kIBP`V_eqQbHq51>Q+ozuPuE!_<0000Kl(7=S zFbG2^l!s zEK==NY}a(mgLyl%kA6xIVg83O1(1Osgf~D2evlSGMt-~jGV$XC$jFbv!wo;qk^3$r YUjJVa0^T;WvH$=807*qoM6N<$f;}C4AOHXW delta 278 zcmV+x0qOqT0^kCW7zqRe0001qplF?uEM z!y`C=&tx~IrDCi2jP9r$-~dq;&*(vsKEvPbr^l`|Us3$4c<=XhOExFI22duVv^%xn zVGdxao$kPF0$95isCayY6Ln`x-ZCdpjeVa0$&Fh*2A~OimlM~}<_D1VE8-yP^^||X zOd4##OA^PDIrO&!a$u+7;*5_-HD6rY4}Qcgz8{IEp-NjmZ$wYH1T+z?R;POxB5UZJ z`ltnF_F3aX?W%+2$Odh~WY1geCd|Z{K_X1U$P5x;8l2)=-ol&-nIB%-u9O=gU#Rw< c_;-E*@@A0Sgzy>t00000NkvXXu0jG}g30ZI?f?J) diff --git a/graphics/pokemon/beartic/icon.png b/graphics/pokemon/beartic/icon.png index c4ed605a0ef34e9e866e125ba5a1f8cb2e5f9d52..991f9f265d21e4a6fc28676badba498a99034eb1 100644 GIT binary patch delta 313 zcmV-90mlCF0)hjO7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&^R0RTxvK~zYI?Uca| z!ypKTD_k@&@cwT*er&c@(8DgxlG)q%1_E>n1K> ztb*oE;Af>Of+iBeYZt1$_d0;-wg5zGUlJ&e1pastoqAOw)!sUCI3aT@mQh<{u8kWP z&PS?*s9{owl8M@XpsD#aNfb5XRXxgM9bv2I8qSjp6F_-G*+$Vqv9K%v>k6|V#X4e# zJ_)>T_LM>?aLHwbwy)L5^*>LaCj~M}uLS~s>;&TekhMTge_RC;0sHe>Aj2OwfyhkQ zH**untQg=|fe;17_#8h1NrvuzXyfY_jf$E45ET>rkSOLDcm41JVPX+Evy2WW00000 LNkvXXu0mjfoJWPi delta 297 zcmV+^0oMM41M&ip7zqRe0001qplF?uE*l09z2Fbsu#0|M?1#3fxS zSZ~S_9WGM=ZJBbT6!0N}WKUFU539zqe!Lb1T5f!JA}R9gx<4M`S2=8xlYwb10j9E$ zj{;YYM<;Ai1cGdCTvZJiHsdJ@l7*Xd;~t*Us|mexZVx-9SES@)bSL1t6c#$-eLH{H zP&!SA!*SPho|eoj!`vsG8ym#Xlnnq!p-e^?zNPBFLA~&`5=bf07pUS8@&2<{?TUz5 zw}Pzq{BPr@z)05uL+2GR!9E&b;+gsxm@Mor4KT!mnt?edrY4<$k<^L&42*fpb;vw{ vDf0)jjX2yDbZ-3QLze4iJ{EF+pN|zU)bo=sC>|6{00000NkvXXu0mjf1;T-E diff --git a/graphics/pokemon/cobalion/icon.png b/graphics/pokemon/cobalion/icon.png index 376226b242ff93026a7935c3e6575d4f4ccae4e3..5dcdd6cb0e912e463f735dfa70f59fd09b8786d5 100644 GIT binary patch delta 292 zcmV+<0o(rX0`3Bk7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S>`6pHR7i>Klu-}E zAP9tq)(sL1|Nr0au=b_UE_++D`qIYlJP?z6JpOW-eZb8wRKU)sD&dQB!{>yz1=cV* z;Xq2{$4@yCDO~n`Ea7cw#M?D`KMKH~RfNUw(If9`w^tSB$@NeId+XY}46gW#7T6>= zFk@y3+|MbvXj5i?N)$%bJJ8ltA)vr(sZa=}-Q0u2xD32N0f}>tEx@6O_lIGlRMKQA zrQ)#oi)kiM9fEDt7)xlPYc-Q8SkpoI6j^ON%(2G4HLF{A?R_ipPK_=U(feNMx&!16 qkRkXwKw>_O0J+Qu50Kx?hc~eF8O{;ChKK+F002ovPDHK)LSTa61c@8~ delta 293 zcmV+=0owlV0`CHl7zqRe0001qplF?uE-hRm-WAzY{y@Q}{veZJioObpx=MUt_%X6Fa~ zGv{GC&Ymxx(a-Sb%zLN`{xf&a%=p0n_6%Ih-!qaO|9^DMIS;qx-HgtsFB&@$h8lm* z=nH+<*a$b&$k=j9Xy}U$xZ6G(E62eLp0{D)f$WbxmDn+SER9GU?C{|^j<6O1Mp rA`%QDeY{hCiJCsn+5e|)`TzjU#NZK~E}pgm00000NkvXXu0mjfJ;soN diff --git a/graphics/pokemon/cofagrigus/icon.png b/graphics/pokemon/cofagrigus/icon.png index 19476138c140f9d720f9c5b967c7ea16be54d526..1ae2b6609952723b628b01d46ddd28c29342fff6 100644 GIT binary patch delta 480 zcmV<60U!RC1gQj&7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sr%6OXR7i>KRLhdX zAPi#)PGKgt|Nn1SHYDNI&fa(Fp_524!dMF7PcBvcjxy&BMT0t=(s?qMqAQG7nkg~! zS#q8U>KiLX0s(kR`qX{!d=iOpCQ6l|7o`e^JdsF}P$*@6zN{1@$Z=3I0%wz<;UTz2 zl0!kjE;wqg@K6DN0^Wd+Lr%^nqU%}J00wYO^-?)B%eow2QN&d) z1TcsSIMz%fXjtw<@o@sjPEj^E7`O{7A~J*R8Mm2)teMNl+Ef^0#kDOX;77Xx4r@oK z7pz?c`;U%dpUMwUp*C`qV#T|S$39?(7#ktXu)mV0!Z0v@(}9MK|JQzf4-mi@+RqfV zp=4h2;l|2XksY?$f9Zo6+v9=rlt5RbsHn$7`EVUt z(;o4#1HHsQr+Bz}3F}%6Z3xX$AM>FF#9;sFlzuUt{a5dY+5WrX9PGcT5QfUXHvbR( Wp&-UXpdU5>0000HD4O^oGpb$W1)2y4KO`y)m(t~vW)kdm_mGp?y>F4W>2&HQRT%R61>qNGt zHO9lWv}YTE!JJ#Xw+S`(SxmMO?FH2C6?E?K(QchdL^%tGa(h*xrcTuP8Uuue}hyyTL)E^5D6+z?# z9BW5V(S`W-F*BPxNkx#O?qOzHfIpW2VRgk|S^|4shlh``HzO$<1 zi5J`(uka!EDjc9vh)NuoJ(eX7?5h?PFiS?<>F;Rx2FCv%s3JVwGynhq07*qoM6N<$ Eg3Qa>g8%>k diff --git a/graphics/pokemon/crustle/icon.png b/graphics/pokemon/crustle/icon.png index e6a99fe634cf1d556cb5851b49a47d807c0b25bf..5b70147792e6acc74b2c181879d9d000f77077d6 100644 GIT binary patch delta 373 zcmV-*0gC?l1HS{17#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SJxN4CR7i>Kl-rKO zFbG6zRl>0!;Q#-2889~SCS7U!8l*O@Ipxx1=Jk5wA0Zz1$!bAYj0hox7vAd5AWfdC z0cAw$%vCR>2vs>1I1&Cm0n8iX!)AbKM<@ei1o;-^6I0$pa9{}40TG{oW=CEoKBf*L zEeMYH)IxgKlZ9A+zO|f}_krKEQ61^FM$jF#1&;*o6fWEYkWz}YL->8@E{(euM44VB z0FlDz(=?%1Be-*!CBW!uJ6H(+sRDum`EKf_x{9`EZK&;at+GEf_K0909Z9-2y?pY< zK)7C|V<4+{0~qtf_wg9Smj(g-e=-Qu-EV`)`9BOo^`8t>0{VwRth|YB8ieT|29W^O z>@}4!VT%pA4324{@~1Ke>levLTVvc TK4Y9M00000NkvXXu0mjfFtMp| delta 432 zcmV;h0Z;zF1Nj4x7zqRe0001qplF?uEJ0IhT=1F+OmUoL;( z1f>HiXCq)(({~qE+A`g2B+eGsIAA^xP|$u`)LjG)FVvjS*JTsHz{lgq5iX_y_ZH3= zFrS($Ovd>39spy)ydV7R47MWuj~-2jciv7;e7{i7I2TjCy;;V@&@qucRX_9@K7)+? zGM~RLMuNPw4~lJ5hIxu!Nxff(yoP^Z1ffKjN>NKCWr|KN+0$nNPOg5a1=y9Oa9PM+ zDG^mZ+fs0000KR51?3 zFbE40OjYpze_Io&RR^HD;g-92$PgQFP~V7cNrOt~tDsikA0mKG)zm5u2#g%j8*7l5yT zD!t?*cux}=EvgPT1Iu6YY0BbfmyO@S4v;?y5EiZg>GC1imwYJvJ-hV$=QsgNPYlwI SiBpLH00003|L73 delta 186 zcmV;r07d_!0)+yQ7zqRe0001qplF?uElE47#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S!bwCyR7i>Kl)(za zKnO(RM$OIr|G(`h?9EvyEiEk(a+;@W6z4eZ_)bj3R#pT@QjQ29Og9U2V+8c`40jLh zi2^*I=u4o1Ot<`6VnUD7-BF_lrjG)g07xIhg90e*m!nKJ(RLYzNo13(2MsY(HDQ0D znt+MWITRtek#>?;wM(SuFxk3lpGtPI%FLaqyn#Fbv#$>&+0TES00000NkvXXu0mjfyoYO& delta 235 zcmV7zqRe0001qplF?uEsE`SH?Q0Mz zyx-ygg#?>GqQ=6A9z~6HLx!-UEp>z*5= lgqaOe!emwYAWZauFgJqqeuzp^a9RKW002ovPDHLkV1lkoX_x>2 diff --git a/graphics/pokemon/dwebble/icon.png b/graphics/pokemon/dwebble/icon.png index 32a23fd05a22cf0b8ca3c386287373e11a398e01..4b356d5aaa9f0daaf7f32ac30087eca1b5593275 100644 GIT binary patch delta 258 zcmV+d0sa2i0?h)D7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S%Sl8*R7i>Kl)(za zFbqQz5A2)t|9?9g~QlXtMBn z-xdTugtsg)3W0Wqk)w|S!C(NQ2%`Q)z=%LZVvsvr1)lvuf$0G+0Ehdapq}8OyC)?T z)r#YgN%88)b5yWl61t<807*qo IM6N<$f{&ea3;+NC delta 269 zcmV+o0rLLM0@wnO7zqRe0001qplF?uEj429W1XDz^41CSB2 zP0~@K&dh2G=o|uf&{;7B{-H~aE9*PSlKfs(-SU9UC0OuL#9~q9DS%p20x&NMDa(MT zCDJ+p@sEYj)-jjdf}N*c93`+B?u~2Q=d9rN#gnnI3v{xz%r1Mg0{`MMb)9*S zviDXj7s{YqzQ6oNHDAH)k4PCquKp2wrRyAg33CexXhm6utR9IlNyjn>=_ZQ1^X}F! zCABv;EN;*z2)a%@@!;GEIvEc;LDzeit89$Zwe5?oX+`-dHV$98QH TWRMAN00000NkvXXu0mjfK?rqb diff --git a/graphics/pokemon/emboar/icon.png b/graphics/pokemon/emboar/icon.png index 8d6f99628e9988db0e6275eac3211f8d6bb16954..d79f6f004ba6bc4ec99b93c6b8a02c3b125a5fb6 100644 GIT binary patch delta 443 zcmV;s0Yv_S1cU^T7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sf=NU{R7i>Cl)-v~ zKnR432;7+Wf7=3T+-38{9(ro`5R=U8fUf*sU;k|3NmqRKKox``3X7fwM9gVZtU9?F zJPpXeZg3*A_y|M(Tn*tU-3{n^Ih-lwD5I{@9S~(xC9p;vm1Y1;j3XpeHWCq=b=ocd zi|~k#LL%g&AzPwR;jd^4E?h}1pmN-Yf+5e9vWSl_SxafwWF+y-V&UCQIWS0rJq zkO8ub=l;^ekq2`+nBf_aOVYqxUELY=^kX|^ipPen3_ji}s{ZW7YF!Y>fz8EI+gI@JM4*~ErB!72*{R9sWh6Nz&@HT+-(U}3# z0C5Hk0O^2u2arY(8vzn8uB?2x0g`-J4R!-WS3oQPnF6o^#D?KMTJ8WD2~xv80c0k~ z!4FITnFvz+zyy$)AT_rb0n!PQ{D^_P0df%puOi3kya4i!Ajh3t0C_`@gAW%#k|5p* la&&Y8L_dxiFZ_4;@C~c!94j)swWI(5002ovPDHLkV1kMBz1;u+ delta 441 zcmV;q0Y?6W1cC&R7zqRe0001qplF?uE`;vzqVe$EE1~ZM!Nm^v;8YYI z5G)9aa}r1}4XjSO0I6P9vOrS{Hr+KcpfgCj8$4(d?T#-*nWc*+0keBz!)(tTfS-SO zn7)60@Ys#0XTHv|H{?CxHYCef$|aANZURHe7o5)yFU(Hd;a$D#8B4+qEb#rqxq!M52cA{pxw)Ko=4ZA%~{HS|>s^9|>l8iTL+t0h!mu;L(38Lwj9Z{`e07;R9-fY0GYeX_|7vz^MgRm{a4! zSr`XkWrQhd*7{+D+4B~}MwkU(dBSjaNh{1p?(S%W$zBamNLHA1X^MfXKC{BeQ&P`B zCn~Kl6AbIB0I@W}j1;1%+de*m5oV;K%7;2qSYhOGfT?tr8DWG9ODjm_M=d3cxXHo2 jy{fqqhP<}RfBW$Z0uAR-WPr3800000NkvXXu0mjfna;~Z diff --git a/graphics/pokemon/escavalier/icon.png b/graphics/pokemon/escavalier/icon.png index 32c3988341d4d8ec9a552c1833fb5b68e9be20b3..94f646ecf70a69b2d5aabffc4e5afa8b0049c28c 100644 GIT binary patch delta 342 zcmV-c0jd6x1E2$t7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S9!W$&R7i>Kl)-ky zAP7YTY);|={{L_L(3vKKm@ay{n!!zy_cVZdOL@nz9yfApZQHh$#k$%fb=Z%bJBF@G zsy7BD#z-Bmn+asMH-H}v^PbMC&lSo#nkzgPPcV%^S{R=uWwZ3LB zu!wFI^T`*m=`SXKtg7M*c$Tw{HfpV~AWQe!q@x6?^-%N@j;M?F66x4?@1zF9nBP0S zA9##s!h9dPj{HsA)P>PTrcqy89GI~QUhV40Au!kS`RA|h^oQpYe~%A9{s|!QdIf+) zLf9)nCPLu#0uY)AVW{i`2oMtpVYu)w011S!jqM7MNC?L@!v!G42@#uAPJoo05GO!Z ogm?m^ED7)c$Sol(*@0i;8{_pAI;n^8t^fc407*qoM6N<$f;5eoQvd(} delta 327 zcmV-N0l5C41Caxe7zqRe0001qplF?uEl#A_w8P%JA{byOHkFoze5Q59@ z+KN64TFynBfur%f5PcFjXt+#*H|DvLRaoB$fT-j<##et~ zvnd417<@L(eOKPFb?6KGJLEO&DDaitDt_`b1FhX#RVhos(BakXhv;f5Y*CfZk9}Lm zLQ`J9AZ-MUN6zc%us-R$Dx@3J1xa}Vm98)Z14&^S8?vp>C3YF-^1x7uzz`7l1+xP2 zXE1_*fSzVBWko=|IfEe}@Gvc4ECDka!UE=LI?%V+0){0(7BDH084SyS{D5IO5O9A2 Z`39lhuSKpdl!E{O002ovPDHLkV1ni;k^=w$ diff --git a/graphics/pokemon/foongus/icon.png b/graphics/pokemon/foongus/icon.png index f6e6171a4618a436bbf3097eaf40dde62d6701cb..c6e4ab426bdb76528e9d941daad9a86480b43276 100644 GIT binary patch delta 205 zcmV;;05boI0+<4j7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SmPtfGR7i>KlsgVX zF$e^`AUz}(=Ki-0pC$#6E=l2O85xZ1UF-6nXfTu+hIER8LCgn&+E8X3W`am5Se>(l z)J6!=p%W+s!XxsO0@Cmv^^^)%$j9jJsR;U2sUBn4BqX>LzeuyD*%Qs~AoQ zW11l!#8kgr-njuRvc44{kq^`7-k$;_?lFZ>=ED>KKgov|JE92aSI9M$00000NkvXX Hu0mjfd2v!+ delta 191 zcmV;w06_nk0*V5V7zqRe0001qplF?uEw*MQ3Q+I^ zP`o{UQbgsF|KwME0D|c`+;Quc3dD9Etyfo!b3YeV<@YEXOZ=+C<+K=pErx8s1NBQj zTYw{h0>pKm-rybp$vZPDA&Qt$ry@d^`RDaUmzJ_W5b%8(76NnPiVqm6QBUIy=anl9 t|1|kxVfxevGq=J7M6Ogn*oTk&cmW37M^9|MvxNWv002ovPDHLkV1l#MQEdPK diff --git a/graphics/pokemon/genesect/icon.png b/graphics/pokemon/genesect/icon.png index 6ab5e6f03546866e91cb635e3d243ff0500670b3..a448db60332e0a00942b3368569876e37b08a4f7 100644 GIT binary patch delta 321 zcmV-H0lxmF1B(NY7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S2}wjjR7i>Kl)(>)MZ~)?Ly>AMa5?#auJ~dMNy_O zgT|=I6z=%hqBIk@;;&u7F=rQEEZR+znDoL1+FPxb=Jb^l)~!tXR6N$Q6&%C!lMK=m zsL|m$gex}SRa9bskywVG`!tRYRsauNfie>*S8lJ=8NLX{lDwFZhrijA1Oc%{73=P z_%R1a=f@l%dn`PA$Q&T#gEc;+00}Ji{VNqThwpQaa8pYd^QWgnM^_pN7Dic~qJGdzFw zK?j{S8*nv&v1S^qi>di}b1z4sSJa4M(z#{Y)iX#YwTQz!9hsW6@2HG>J4N=0TsEeo zVkdf~`&rtnWvl@;cC~tD_5WktB*87wIHG|>gN8LikNgR`f-s0u)+5*gMxX5n)=Wug z3zwDY=cM!&JieqK7vSYp2&Cxo=@>^)grOnVfDmTX^+Fgra9jv;|3>0mRSJ{Lxdj(t tvL9*ZyFvQF+Jg(oesK1qY~+{y_y$t=_D>M9|8W2S002ovPDHLkV1kgdq)`9> diff --git a/graphics/pokemon/golett/icon.png b/graphics/pokemon/golett/icon.png index 20dd1f45ab2552b2c1f94630299e46c30bf3ec8a..a3513174898f6a17a50a6affe1e539e346299da8 100644 GIT binary patch delta 273 zcmV+s0q*|H0^9Kl*?rPT_7znNciIr2xkU?KXeyJZV00000NkvXXu0mjfUL15L delta 257 zcmV+c0sj8n0?Y!C7zqRe0001qplF?uEy9mxs z?b!D@LyXT}xR8wsm z@yY_Ap2s072Q(;a_uxrQ)U59>eenGh{A07ZFt8S8OnqTMq_Z%gG9cH&M6xtMXkkKH zMnjHT7*1@dd8b+!elq}OVX$L%juvMBFw)I_$Y$`C-_(x}gyWUPg$Nti00000NkvXX Hu0mjfwgPm* diff --git a/graphics/pokemon/gothita/icon.png b/graphics/pokemon/gothita/icon.png index 19da4895baded46899d0f2d313d07909ed9adb5f..8d280f51746defd2c090b23b5bc68898efba218d 100644 GIT binary patch delta 202 zcmV;*05$*30+j-g7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SlSxEDR7i>Kl)(9q^taN_cgA?$gh7`8ya|J#wx$$IsjkF78JV?C-~owEidb2BzZ+L=_->KmY&$07*qoM6N<$ Ef^mRZ`~Uy| delta 258 zcmV+d0sa1!0?h)D7zqRe0001qplF?uEB zW$HQs=1uDYtMT?kFI%xYmP9pju%OzO931W!Q}K8F^Q@2D2iE$^3!p?3g!OS^T48P# z@FN$ zZ~Lv~)?oEmi+p&E!~>*!ft`#;i%!NNWT|WpLKfu%;(2_d4>aRmha)60+yDRo07*qo IM6N<$f@=K~zYI?Uca| zgfIw1rRZgY%>V!G0&5e4ST7#dM2rWW*BRO-Ow(I;7jPjnV*r^r! u{?;SvogW+VwE1y%D~S2=2Lt5(`S1mMUJnBITYZcG0000@lCe(2FbszC29cHZ+3_#LpNh19Q`jI$peYnO zX_cWAR-H7?deD~AteazS4FFQb3qYO$QU)U`0JtDM>GO0njLWf-xSsD!g7un`-cDMK>$oSKlu3?+ zFbqYJSR|IG``@;|Qxp|MY!)r`rrKhKA09&Vw(X0;{UP6)R}AtI1>>qEgM386;N=tJ zW>zvT#uejDOqg%XR6tN-#Kfrj1dIw-#%wNOLd?WOL4d*7dKsdbs0#TWd1l|Piv*x( zy6?M1zTZw_5Neoz#X9nL02R9#5n1moIxND+rvUnV0&^2W9wYWugIKi1qS(`te~!Z> zJbhXIO^CE6k`f4JA*yb$JBig-yu9B3@$2{^!^neShCnLAyaiGi<`l@pF M07*qoM6N<$f{iMOqzb4G)1S9Se2l9e+Zp(dz@^5V9%KheW6ta_#U&jd_M;d2)Zd zarUFF&v?Lgd=zA}*v=fTe+TK7_GtE~rpYcYE7bgr{O@V~tR7cn1G&QebVEQ@K|X>Zf}qM(Nd+Y^RFLQcm?a$D3HVCR7sKp zAq;D#;E47A-^P*~aIdGFGO12wk??{oZQFl*;T6ONdt?AG!yBP@!p@m_0Hot&bjQ1Y zE6{(X6wK3pd=Oy#pYX~@uw%Rjz9Q@~0vAEJAyw?58)~gg!Gek%VBxJ*f1)1Zs(n=n z;_xsm)p%ZQ%s$|Mr<*ygB5;4FKAi1%6Rzvz15q$@N!2>wsPvIxSY-Z@5 zzcHxa0r-m{Vd*9toWRnGA7(imYq|)QsKcy^?X;%!d7S%%Kmx<5;WUgOLpRQ5bT6%3 z)<+e9aIJT^7t_^)t^{}Mr__yvr{#>|y^vP{_}aeXzy5lE6Tdzl)vvY1c0Zpbey&4a zqjfrqf2`5k`IGo<*+;1cjYd|S^S~>oMVYUG#mD? z++myI-`&A3?l8o^w10L7iQmd#1Z6ZKcaSk9cQ}Y&?!Yl5cgWKUcaZv*I~;6uPN)xe zs1onV9p;@X?v~feMgNHUdQ7I=>{n9%LnNoMGYtye}nx^hhOAD(CWx8NA4gPfr$R%QLQh9b->5>f4YgB*d zYYQ;~qX=gHR~LyX-g+AXb8vzrklW^Hq0YP{ZKc2IHL7^P92R;$x_-p)Ii$d1Z(DA<5yL z{llRR{DYv8v-$IQq#+whKZO=RxTk-e1_X0TI}Okmp}zi3gLGc(uxvC)*8DQAe$b%2 z497u3OnZ%!2AO)RgN7J)#;DT}W0E-V$Qun&@kj?AP#QWO>A(Xb7o7z$?RZF(j>mYo z4G)x#$G)xNVG1@p_JtJ>gP?ePxn05-7mj&4PD$?pSDxSQhpS7yo<+JPQ>`6OuTM{Z b)&Isf<7`_ymAV|{00000NkvXXu0mjf5E03g diff --git a/graphics/pokemon/karrablast/icon.png b/graphics/pokemon/karrablast/icon.png index f155236f285b5f2658706b68bd6097812a024435..9db6f2f4d390c517b263e1faaacd671ce89dff3e 100644 GIT binary patch delta 198 zcmV;%06G8t0g(cb7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sk4Z#9R7i>KlrauN zF$hD08d4%5xc_bI=vQionk*gu5Hs>*V8E>%-BgJx`;ICBbK6*K`dc8)N@A^05vlGT zHYu@y5TzCw5}{9}L((21(#1l46KQY&V-d_k;UJj6mr$s<0z~g~7C=jgt@s7i{iCCg zPJpz(1_%YlJ3!ba`=*XDR)8=I5LbW{hu$+EUUXFn3y6mj-~a#s07*qoM6N<$f@OeB AV*mgE delta 178 zcmV;j08Rgq0{sDy7zqRe0001qplF?uED6en1s?7=bLn|L|RS1hO9fWwsRZ*LS)dJ=U{GTFYg%H*KNKEA gfC&aQ`l*{f0PDk0c>OgKZ~y=R07*qoM6N<$g8Ji22LJ#7 diff --git a/graphics/pokemon/keldeo/icon.png b/graphics/pokemon/keldeo/icon.png index 4d8c580f229661a7219821a4d4192d1774b0c86e..a7b3f96ab5d96455bea80439c9482a554004d4f9 100644 GIT binary patch delta 333 zcmV-T0kZy&1D6Ak7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S6-h)vR7i>Kl*tal zFbqU1SxIbUdH(-zv0V_&hQx&nSUIH3bh4PfLDZ?FMI8~8(5m2eA3rnqYKsv%;X4PwTQcxo?cF|Ht zoUAvHk*FbW?0~9&Lec32;`|ArDTU=~xDn}7ciA7PU&3!t)wd7RoaV!@&&c()qOH8r zBQ+}$~-%0KxF} z_W(%(42}yxa1vk-5IqaMeg#N;=K~&kfW&+_Ne2*J;o%A_kT9=M*#TtMUjSM2;RTR) fd?>-DZ}Z^}ZRi;Ymtp5}00000NkvXXu0mjfOEZ(C delta 325 zcmV-L0lNN|1CIlc7zqRe0001qplF?uE4l);YV zFbG5koJb&9)c^nO7Vg+>JKjC*X>w_`sX&3r`}z6R4}kq-3)fWu7`__RS`~8=6s;Ad zA3((Te@+7DOI-lbYEo@3f-oBjsJf`kf-FHr3RpQ9)rd6%n1B+nyhuny^{r2sxrd0V zM2%A1eRP4|J9G1YiCRiAR~?@C+r(gI$pnSP{L<+061bZ^W{wtT&sm~(Q1!lYxXc_X z&FmECT&uhv1AjG>8YTF$0O?1;>?d{^+b!g=euoh|X2t^7;CecktdS8N~3uYLCEzGl4+YQ@7F z5E~v2fLQQw0>pxc10W_mJOy?@3_Ls^`2i3O4+9`OAfC=`0AvTmu-X7}0K^+0Ga%jo z*#L0>$N>;j8$f12900Nc;sB5b5Mx4bfUJD@0tDUx5`O^*k`W1pi4QYCK3`mWb>hPe qkk44lXC($7P5{~X@B+wx<-;H4{3QIlQUk{T0000j91k(hN7zqRe0001qplF?uEa}1Q~ zv>MIMjCP;n{Odvx5>(0krOnu2STwHZRmspcj7!F=UuUuI(x<5%8~bSxjj0w~fOMLgd1;tmuBhbs zZwb4gtfrX9RJ47(QeAM)F~nFG?XJJfgK2pjqPX*^ME3b31`qBMF}t7i6T^=y#Ju!o z-zv-#%DDc3`GfLirC--nvx|iLb_IX+a^W&IqQLz7`%rFO#a0U)*x;K_d7_dLmkrll zqT5N7fNWa{>jf22n9<>?{$SUo{(XCp{lYytxCD6Oqr*U_iWm3fNaue%Fw8u#7zR@} zMofn%+7O&#t8JKbCzR{_>P=kT-E!P1!&4d=jSZy+t$OM5Y>)dws+e9-0 z^AyC1C8Qz(6HM>uF7;SF7+y`qy?+2k7!QBJWa0%Fk>z6|wFiUIWk2#BOpQn^_h49E z|8$;%;ns%+vn4Q#XJAy)gE2k~7?8lN4+EwjryYFk!3;hIFt7IU2R>Ip3=)Ybb^rhX M07*qoM6N<$f@vxE7ytkO diff --git a/graphics/pokemon/landorus/icon.png b/graphics/pokemon/landorus/icon.png index b86a7cf7a84c0c2a3b37df31ace5b3593dc8d446..4b2ec8d4f791e3c238098ad842091aa980cc31db 100644 GIT binary patch delta 460 zcmV;-0Wq8BM#GZ@}^z5bYqn*W^rF~LOqdGf2kL?+o| zH^DSn+!-biFh@?zUD5J1cV-BPD?UTwQ6MN*JB||-E|7S(7^8TA>PjfyfdZ8fH40Q+ z(CQJUOlkq4Jjz3W3n+h*h~96~R6`K7#I8t*vZw(5o+4!SB2YsLR(vc)BeXuPN+<-! z5<_AgFpt|-L8&4I0`!RL1Kd=`O==Mtj#4Wm1yRr`)w(G%I#+>x)nEPgrT_snfqBXM z#N=g3f4>=!rX%J`n2wkeVPxThB4#Jd10cqSjWA(Cf9oJMsFV3-;VQ*;dGP>f@i z7llge9106!WWLG@>GOY(X;Q+DkZSO-TwSV^h1Rfj`MnT*fjNzFygiCXv2w;9@I93C zrw{SWY{@tVideRwd>5|O3()q3Na z*#oFTt*WtrLPbrl4XC>zT`Zx#+?T-<3r_R z>~1xCPO%N_ycL<^|=@R6OHbK;z=ng^Dd)svg!rvyQO%NKh4nfFAbS8+_ ze8lQRPy0oneT1MdQm7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&^R0PRUcK~zYI?UYdq z!!QVhtA@y+c>n+3E=k)pt7c^n+Za^H(;em%{HE!u4;9Yz{Mvy$G~lE`Qvj$A9LNf= zh_E(iZ%&+TLaN-Q4R>p>M<7Y*z}uOGdV~5!3;B11Dl%zFf*cgE;^G@ zBHtqm5pf+OTk?*7vMGKHnoElmd{Sd_3y@MUYFRbdiky&q$i*_DD29Q&bZNGceAR!| zukkRA>Co`7^CQGV$B!^c&kqfg^!y0*H~HaD`^XP>xd(puP sctFn&3-7=2164-2h^0$?U+2ReP;d^mcE0+<7k7zqRe0001qplF?uE@lCe(1Fc60G2B)Bos0evr zON4KzSXxzLZr=eA-HOy98S^H6m+pvnNYgpC400D_b4H5on1vN?%dh|byZF8=`||~< zpk-osjs>#A%h(RKjvcyD$eYZDmIp-SCW?6{p{_yZ80X?+uK57#0Wv0000?P=%ZT0004VQb$4nuFf3kks(BXNQv!~F%H8p2t{K) zRtH=B``@+@r&}P6x^xI0dBT9Lw{1_{5Be$d%}))qMpg)$nQD$O(%QRb1Wf^ygbWer z=n24q35aM`f}X}0l9nJMW^{1|_;iF|PQT)`K&*%_?;&krr+gD5pOUm@MS-|O&6(nc z<`vAcMXmR=qKQ~kwi7*>a}hAIoD*Ct$%#Dm#6QI&kOeG(Grl|c9r vNDdqVDHO8=Vzq-V1;Sb&`=_ga&E0qd{9Ft%EcQkh00000NkvXXu0mjfLgi(g delta 232 zcmVC!igTEHIJi z0y7WcoB3yQWc4LTaIFQMJ=yH94mc8T>zBLh-Q^Qv(cv7vDUJgmV@5LA90=LGsQfn6 zYg6z1l<|<1jh}IBQ{~rCt1s&81FhGl{s3~1KlsgW? zKnO%*xmY1SbN}0Bz)BIBU6+;;(>aV7V8eU8p131`i@Yk98knfsLW6Bn)nJ{O0|lj- z322Z4nOR^rwjk_ck`GsvoswRF!Mv)^@@!Fpfd#ig3G_v6F(CFzz^Qlnjd+( z2S2=+ycaT?;ym&iXa3;ex5o(+002ovPDHLkV1kf;gJS>y delta 298 zcmV+_0oDHM0`vlq7zqRe0001qplF?uEyT=;E%W7a0Mf-wyg1U4nJfLl%~*`jt+bH wT5T=?)pS~99c{^)!LkWS&`4Klu--A zAPj`t_~1jb-2eZ#OJW^U(+uaW4=_LdnI-b$BN znSiYye>#76JVu=9gO@ITs%f=ZlW% TzqG=E00000NkvXXu0mjf!9$Ej delta 312 zcmV-80muG}1A+sP7zqRe0001qplF?uE04a$=eoy%s_(B*wBM(Ix1 zUdecII_Ng-Eo~-Y&dmmn$Lv`ck>n)Ysl<@{ayrlaxCrxoKRy63ZK=4gF_)hJ0000< KMNUMnLSTZBcZKl(7zj zFbqUvTVi1F{r}(AmjnTc3rp3Z#X|<}adDjJN_pzb1>jm&vr7VIJAuRwCK>=Xx5*B+ zEUM7>wdymVtE#)Yz*QszM8!4M(5u;e456%CWTieJ;cVJVXn=8-Xpo|HJp-HoDX)6c zC;w%mC@H`;*np#S(>_^Td&N1cm@fh*N+hLpcRVI<-T9gIV} bpN)tYF3k;X?=f`q00000NkvXXu0mjf6p(w? delta 254 zcmV3DWd z)K_DN$qr#t4d%d>FDPZ&G0<(D$WBDkHEo1_khJ2z_cP z?x$WT8c~rWgw_+SQuGM;O4(r=!|*$?C@%vEB;FnwJl{0}?oKfsi3ijsO4v07*qoM6N<$ Ef;6gf8vpKlR*jq zAqYi-K+F$$|J#l>!ECHyHnRvH?f%2ku$1If)Y-)_c&UsSOvJIFsMQ4~Mrddqf*A+} zD}aZqU`v126 izTGP8QR+PBaRFBoZVhsRUZ+$50000 zXzNF^W%sUCD?8>RIqcWERqtORISlBPS07M4!+^#e1%$v5P7do|{a=rg96tQ#N9GvQ a9{>QdRdQJDO}$3|0000Kl*lRxL{uFz=wxuG`jKI%KpRDu zr9`p15=|5ft4`kmXar;pvKnw;NFo1nSm`$jO`P*Bq1(=!nS(&*7l6fxX%Yf*1H^7Z zlm@5)5`izElqFDq>JEC~N*||hL-)d-iUYJ%R?+BYfenM67smxsUPV33L!A3fJ_vq6_74J zZ5I#&9teoO|Gfg@0{=unT002ovPDHLkV1gez BeGUKs delta 281 zcmV+!0p|Ys0^gTjzBzx&~;PKjU^zCb|1%?&0~K6 z`wHx~8MxHa^)`cau@J63Oa3gtDO>=2z6ZN?xOA%J`N9rE^LZ)}^zaNAir7yyZ=qHG z*Fn`|u!1?!2nGC9gl#~GX{p*coDX8X+SxUOFgpF0moRyPd@c+v31j4AVW9ewFj5PH fo=O<~PM9Yk90~uj^~(AH0000Kl*tam zFbG7WIG7vr|9@MSNOb~ss~)Nz%F#0{#>v~Ze|!+Y3tg}_nZZrd>X;kQRD;M=7umt$ zQ8_?*?mBBA&j}_pm%BNn-5t=h9lf*cuBSd=Xlj>^##{~paBo&!i!fD_!uoeL*_cE} zHW0DT=l5Wwjf0MV$TbIiX~`khp3V`G=CBjdGGRcvN$fE?oR(XGodx5r)4JnO_u+R~ z1X_BCRBEmN<2T|heynU^m=fg7Mg9K=T;Sj8lrSrRc;P2N3Y}yGNKKdlAQfRQ04WJG z0Hh|&0Fat6BS31x3;?MJa{)+2n3E4j@Bv7KF+Mmzyg@J_=2jxI27pu>xA;CE9?tm~ UD`uDpasU7T07*qoM6N<$f>7#-h5!Hn delta 305 zcmV-10nYx61N#Dy7zqRe0001qplF?uESwi|0CuUt~vis{Y%Y4y79uN~RkY1$x~6q#%2qye`e zNWlbP=KvEiBLd7)W8(WW_{{F50>3-C2mV9}iC_G2dD1ckP&_i9$G(Ct@#*Mz*jIlr zzcFhYPle2{JoKXvQf8sv4ZYS(r3wLi08;ztpa-y$l5%wkBYUYuNk}65&CVV}3w~_% z{~X#rRsX(a3Q_|o5Ue2jBgro4Cao}(g;`VPX%WU7gBD@18kB`G24!K4L0K4MP!`4- zvHfDJO8&%-oy=x7O^X%{X<16m_xXJH<^G3W%Iu&$SNM}I&Ubzv4K6CF zcZ08v)XgcUt@>!_4hIF3yrPx#g+2^THxr~P0xLEQQGi-_tksdwZ7pDirdbv!Fsq}x zAPrI-1}fC~!M<~UG!<|NzM(M;3Y5CkO+5;zT2%3Dg1<`PjaY*^6?f!n$zE9=(AF#Z zQ=!Dy4@L*l_5NH1t$*q$a$Vz(@wR{VFLbSXdSc9?Y%fO2l2{Im!<6L0`)KLJFM z3BJdF0EB!!c#8i3$V2?Y(ExIcf8|4NAB;G}zwsfoH$DVFUipv!dErBC{oncU3-sP3 UMNJ<%QUCw|07*qoM6N<$f_;?Z$p8QV delta 456 zcmV;(0XP1q1d#-g7zqRe0001qplF?uE7!G5CCA_;NHQL2P++J zNhO5eEnYH2$vcIGO2~c(vm%PZ8igJ|j-9M+ku1ac4&(F3*k6zMwuZ)+yN?Xg zgxIs-*8uF%Lkjp>5(W_idKP-7^>z4*ZC=JM07+I*~eae4tZ@)(m^uv&aqar5LSph@6fC zQOYlwwxIV&3Zz|8IDN%5`rHKCfnLEi1?uM;+qQO~f~odpJYBny>(j;8PTkK+kH*Ah z9o5ll>!xK5N~?Lg^Xb{z+c|a~hG&0(#R$~@hxTkcfUh+r5H4@ODZWHMAuM$;ZVSw>`5*h5*XEPIb<|2TMq0& yVD!p?d=MC`R}SRE>Ng+r^yZ`UuRb9D#>WrNr8MZH*j(=b0000Kl*tOi zFbqVk_RUsC6nCdMdKw*YqvfTQY)K8Sf&U>#C=C5K1tZ|N=-nX zK2^jXa02BBWWaU;M6U$IeA`^ia+$>ls3c&f`-mz79s?wOt|A(k+<-l!TqOG#!~x`X zs)N87qkBX!dw>OG;KRd7iE}}~+?gbwTuYUqMn*&ynp~HLrFj&S3x{{8s+W5>2sHHG z7yr~TWeK!5_N|}MT_FEbAVFLTq$Vx}QddlTxh#;g9~K4DzS0j5N0$$&;MdZy00000 LNkvXXu0mjf@rZ4H delta 250 zcmVuK57zqRe0001qplF?uE zey3S4Q A4gdfE diff --git a/graphics/pokemon/scraggy/icon.png b/graphics/pokemon/scraggy/icon.png index e63301f36bcf3c7ed744c5691dbdaa5edcc04c48..f1baf8d0783dcf1f9f38795ff9905a8118403140 100644 GIT binary patch delta 207 zcmV;=05Jcs0-6Gl7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{Sm`OxIR7i>Kl)(za zFbqROeX!Mo_5XjncxxGh$gtC3L{}-UE$AC#>wiVEch9p4Fc7T|AObQ`ekoLf=71UG z2-*Q-6Bs^u{t%K4i)VpSit4iAdnE3H`(N8^Nsn%hy$b)&j@C|Vu5f86+uLt z2IIa?8vyGa0$SB+4qYc}p(!2OVu+yQVjXKj+KluHW4 zFbqQrRSfZfb^qIr5@u6~-Q|=LZS~@B@NsNCRU~WMtO8`CB4`mXAR~zQc!Z)PgaY_L zvK$25y9=;&CzL-G>q2S${1I4IA%Mdbg=Hh^VLqq#WE3K14*5wRWZ>+rnkALqTRO=} zn0YJLHDcT>y#5d*TU!_H1M;Q=a(5s2kNfZivBC^#eDwZM00000NkvXXu0mjfCTmi8 delta 175 zcmV;g08sys0{Q`v7zqRe0001qplF?uE3~g2Q+>fssMkQTRw`w zw|8zX$V&MAcD+mUM;6Fix9b_QiZ5O(S3S!|68W-f)v9$!#`0%c0Y%*WkpzCNTD-~y zNx*N_s`V?8o%ZGNs#VjF1^E9tPepYq{}QhdRL}fMTZ-npC0^+M|IaWA@PUz)V9*=W d2R{Yr0|0BIXTmgKRLc&- zAPhsLRGJjx|Nq-LJhVbXr%5|ai#QS232E#Q{_zUn9YBD45DrOcKumb3?gX@3qmvOX zl>utkNJ);VU}tE6U3CT+g(5~KNI(Xe5g>&=Du4ttL#4394tNBGB9X&-@d)f?Vnx)B zM_}*RBHK%G)9g%tm3hq)8CgWV!SgDLWIOD@>mlGl7Ud{d!s)V=;V5#3|NpTeThwto z2&+;^wwuksZi83@aOgoqS|Ye6Ldd)fXGE}Fat1wtZu9?G#~1D4j2gaZ;tqYAXM^bW z&;eJ2==M*y!>Uksw)&+_*K`l0+6zrV`=_w@e+N2VGh>4XU<00000NkvXXu0mjf8quBJ delta 358 zcmV-s0h#`%1F!>-7zqRe0001qplF?uEZrE5JmR}bBG+kQfQNO zv{Yz=ofHP76rP<1SF4>Y26kB__nyjnnw`Oao)Aw{yat+A2zHXj zA2b1s$@T#232574Nc7vi@Erq4)C|g_iWJE0j^@2hc2JPw++l~L*sv^Xx7VZ@#tDDU zF9ho*YtfIeYhI*$z54Gpc#5J^<^KWj+xOQAjh_LZc=@;*w|02+_x=m6L%`;I{-H%M zK#aHvGf6TPfLqtLv;t>I4#0rKvlq}B)VxBsV?Kp7MP`~@42d(3x3tH<1CS-T z4v3Vn=XVBWd{Cly=LZujt3&V3Z--J0IxG#s)au|30R6?vW15WULMt9=j;AJdCX>_Ddj$>so|G>#!fyKg31Z%uLg|&Hw-a07*qoM6N<$ Ef;5w+C;$Ke diff --git a/graphics/pokemon/thundurus/icon.png b/graphics/pokemon/thundurus/icon.png index 9295bb7526a977998ece954ea069cab5a1feff33..9b116651160765ef9d259797932fde36d79383e6 100644 GIT binary patch delta 455 zcmV;&0XY7mHjV_47#0Wv0000?P=%ZT0004VQb$4nuFf3klLr|-e*uh1L_t(YiRF}0 zj>8}fM2l%8kc{X4w_V#I!P!9iTd8QfQaaPI4dlIEU%7w}dd`my)z$EjVutjPVtOV^ znK|@JWXYrkN|%go2Ln=sM9d?>fdun_E7wwl&2Y_tB>Mq2u9caaSO{GrQnCi#>`U~I z5FM6KfsD+&ZJfCwe{6=L5Hb*HnItnODE&F`C?uKIyR2x97fUE3#MK<O!`15-162x{4N^BGXr0J<2CTxddo%6`NW^!)`#EQ&XhkG@9W(++db|5-2Z9{ z^Q8BJ^vy=^=YKYS``mvG<9?Zu{W0<{Up&pW=jVSv*>3My_Fi{&EhH?J%)6-1QqDUr z?3mJ@+Y&#S|0D17`KkOAmN@X(#G9R;VQjSyYi}Fuw9Rh2&g-y)DF(M(=GD33{Q0c- z?5Z2bDM3GWyNnyA@daNEyyp4Xea*$5aqAgx*uu!ua(|_>Jj`;(Uw+K*KK#G@d_8Dy zg|4+vxppeY!A>#FG~_w`<|-Uw_iNL5?0bI9PjU178vJ%87_=E53vhODegPQcJ6@dLS&;RI{n2*4i3_HXhx$yKzNp-F4qXk3IF=ORv2R z!e@jLM;dvQQAe9@`bqlFG_#py*4dU_gwhHtu79-hDyy!xiM8!_*m0+wciDBfFR$4* zZGZ8a{pPv9_nLjZCXa=4UH;)UKF;~`2rD>=@);g;!Q$~O4-n8!K6{D{!O3&-*;5@! z5glH$QO=oG9>arSSr@nc^4$;5{jJ|j4F8ee+@CyWHwepx7sM3S%nj?9?cz;Cd zJ+{CKd`!f6!pO3{DG*$`0RX$E)p~2XmEf*^_qu%^TKvd8YcAdH2+lQpwR_lO?KyUh z%fy9+{G1gV&5~QRtzjwoWre+VABxMIH;Rc%?BZhApSIfSn~+a=R4%N>S1#_p?$M{K zb>`4&a4opevv0e(UZ39PgOhO;K7Y?x>e%fe4BEs>d#N#55QT<2L`Yv8$r0v2wh zcpSbL*RiTZq95KWzAaP6nlc*^o(2!9DIR~!$*e8!T6qnnA^g`6^D{&~L#*P%oT206 zr(j64GdanO5)&=Dq4wh)U%9o#oM+Qa$Sl~J8_q1IC9l0=nJDboU@en94u5Sx-@p~| zY2E<@pve|2Eyjqe11Ang?;J4k;${G|FzQX(he^(ASg6fwFfCk1{7#RzcSn_Aje^a{ zmXH&kC8QO|IIum$8aK@o-8Cszje=E7f5LS$yD{BJ8z%uwMCHy4<7_gODB@8wgSV65 z#~NE$LZW+u?j&u>$A-Jd+<$T*a}vm1-NHf)45qOhNMt4`)y_di@??)6yn=t18geyt z$;{xQ;uf1S-At_Y2z+vBP(Uhnvo66M3`t0KoL^CAagoj^iA;CQJqrU4BXB z?E~p>lKR00fWgUq7FeMS>%S%WOFKCV8V zUbz8kgyR6ecE@X;%p1f@$KHfT$KUmzz4YBlrVYX^_8V_l+wMf5Zr0Up&mt72+asI? z=8DFM*HV;%eLny$AuO>6)E>wn;i10KTYXljTp4YI#>nvtPvF1{PfYNFlfB?X9Eh|! zk$s{CGa_>*Q_db25r5-x`eq69x~WQFy&!?s-`g1*bg2Ho zPaYBN57|H^_Lvz9Gb~}=&qBBH8viC=5n1_j*$Pm?>JvFp#eX0ZgyioK(CbXXVN~!R z@7SbFM<^JgHXKJ1Mcd!en7&B95|b1ZbBfl0XaEI6-at_LklXlmZ!`=r!Z=XbE<{tZ zm)mFOriaV>P6@m5Xvb$VVwV%`$3#T|Tx2|p@>lQx&5VTWKDYUNZJ#U&8(9llT5=nO zLe2xbWygZjA%8TA=YHJpg#?FymPaVg+_*e6Smy~#Ql#*kDK=#hi}eDP5WSdF zNlUe)Il(?jVcKs(Wsw#U1-67Xt8#CwWlvl|?QundR`qy*m# z#3aFTIR0dt!Ysc=t~cBKk8HEg$u<;QMb|Mhv4G1n?|%-Kb-|N7fI`{m+JZZ}*p09# zq&^&m#TP>H=8HKAGb%{F4*-d=06?&VKOGiK*UR&I85@#c6q;kEGH2mQXhsOsAdCwd zEBI{>kb%f&`tTM?0zj6X`xzEc8ui34bl&U@;+Tn8^1zU2Q`G`kA7uk(B9ufMz}v7q zs%}lcWq%Y;6js@{oZMD$h_1!O*%{Ct@D_=ob|=-;a|P7Q#N(9W)jWs;CkzpzP~;-V z707K$#Q+~3c`VHFqT-g~eFQcbM~uufdqu-0Xr?9!MiEJ@wjbF^3`ePF;LI!lCISKd zs2u_YJ8P8-&^Thp!#^#;wJ8&R#M2<$(aCc6;qZyBBt0Vucu})qvJ)Z!GMdj;GG2YOSoo}Rsx&fR1fWV3 zuYYLNsz6!AAUWbuhAQAzzz6`i9j=JH4m`nt#(>6m=`{rozcSrz-jHFWPig=QvlS36%9Q4p2n1lON{Rjw%)h-bP zb0FwEHt>dW%`q!c8_KZ_D&AG_0^^B@;&X(9vW*A2j&zJXUUChv(4$p#;!rSKB!69w zaTHx}LVqa<-}P&4QmP)=Ki7HsuwaHqW#PE0!u1!uV*V&t z%D+Li@nmVz3b1V-JBp=AI~_n#`G4e5ob)BjwImrWZ)cG#Gb#Ag#b*vsqEi$!o ze3~yVZ;6T>6Fg+41x|8ykvY-T3w63zs%ichPcb{ z2Zi8%$&!y~Ju3LcBf*JN*(CudFiZ=}AsC=ul3|?U61_<77F};3XGd{~&=zWyw_&lw zQ5t*J!_!q>mkt0=P!X&~mD+SCA2B(ls7$SzA20?KS}Q8HsE2tn=}zTsR}A>I#1rxa z;0^eF1bQqdTtIab@2Z1;!GH6hXt5u0n=KKXifWX(PU2>@EiTF2m{8)zXoxpBu|Jo2 zPo?$_L89`zV!`%y#KiPj~;Gq znzmJxAiEAjZ0Rls&W)?ORO+*cpjtmmX_S0dc`K&?5K|C|_c09qGjfZ{>8C)yI{aaQZ-X7)G=nFR6_vUXx(0 z(p(K&Z)r-=u5?9~z<+>kmJ%Ge0yjjG2qdmc1SB(BwQZV9x)0&r0f>;1q>Pxz;G-oNGiH!tLDIwpkjUht14(L=XBj{fcv@qtXXM> z)I@UxhkrULsfwnZh$m7N!D4MuVn4-~kP5Uv?W1T|?+F%1Mt^2>$64|1uB@-_iha8) z;+j+G2dSxg&8{}yj%HymkKRjaxaT;rBRaUK#Au7~JC!#HDNtN9d?Fh;@n(|L3-oIg z%=uP0Dke^hsKhxM^e`M!I*aZy&|SWQE1-FkzvVPDbw-^A^fxGE#YIJGJ(}_WZfvzW# zQ0@ILR}kjm-Vtu&)r``Q6T?24blMb&X$z*A4OOjLg2vu#en_L)G3EAM`Z~S z>`ZQ^W}5`4OZ|c>7_?0a0@l9FQVGAk+RtmY_7*Qn z*rO5=KY!l;N(-rxzK5VN zz>6eQcu6OH6SJwFqL28L_-tlC$2U2D!UlKi+kd!-;D7l{6XGZ}raCH;@NQI8TmN>0 z!d=aEtmWK2+2hq)a74 zQ$<>$9x;Vuc?8ed!%&)@=Yr>F2jlEtFsybk^z8vc;oN)7SqQB>B|qo^!uWphQk1FS0)S zBL3`)fcyzVIno1qp~!b?YEchj5A8=4dw_g5p0tgK>2+g;KrZ*GAZ=_|X)y*{EJ zA+GD80?8hZD_}7i$1br=s^+!|irR8-tDsT-Y+G*6P;I_X1MsN0tAf<`3hF1x@)7mx zj06q!BWA-QJ&f|7?r3fI5DCjjq%bMvt#w5KInKyq-Q5C(I4CyJ1%FEd=CA;0IDaQ& zKA+Z;0I`4VC+2rQv7Y_J$O7_dgJ+2G0`kh{Yyr7_X<^)+UcTJLxMGE^{lBH2^+VXM zqn?GSXtpm*b>2`(&4+C4L6Z!Bu0$~m-;Pos`^U)h{7p<`6sMYksuXKBa5}K#zt^{s56Qt>v!1XBea0LiqH?PiLID{OjI0YNUMyI)8e^q8(vS zN$p0K!gMjI5Jh?csN#=+NtVVCQXj*WSRm-=sO~1hh z7hXxFO-O{cdf@fCKQQmD8d?H@v70uwC?zrCLn2bJ6E72mOhixZ*wm4fs3)c;sm!3R ztAZq7cS86s)xkWxD0lc!=zlxjuC{g@n>}8KlrHw2kKCBkX> z^S%3Q6c8~)KUO)4Xy-Rk-a>Pism;vT5dA=+!;h(J=FPXvl2LtXl)hVAcQ5_h=GNEN zmf1gcw*KYD)`~iURc^b=_7|&+1uw?@Gz|Mi3-yqKs_=G;@G~1oVt<^*^ikyBs7M@pPe0{c`5fxnI2s#;W3}2z4+lskwG~h(|-sf-G1-1o7-xKvD+<)##<6? zl|)Q!ENum~<$QR7xPKF|_U{u2~_m^UOoOf&l1GLqCLa>Z}p(V`wKu4?n0YKRgm z{n~~~s%ihR4Fw+&684-P3HfZ`V#lEMR(lIG^|NJGxoh5D++W+df7i_o>TYN^Xc_y& z+tGFE6fE^XZ|xVqX>3y7)?k6Q`5c~h5IM2Ipg`zju7M97qkro!;@sEnwVkce>}k(C z^;%WIH5KgW%d@JfT|xEOx|-{64_2V2JroHa)IZ`!I9dTQkI-oNwNi{9HK3~O#Ig2p z6p^L~9w0#~LAz>lAlXEFZK`$chHC4d($I$LDBdxfd$dW0c*$4gPMc3y7=JWM4?i_g zb5#Mqt|n0)seg`nTRd-=@H-qmaul>ZClH`af!W>NSF$+RPkr^%Uv7o%)B65ue49UazEL~Av=(Aqa05%dWuf!_ zBQR7A+4nG$5$-$(zF{yQPk%o4QJ2^09PN)@p?bHR;(s5(#Qf-lL#vJOQd}I{+=f{p zQO*$+TX1j&-3dA7(f5;(LIn;isR8~d33v1^QUWFcL{Bm$FC8yc`n8dm4r^*73j>^^ zGxja)^TpSMj9F^4H98pQ_iOsBO=!JP*hR##Rb`Bv8?H5TsoHmwr*A*4f{;5m-@0---WOlYAK@e)n zG%1(}2YB)H0|s-g{bzVF|CimO*#FwwHa|DF|Eaf)<{jFkb=u97U`OLyrAk@A2w)k7 z2lL&OJ^Q@r>>)3ATki-6?IHbrhdqp`^R=g|=YRUAsr5mb7i3Dre&KB1p^sgvjsG$w z@et)+7^&wZgp;Zz?(JC|S;~??9iARx231P__C~AvnF@do&g&Famkc81&6%Uli@nFF zqCb7(vmafBUg{ekx%qC}pA>z`Mio6;hS+fi;a2AHgtlEkPr$`yuagap%G-U8L8=A* z(|; zEdGew+by_>#8bD)jV0xO+#TvVpoP%3QNi9xrHMFexmAD8k}VUfMGm7FR6^g4<+CLu zC?#gxdl2-VqLF%J^sjR_QB-`yTJ;@nhaQ*_}U=&3Cd~)_v*S)b6!Ha^nj@9wq~Z9T!+>CIj23ZjzN_lf@li&1f38_MLKaMC#&(an3#M*04i=9xOAM=kGgk3G~!2fabY>0*>Rr}}(At71<* zde0+Wi75<_;cY`}y`%m*rXl(Lpg6c-T>!VVG$V2Mx)q515`J3|Y5o^pfV;Nm1Ip2n zEL;#2d9Y_EG010qNS#tmYE+YT{E+YYWr9XB6000McNliru;{*#3Ck|iU z-d_L!0g_2XK~y-)&62%N!!Q(u{RWoliX7qWiIh9jz5pv557bJiU5muevmh8cxaA2b zO1!jEWSCrfKt`K+o-WDd%z7^i>I*M3d{uqk>-3hXX*eyyF=_eN)PqvPz^wdu|dbSKV3) zld$=fqFQ8WlMO{y)1^lcZV(R%!ZaryL7ZR(9znIkBgnoA`UDX=`Xqm-YOk- S^{G7o0000Kl)Vna zFbIT$0!s$&{ol6Wzgl3oODnZfZg2+3aai(q9Jl^fz?-_fZh(x2wUrsT7FOuL5veL> zt9f)S+W`)B68Cj?tvw+D%u&iAbqIxoUScqF`I<@Ez|G04q}EZ_h zg6s&>39=NKi=4z(j)3ZomjZ6)-{&6K=o=K_xJ6f=YcP=mp1~eCfbZk<$PG002ovPDHLk FV1oGta*6-| diff --git a/graphics/pokemon/tornadus/icon.png b/graphics/pokemon/tornadus/icon.png index a95eccdb309843c52a329a9cc99d8b737386ab3e..271e4c6b691a45a06dac96873b52aae1bc3037c5 100644 GIT binary patch delta 457 zcmV;)0XF`P1d;@h7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SkV!;AR7i>Kl*^KZ zAPht=k5md4o&W#a=>Q5>#oa8XYNEx$ZXkqsKA%4v_NGy^w0Bsd*oON&Uzrlcm{R<9 zSgjOI4V04WH$$mrq8cb8UUg3OKn{u+;lt`Mt5l6HR1rWm1DFnOU$o_Du?Ry0=sOM6 ztM()C^hu=FoFrp^S%B#s6-Y^nRgUWprJ^qYq>x%j&RB9p+rfnEx+Ss-SoDvn=U|!X z!7VXRmu#!StC&^kP$Wp;NmOkbN^>+rdzcsPR$%95GbN>p|4lKrd5ohwqMmY4<&5x`SI?8paFlP0*&h z!ERk^{1{tUy!P9%4d15Oefr{h`(^&)7QaE5-obmqG{n3SrvJlR!VJXh2s07$Oqhw7 zXTnUxYzQ+Evmwlhm@Q!jV)lgTh6F&xwuif-LW|Y-c~qpd%$GLSe+gso?b59N9ve?=%(a47=*#*{)VKjV#w8YsI}rjXcJ~P zV7}tK$9sEE04uJI{|biv-}MtgcGjLCR?U4uteSX&>Kl)(67238%EUwMSnPcJ;m{(6@l?07nBgtGm#nPkmT2 zUbPLoLIddHMI9Ieil`GRI5^}k& za#S#Z1TbXqr79v|#_TRWhMd!H!lUq8u*sZ2-gbY^qrcE^2S_|z1W4}xDnJmsv_-nnVm611M|F00000NkvXX Hu0mjf3aoL^ delta 241 zcmVJ~PM`uKwCCaULvMB{(f_kke+3|WeS8Ep& rhVem9U=of4b=g>_ypVD##{aDzTySRI6asRp00000NkvXXu0mjfp66&U diff --git a/graphics/pokemon/vanilluxe/icon.png b/graphics/pokemon/vanilluxe/icon.png index a7814563b43dcecc853e464c5a9bead356477096..c2f85c1e31a6b8efcc4f75844b2b09fc038c7abb 100644 GIT binary patch delta 305 zcmV-10nYyP0{a4x7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S`AI}UR7i>Klfe#z zFbG6VVNM+Q|G!;2t!_%SZanNsjMm62LSeS;wFl|6+=*+i@95D-ZQ-cR?%NO>{s<)>3>&$*Z;Nr8~JbfZ#VL< z6Tg&yoz=Dcnc)NZPcZt~5Jl$(a|pB-;NyzI zQhPOIDE3O05ETVG2{y1UQl#2^38Z=OhcWYs-b%bCV1lPJTVaVcv5y7? zO_TETbvJy$Ptcv+0iYF{Fji$M6U8ef`u^P&82yLCrkqc|$`Ie8oD&*4p-*B~SUH$Mo zuuI!6Zm)?vH&?cF65lNOGobmklnb3gR(69*u6+LFE{@h2ZsH795{&sElC_` wPUFD8#KA`p;}8Zr;t&Qq;ti_@%07*qoM6N<$f~+xzZU6uP diff --git a/graphics/pokemon/virizion/icon.png b/graphics/pokemon/virizion/icon.png index 4f7390e1f0bc7ba9cb8d5fbf9b3033ef1512f83c..68c0abd73026cb1b1fb2829aedf1d1ae3796f02e 100644 GIT binary patch delta 285 zcmV+&0pk9l1Lp#e7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&^R0Od(UK~zYI?UYNB zgfI+4N&IQAtoz@#?S!i7nmDkfdL~;vgd>BF9lPVIEmjt3@XYZ*}P-^ffE*J=~oG?4EkID delta 344 zcmV-e0jK`w0-*zt7zqRe0001qplF?uErlCe(1Fc60G1}6{6ir@iQ z+!+vRG7=%BVQYnmPnqh0M`(pQ(PykgB&IYaY1FAl8j1L9Rw{1uZ~N}|@6YqjRphJz zD@Vv&LEqUzi)0^ZOL0LSnAS((V?s?j9NPtWD)l3Pz%oUZ3|Am{y7`#IrUl4@47Y!L z4$0ADzP8>HMXQRx2r%1vq$?))iX!8~t9u&{OnAX@iWm>VmsD6>`X-j+6;AKvHR+*g z86nBF84SxJuMRWjZ2$RIwVDfi-37_LcPp@Bw6=S}`G|k1UnW}DW*fUgKR6&x% zAPlR^4CcVd|Nm`enlxZ1>1Fp;pOQ!@#vnZ&zgo)7?(tgXD`VC$i;`BI@`0<@%rN1* zygzO5f{#CV8`K?-$ONSTM8rs|PKYh24O|4(RHFbHs@67wGZ1!d2DMJO3w2x~;G$Hf zLT~V1HLkA;MS-Ayaed_z;vQ90_`Pr(Kq=5=u7g1ZFF+hum35Hjx`Xi?H1b2AhFxl`)rF2yz+zCK;Bag1c3vEQ(Rd7kivemAZd zw#(h$&tLs_-5tPg+Dm-o%VGah#$x{zF@tc}KS#_6n8W^TIbw#jCi~YEF*N*a{~R$M z53~JK#2B#HpWa+?(O`d#8Hd&WCjk=dp93V?KL^Na{~RET{d0hL+JEdXdKw_I+n)_v r43O>0xc%ShaN+MS>2PTMX*#?BeCHWnrL$_l00000NkvXXu0mjfLxjBZ delta 389 zcmV;00eb$|1J47H7zqRe0001qplF?uEq&aC3L60Ro3+wfK6VM&%9?^;JLW$80%N1++q<^myE3$(`|!` zuE!(m*M*dgPa*YNw|adkWgafa&ni8CYTe-Vp}MBUS1)O32Qfqy9}xENhrJ9W_24j)R?J&tT&@@KbmO={fLIAf=7t zAfvI~bI>jBJWAxS!vqV)acCo$0y#u5EpoVlK@JfNcn%Rv0**tz07ET@sh9#7+oADd jd632PlLsCy?Kd7jcC*^pca&b100000NkvXXu0mjfqIR*~ diff --git a/graphics/pokemon/watchog/icon.png b/graphics/pokemon/watchog/icon.png index 9ea2f1330861e104e87b225c4fd50e2e9400ef5a..4051ebde8b71f9f4a58c1da358a2315cce32c7e5 100644 GIT binary patch delta 340 zcmV-a0jvJA1D*qr7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S97#k$R7i>Kl);X} zFbG7!mWar~^Z$RlKvHdONF!BMPo;+{nb8=7@`!%*MgcdvjF%P+7LjWUT()AjfRYdD z>KGnE=%X(VY`g0_5AlHBvjM|&HHQZ@`(ZI`yzS5<0R35b|S_szPrr=K;Wk#;sfi#3bCK zrq+6II5x`l$`Na3spJ1`c?s#HJHw6stFP2o`9T>W6F>ZULCDMx$_SbG5&D9VnIA+M zAu~UyK*+=ossQlJkLvrM_)!Kt_;EIw3G&2`D~O%^@W1ji3&z0@i>SYF8(#3k+T1HvsuKAN~Ma?-DTT2m%WL0000 delta 361 zcmV-v0ha!r1G58=7zqRe0001qplF?uE@D7kQbAsrBk1&6g*^T-2w&{pkZb z0_HF!@QGqVIz;3ezy~TUTGaj5kotMW{X($*(SuX*zB|BbwH`pZwYydyZ-)e+oWFmi z8kYVqeJ15hgBb5&WZE!j#*1>Yf&~d zVEwW?uR8+LkfhP09hcLY!8!)m5spDmVE0K|DVsB1o{# zplL#-K#)QT3<8Cio1p*xUa6`JgduYK(xh&>x{2zi%l-HTZ>O0s;z+3w00000NkvXX Hu0mjf@fN3J diff --git a/graphics/pokemon/woobat/icon.png b/graphics/pokemon/woobat/icon.png index 354353e885e38969667231ae5d07a79acb8d47d9..c3640d5ad0786927671a74c72b046f028f54ae73 100644 GIT binary patch delta 258 zcmV+d0sa2L0?h)D7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{S%Sl8*R7i>KR6!2I zAPg%z1&Hkb|8{{g#0Ye^X`1S)7i>ZZvXA4&FM|9)hf4tw27xa|7;L!_z8X;^NJ{17zqRe0001qplF?uEI443~ z#|ma)#6pX0r=*W(9*EdlqIl-EKs*td0N}VsY)Ck)1H&+mE0eATx~v<$%r?7kwbo*s z0XXk;odabLb@4u1zW1Mx!~EW@(;=&q4k_YwNFzW_hc^8!7_Woj@cm$%4jVEOK;?B1 wq6oYWb{>G@Nr!9Zv)2J~!JQ6JtpCkC0iaxiI5gyV1^@s607*qoM6N<$g24o9eElMpVFv#YH@)<*>qC`>F<_keTKgZ%eBBD9uRD>cc7=+KgvS(&oBcel zsUn9_dn&~gePyET-R2*OP9TVo&bq7;t+Eiry2P0vPof^RZU43fO_c)r`&14C^{c?1 zXu=rZ29{gYPs99wvc}P(sXrJ;(ld=I zpWT$IN-a>*$fHr9H400000NkvXXu0mjfjpoKw delta 399 zcmV;A0dW5M1K9(R7zqRe0001qplF?uEh?klIwKjNBa0HDWgw=>#TW25mD`X@BSIr5r}#WXc`K-GV= zuATo=<`{g7KzN`>wFw4BShEIgl@vUySgOI%IG9+S6&=o6t;VTd>77f^Ik`+xTa>U@ zK!IcU&{L3TgKa(f-jH_5@aOvHTV%W2kq!MO$WZ&k!M9%Y@0U>4-UP1hK2j_r^EKpH zz~su6iU_)rj+L8Hz=$r-D`WvP&~tkiS-{}TIDsk8ZFi|;;&E~aw}n*S-=?ghKrA` t%G)+D4lBE9XbBZ#}7&S7{cUkE>-{l002ovPDHLkV1iOYx4-}Z diff --git a/graphics/pokemon/zoroark/icon.png b/graphics/pokemon/zoroark/icon.png index 08d5206f3bf1c434dd0a06819cc6a94cd2487d5d..338a576a4a19c8d1a7be3bced263f4d324c7acce 100644 GIT binary patch delta 359 zcmV-t0hs>G1F-{;7#0Wv0000?P=%ZT0004VQb$4nuFf3kks&{SFG)l}R7i>KluHi6 zFbqUvkg~9XegE6yaniLKm@HHM!l1H0m<*K-YGI-fNhG-@8MZ zU{MJUH}IYUVSciIL8}*$_6QDSu>V*kp}sQF))d3bmH<{HFhj+<3r3iZ{%CuIfx>w4 za7R~chIQ4@ZPSGDtdrDXZH(Nn9s5Yxc^*>LOGCMSasTln@d3c#gUR2f378Zy2f$>A zIRGX@Oax4dm@{CODks3KT?D{vh|!3k2^a@NAjkq3nglsUB4`6l2gD%ABOs_-Oy3Ol z)LMkpz=IdlsvVOu0Wb>!3`Ko{5?ne2g@hiV zN6ONnLvkiB892yyXxA3KK@l$85vQtO)35s%%!4Ha}zMh-rZ->aR%!yaI zlPU!ujcQL!L`*K+1W(S8yH#X5^o~L|EBUZRr(O70iCb*b*aW7tBEDhvr67+*fcAgY zvL_0_T#kYkZO%+O9CJ6_BL`z%h)-Yahf-lA8cgIapP7mvT@!melfVF}?9s1jF^)&V zG)rcmVr2;IFhI1GknEu2R3*iWWR@m2a##tlvibi6h%EEuj>}vhsk;1-3PIhx39P=N zuV?^6)R(uOD?IHsN>!3sct#ay#tv@oabxQyfDccW3sS>`RK&|;j$_*ise~v2`)@6| zA|=8Kj7}3iCZtqBR-u#k5h+!e6WaaI2-A4Ub8n^V3LoNK5u{bTWaQ)SI5jCtd;34G grtDWXu3Vhs2jjZ+NZw28Kl+6wU zAqa#u3#TT``@d}ge0fUbPMV6y@ZY7LP0Vo5)}d;yo`p#T zv51zlNbo|<*%(x{oT6iFRP`29TH1nc5TBqL1oohNs{`D0TPZ%y&;-P8C@WE7;*^hv zI>3^BzgcKL3=7nM7zX=3i6|QEp;!zX=f@uT|2CV?M3D+EP;7=oswa!2W25EQ@d vs{#a_5KId`bb!c`4+B6pe1LYs5BTr|uaFjZ1^bxY00000NkvXXu0mjfzbKzs delta 342 zcmV-c0jd6{1E2$t7zqRe0001qplF?uEb>!3`KPVf)@}^k-1Af z2SuZ`I%TGu#z1FFMC2)eSkks^C2N5nn9P;X*lU7ZOy zk(mw$B8r-NK`>!%Bg%F(I9gPLovR(u6rqQ?gDjYYLn~ooqjZtw#B*%+-I-A#ODUAYPI{ zb7=MLGeF$PSfYA1 zA-Nr?6mdaH8d5_<8ny1!5+7HdN47%Wy&(lsLi}JnkfL-8mC-jogsaG;NNoa~6qwop oV|>^JzT;y7CUtzkJ^qG|AK$;aS~SZP_5c6?07*qoM6N<$f?AuFT>t<8 From 48f90a715556d737948f92916862d14a94620aa8 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Sat, 1 Apr 2023 14:12:50 -0700 Subject: [PATCH 058/131] Update explanation in include/config/battle.h Changed the comment in include/config/battle.h per PR comment: https://github.com/rh-hideout/pokeemerald-expansion/pull/2878#discussion_r1154322931 Co-authored-by: Eduardo Quezada D'Ottone --- include/config/battle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config/battle.h b/include/config/battle.h index 66d4b92aa3..24f4ad4f15 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -183,7 +183,7 @@ // Other settings #define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. -#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, when the player only has one Pokémon in the party, randomly generated wild battles will always be a Single battle, regardless of the number used in B_DOUBLE_WILD_CHANCE. +#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD. #define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. #define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. #define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) From f292fefca34db71fb44dd675ce1bb0fa8e0dc01c Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Mon, 3 Apr 2023 09:18:47 -0700 Subject: [PATCH 059/131] fixed bad switchinabilities call in TerrainSeedLoop --- data/battle_scripts_1.s | 1 - 1 file changed, 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 200a044610..8a47217ff4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8839,7 +8839,6 @@ BattleScript_TerrainSeedLoop_NextBattler: addbyte gBattlerTarget, 0x1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TerrainSeedLoopIter restoretarget - call BattleScript_ActivateSwitchInAbilities return BattleScript_ActivateSwitchInAbilities: From d9ab2d1976468d8d3f251bab267205a619c53924 Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Mon, 3 Apr 2023 18:53:34 -0700 Subject: [PATCH 060/131] combined TerrainSeed and TerrainAbility loops + added terrain tests --- data/battle_scripts_1.s | 44 ++++--------- test/terrain_electric.c | 63 ++++++++++++++++++ test/terrain_grassy.c | 71 ++++++++++++++++++++- test/terrain_misty.c | 80 +++++++++++++++++++++++ test/terrain_psychic.c | 138 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 364 insertions(+), 32 deletions(-) create mode 100644 test/terrain_electric.c create mode 100644 test/terrain_misty.c create mode 100644 test/terrain_psychic.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8a47217ff4..ea7ef493c5 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2610,8 +2610,7 @@ BattleScript_EffectPsychicTerrain: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects goto BattleScript_MoveEnd BattleScript_EffectTopsyTurvy: @@ -6867,7 +6866,7 @@ BattleScript_OverworldTerrain:: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_SideStatusWoreOff:: @@ -7346,8 +7345,7 @@ BattleScript_SeedSowerActivates:: printstring STRINGID_TERRAINBECOMESGRASSY waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects return BattleScript_AngerShellActivates:: @@ -8828,16 +8826,18 @@ BattleScript_SnowWarningActivates:: call BattleScript_WeatherFormChanges end3 -BattleScript_TerrainSeedLoop: +BattleScript_ActivateTerrainEffects: savetarget setbyte gBattlerTarget, 0 -BattleScript_TerrainSeedLoopIter: +BattleScript_ActivateTerrainSeed: copybyte sBATTLER, gBattlerTarget - doterrainseed BS_TARGET, BattleScript_TerrainSeedLoop_NextBattler + doterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility removeitem BS_TARGET -BattleScript_TerrainSeedLoop_NextBattler: +BattleScript_ActivateTerrainAbility: + activateterrainchangeabilities BS_TARGET +BattleScript_ActivateTerrainEffects_Increment: addbyte gBattlerTarget, 0x1 - jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TerrainSeedLoopIter + jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateTerrainSeed restoretarget return @@ -8852,25 +8852,13 @@ BattleScript_ActivateSwitchInAbilities_Increment: copybyte gBattlerAttacker, sBATTLER return -BattleScript_ActivateTerrainAbilities: - copybyte sBATTLER, gBattlerAttacker - setbyte gBattlerAttacker, 0 -BattleScript_ActivateTerrainAbilities_Loop: - activateterrainchangeabilities BS_ATTACKER -BattleScript_ActivateTerrainAbilities_Increment: - addbyte gBattlerAttacker, 1 - jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateTerrainAbilities_Loop - copybyte gBattlerAttacker, sBATTLER - return - BattleScript_ElectricSurgeActivates:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_TERRAINBECOMESELECTRIC waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_MistySurgeActivates:: @@ -8879,8 +8867,7 @@ BattleScript_MistySurgeActivates:: printstring STRINGID_TERRAINBECOMESMISTY waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_GrassySurgeActivates:: @@ -8889,8 +8876,7 @@ BattleScript_GrassySurgeActivates:: printstring STRINGID_TERRAINBECOMESGRASSY waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_PsychicSurgeActivates:: @@ -8899,8 +8885,7 @@ BattleScript_PsychicSurgeActivates:: printstring STRINGID_TERRAINBECOMESPSYCHIC waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_HurtTarget_NoString: @@ -10183,7 +10168,6 @@ BattleScript_EffectHitSetRemoveTerrain: setterrain BattleScript_TryFaint playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds - call BattleScript_ActivateTerrainAbilities BattleScript_TryFaint: tryfaintmon BS_TARGET goto BattleScript_MoveEnd diff --git a/test/terrain_electric.c b/test/terrain_electric.c new file mode 100644 index 0000000000..b5608e661b --- /dev/null +++ b/test/terrain_electric.c @@ -0,0 +1,63 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Electric Terrain protects grounded battlers from falling asleep") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_SPORE); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Wobbuffet used ElctrcTrrain!"); + MESSAGE("Foe Claydol used Spore!"); + MESSAGE("Wobbuffet surrounds itself with electrified terrain!"); + MESSAGE("Wobbuffet used Spore!"); + MESSAGE("Foe Claydol fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Electric Terrain activates Electric Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_ELECTRIC_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_ELECTRIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Electric Seed, the defense of Wobbuffet rose!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Electr!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_ELECTRIC); + } +} + +SINGLE_BATTLE_TEST("Electric Terrain increases power of Electric-type moves by 30/50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } + TURN { MOVE(player, MOVE_THUNDER_SHOCK); } + } SCENE { + MESSAGE("Wobbuffet used ThunderShock!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_TERRAIN_TYPE_BOOST >= GEN_8) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} diff --git a/test/terrain_grassy.c b/test/terrain_grassy.c index 77f8a99271..cf83048750 100644 --- a/test/terrain_grassy.c +++ b/test/terrain_grassy.c @@ -15,5 +15,72 @@ SINGLE_BATTLE_TEST("Grassy Terrain recovers 1/16th HP at end of turn") } } -TO_DO_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 percent") -TO_DO_BATTLE_TEST("Grassy Terrain decreases power of Earthquake, Magnitude and Bulldoze by 50 percent") +SINGLE_BATTLE_TEST("Grassy Terrain activates Grassy Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_GRASSY_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_GRASSY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Grassy Seed, the defense of Wobbuffet rose!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Grass!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_GRASS); + } +} + +SINGLE_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN { MOVE(player, MOVE_ABSORB); } + } SCENE { + MESSAGE("Wobbuffet used Absorb!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_TERRAIN_TYPE_BOOST >= GEN_8) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +// Magnitude is not tested because its damage is variable. +SINGLE_BATTLE_TEST("Grassy Terrain decreases power of Earthquake and Bulldoze by 50 percent", s16 damage) +{ + bool32 terrain; + u16 move; + PARAMETRIZE { terrain = FALSE; move = MOVE_EARTHQUAKE; } // 0 + PARAMETRIZE { terrain = TRUE; move = MOVE_EARTHQUAKE; } // 1 + PARAMETRIZE { terrain = FALSE; move = MOVE_BULLDOZE; } // 2 + PARAMETRIZE { terrain = TRUE; move = MOVE_BULLDOZE; } // 3 + GIVEN { + ASSUME(gBattleMoves[MOVE_EARTHQUAKE].effect == EFFECT_EARTHQUAKE); + ASSUME(gBattleMoves[MOVE_BULLDOZE].effect == EFFECT_BULLDOZE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage); + } +} diff --git a/test/terrain_misty.c b/test/terrain_misty.c new file mode 100644 index 0000000000..dda5253f23 --- /dev/null +++ b/test/terrain_misty.c @@ -0,0 +1,80 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Misty Terrain protects grounded battlers from non-volatile status conditions") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + } WHEN { + TURN { MOVE(player, MOVE_MISTY_TERRAIN); MOVE(opponent, MOVE_TOXIC); } + TURN { MOVE(player, MOVE_TOXIC); } + } SCENE { + MESSAGE("Wobbuffet used MistyTerrain!"); + MESSAGE("Foe Claydol used Toxic!"); + MESSAGE("Wobbuffet surrounds itself with a protective mist!"); + NOT { STATUS_ICON(opponent, badPoison: TRUE); } + MESSAGE("Wobbuffet used Toxic!"); + STATUS_ICON(opponent, badPoison: TRUE); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain activates Misty Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_MISTY_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_MISTY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Misty Seed, the sp. defense of Wobbuffet rose!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Fairy!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_FAIRY); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain does not increase the power of Fairy-type moves", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + TURN { MOVE(player, MOVE_MOONBLAST); } + } SCENE { + MESSAGE("Wobbuffet used Moonblast!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain decreases power of Dragon-type moves by 50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + TURN { MOVE(player, MOVE_DRAGON_CLAW); } + } SCENE { + MESSAGE("Wobbuffet used Dragon Claw!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} diff --git a/test/terrain_psychic.c b/test/terrain_psychic.c new file mode 100644 index 0000000000..eb5103f314 --- /dev/null +++ b/test/terrain_psychic.c @@ -0,0 +1,138 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority moves") +{ + GIVEN { + PLAYER(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_QUICK_ATTACK); } + } SCENE { + MESSAGE("Claydol used PsychcTrrain!"); + MESSAGE("Claydol cannot use Quick Attack!"); + NOT { HP_BAR(opponent); } + MESSAGE("Foe Wobbuffet used Quick Attack!"); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain activates Psychic Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_PSYCHIC_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_PSYCHIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Psychic Seed, the sp. defense of Wobbuffet rose!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Psychc!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_PSYCHIC); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain increases power of Psychic-type moves by 30/50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_CONFUSION); } + } SCENE { + MESSAGE("Wobbuffet used Confusion!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_TERRAIN_TYPE_BOOST >= GEN_8) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target the user", s16 damage) +{ + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_RECOVER); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Recover!"); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all battlers", s16 damage) +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_HAZE); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Haze!"); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all opponents", s16 damage) +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_SPIKES); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Spikes!"); + } +} + +DOUBLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target allies", s16 damage) +{ + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(playerLeft, MOVE_HEAL_PULSE, target: playerRight); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Heal Pulse!"); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority field moves", s16 damage) +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_SUNNY_DAY); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Sunny Day!"); + } +} From 35952cf7ad81390e90d550b705f128ca24d9d76d Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 5 Apr 2023 13:07:02 +0100 Subject: [PATCH 061/131] Clamp RandomPercentage to 0...100 --- include/random.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/random.h b/include/random.h index fd340c26db..e7c2a3e284 100644 --- a/include/random.h +++ b/include/random.h @@ -80,8 +80,21 @@ enum RandomTag #define RandomPercentage(tag, t) \ ({ \ - const u8 weights[] = { 100 - t, t }; \ - RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \ + u32 r; \ + if (t <= 0) \ + { \ + r = FALSE; \ + } \ + else if (t >= 100) \ + { \ + r = TRUE; \ + } \ + else \ + { \ + const u8 weights[] = { 100 - t, t }; \ + r = RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \ + } \ + r; \ }) #define RandomElement(tag, array) \ From dfee8a4759c65bc222abf77c2371ccda0815d638 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 6 Apr 2023 00:26:52 +0200 Subject: [PATCH 062/131] OW Poison configs --- include/config/overworld.h | 3 +++ include/strings.h | 1 + src/field_control_avatar.c | 2 ++ src/field_poison.c | 14 ++++++++++++++ src/strings.c | 1 + 5 files changed, 21 insertions(+) diff --git a/include/config/overworld.h b/include/config/overworld.h index 7831858d27..f62588b5fd 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -4,6 +4,9 @@ // Movement config #define OW_RUNNING_INDOORS GEN_LATEST // In Gen4+, players are allowed to run indoors. +// Other settings +#define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all. + // Overworld flags // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. // Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. diff --git a/include/strings.h b/include/strings.h index 959bb8c22d..984247b218 100644 --- a/include/strings.h +++ b/include/strings.h @@ -180,6 +180,7 @@ extern const u8 gText_Confirm3[]; extern const u8 gText_Cancel4[]; extern const u8 gText_IsThisTheCorrectTime[]; extern const u8 gText_PkmnFainted_FldPsn[]; +extern const u8 gText_PkmnSurvived_FldPsn[]; extern const u8 gText_Coins[]; extern const u8 gText_Silver[]; extern const u8 gText_Gold[]; diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 96e9173c9b..b784a2ab86 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -565,11 +565,13 @@ static bool8 TryStartStepCountScript(u16 metatileBehavior) if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED_MOVE) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior)) { + #if OW_POISON_DAMAGE < GEN_5 if (UpdatePoisonStepCounter() == TRUE) { ScriptContext_SetupScript(EventScript_FieldPoison); return TRUE; } + #endif if (ShouldEggHatch()) { IncrementGameStat(GAME_STAT_HATCHED_EGGS); diff --git a/src/field_poison.c b/src/field_poison.c index f254a6d142..89463a1e3f 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -44,7 +44,9 @@ static void FaintFromFieldPoison(u8 partyIdx) struct Pokemon *pokemon = &gPlayerParty[partyIdx]; u32 status = STATUS1_NONE; +#if OW_POISON_DAMAGE < GEN_4 AdjustFriendship(pokemon, FRIENDSHIP_EVENT_FAINT_FIELD_PSN); +#endif SetMonData(pokemon, MON_DATA_STATUS, &status); GetMonData(pokemon, MON_DATA_NICKNAME, gStringVar1); StringGet_Nickname(gStringVar1); @@ -53,7 +55,11 @@ static void FaintFromFieldPoison(u8 partyIdx) static bool32 MonFaintedFromPoison(u8 partyIdx) { struct Pokemon *pokemon = &gPlayerParty[partyIdx]; +#if OW_POISON_DAMAGE < GEN_4 if (IsMonValidSpecies(pokemon) && GetMonData(pokemon, MON_DATA_HP) == 0 && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN) +#else + if (IsMonValidSpecies(pokemon) && GetMonData(pokemon, MON_DATA_HP) == 1 && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN) +#endif return TRUE; return FALSE; @@ -73,7 +79,11 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) if (MonFaintedFromPoison(tPartyIdx)) { FaintFromFieldPoison(tPartyIdx); + #if OW_POISON_DAMAGE < GEN_4 ShowFieldMessage(gText_PkmnFainted_FldPsn); + #else + ShowFieldMessage(gText_PkmnSurvived_FldPsn); + #endif tState++; return; } @@ -127,7 +137,11 @@ s32 DoPoisonFieldEffect(void) { // Apply poison damage hp = GetMonData(pokemon, MON_DATA_HP); + #if OW_POISON_DAMAGE < GEN_4 if (hp == 0 || --hp == 0) + #else + if (hp == 1 || --hp == 1) + #endif numFainted++; SetMonData(pokemon, MON_DATA_HP, &hp); diff --git a/src/strings.c b/src/strings.c index 8815212e05..d297c45352 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1192,6 +1192,7 @@ const u8 gText_IcePunch48BP[] = _("ICE PUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_ThunderPunch48BP[] = _("THUNDERPUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_FirePunch48BP[] = _("FIRE PUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} fainted…\p\n"); +const u8 gText_PkmnSurvived_FldPsn[] = _("{STR_VAR_1} survived the poisoning.\nThe poison faded away!\p"); const u8 gText_Marco[] = _("MARCO"); const u8 gText_TrainerCardName[] = _("NAME: "); const u8 gText_TrainerCardIDNo[] = _("IDNo."); From 50b5dba6559c6804c5cb3e760243058c6a6321ad Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 6 Apr 2023 10:13:32 +0200 Subject: [PATCH 063/131] Fix string issue as requested by Jaizu --- include/strings.h | 1 - src/field_poison.c | 4 ---- src/strings.c | 5 ++++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/strings.h b/include/strings.h index 984247b218..959bb8c22d 100644 --- a/include/strings.h +++ b/include/strings.h @@ -180,7 +180,6 @@ extern const u8 gText_Confirm3[]; extern const u8 gText_Cancel4[]; extern const u8 gText_IsThisTheCorrectTime[]; extern const u8 gText_PkmnFainted_FldPsn[]; -extern const u8 gText_PkmnSurvived_FldPsn[]; extern const u8 gText_Coins[]; extern const u8 gText_Silver[]; extern const u8 gText_Gold[]; diff --git a/src/field_poison.c b/src/field_poison.c index 89463a1e3f..da162e4134 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -79,11 +79,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) if (MonFaintedFromPoison(tPartyIdx)) { FaintFromFieldPoison(tPartyIdx); - #if OW_POISON_DAMAGE < GEN_4 ShowFieldMessage(gText_PkmnFainted_FldPsn); - #else - ShowFieldMessage(gText_PkmnSurvived_FldPsn); - #endif tState++; return; } diff --git a/src/strings.c b/src/strings.c index d297c45352..847b2849a6 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1191,8 +1191,11 @@ const u8 gText_PsychUp48BP[] = _("PSYCH UP{CLEAR_TO 0x4E}48BP"); const u8 gText_IcePunch48BP[] = _("ICE PUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_ThunderPunch48BP[] = _("THUNDERPUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_FirePunch48BP[] = _("FIRE PUNCH{CLEAR_TO 0x4E}48BP"); +#if OW_POISON_DAMAGE < GEN_4 const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} fainted…\p\n"); -const u8 gText_PkmnSurvived_FldPsn[] = _("{STR_VAR_1} survived the poisoning.\nThe poison faded away!\p"); +#else +const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} survived the poisoning.\nThe poison faded away!\p"); +#endif const u8 gText_Marco[] = _("MARCO"); const u8 gText_TrainerCardName[] = _("NAME: "); const u8 gText_TrainerCardIDNo[] = _("IDNo."); From bd4736cc97dba7dd5409d49175ca8a89750c51e2 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 5 Apr 2023 21:50:26 +0200 Subject: [PATCH 064/131] initial commit test multi battle final remove empty line --- include/battle_main.h | 2 ++ src/battle_main.c | 6 ++---- src/battle_tower.c | 45 +++++++++++++++++++++++++++--------------- test/trainer_control.c | 2 +- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/include/battle_main.h b/include/battle_main.h index 8d1aad454e..4f20e4c17a 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -70,6 +70,8 @@ void SpecialStatusesClear(void); void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk); bool32 IsWildMonSmart(void); u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags); +void ModifyPersonalityForNature(u32 *personality, u32 newNature); +u32 GeneratePersonalityForGender(u32 gender, u32 species); extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE]; diff --git a/src/battle_main.c b/src/battle_main.c index efbf1b8195..fb2f3cb4cf 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -120,8 +120,6 @@ static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite); static void TrySpecialEvolution(void); static u32 Crc32B (const u8 *data, u32 size); static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i); -static void ModifyPersonalityForNature(u32 *personality, u32 newNature); -static u32 GeneratePersonalityForGender(u32 gender, u32 species); EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0; @@ -1925,7 +1923,7 @@ static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i) return Crc32B(buffer, n); } -static void ModifyPersonalityForNature(u32 *personality, u32 newNature) +void ModifyPersonalityForNature(u32 *personality, u32 newNature) { u32 nature = GetNatureFromPersonality(*personality); s32 diff = abs(nature - newNature); @@ -1938,7 +1936,7 @@ static void ModifyPersonalityForNature(u32 *personality, u32 newNature) *personality -= (diff * sign); } -static u32 GeneratePersonalityForGender(u32 gender, u32 species) +u32 GeneratePersonalityForGender(u32 gender, u32 species) { const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[species]; if (gender == MON_MALE) diff --git a/src/battle_tower.c b/src/battle_tower.c index a4758b9304..4e16467f04 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -3103,25 +3103,38 @@ static void FillPartnerParty(u16 trainerId) case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED: { const struct TrainerMonCustomized *partyData = gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].party.EverythingCustomized; + u32 otIdType = OT_ID_RANDOM_NO_SHINY; - CreateMon(&gPlayerParty[i], partyData[i].species, partyData[i].lvl, 0, TRUE, j, TRUE, otID); - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem); + if (partyData[i].gender == TRAINER_MON_MALE) + j = (j & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species); + else if (partyData[i].gender == TRAINER_MON_FEMALE) + j = (j & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species); + if (partyData[i].nature != 0) + ModifyPersonalityForNature(&j, partyData[i].nature - 1); + if (partyData[i].isShiny) + { + otIdType = OT_ID_PRESET; + otID = HIHALF(j) ^ LOHALF(j); + } + + CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, 0, TRUE, j, otIdType, otID); + SetMonData(&gPlayerParty[i + 3], MON_DATA_HELD_ITEM, &partyData[i].heldItem); // TODO: Figure out a default strategy when moves are not set, to generate a good moveset for (j = 0; j < MAX_MON_MOVES; ++j) { - SetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); - SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); + SetMonData(&gPlayerParty[i+3], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); + SetMonData(&gPlayerParty[i+3], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); } - SetMonData(&gPlayerParty[i], MON_DATA_IVS, &(partyData[i].iv)); + SetMonData(&gPlayerParty[i+3], MON_DATA_IVS, &(partyData[i].iv)); if (partyData[i].ev != NULL) { - SetMonData(&gPlayerParty[i], MON_DATA_HP_EV, &(partyData[i].ev[0])); - SetMonData(&gPlayerParty[i], MON_DATA_ATK_EV, &(partyData[i].ev[1])); - SetMonData(&gPlayerParty[i], MON_DATA_DEF_EV, &(partyData[i].ev[2])); - SetMonData(&gPlayerParty[i], MON_DATA_SPATK_EV, &(partyData[i].ev[3])); - SetMonData(&gPlayerParty[i], MON_DATA_SPDEF_EV, &(partyData[i].ev[4])); - SetMonData(&gPlayerParty[i], MON_DATA_SPEED_EV, &(partyData[i].ev[5])); + SetMonData(&gPlayerParty[i+3], MON_DATA_HP_EV, &(partyData[i].ev[0])); + SetMonData(&gPlayerParty[i+3], MON_DATA_ATK_EV, &(partyData[i].ev[1])); + SetMonData(&gPlayerParty[i+3], MON_DATA_DEF_EV, &(partyData[i].ev[2])); + SetMonData(&gPlayerParty[i+3], MON_DATA_SPATK_EV, &(partyData[i].ev[3])); + SetMonData(&gPlayerParty[i+3], MON_DATA_SPDEF_EV, &(partyData[i].ev[4])); + SetMonData(&gPlayerParty[i+3], MON_DATA_SPEED_EV, &(partyData[i].ev[5])); } if (partyData[i].ability != ABILITY_NONE) { @@ -3133,19 +3146,19 @@ static void FillPartnerParty(u16 trainerId) break; } if (j < maxAbilities) - SetMonData(&gPlayerParty[i], MON_DATA_ABILITY_NUM, &j); + SetMonData(&gPlayerParty[i+3], MON_DATA_ABILITY_NUM, &j); } - SetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP, &(partyData[i].friendship)); + SetMonData(&gPlayerParty[i+3], MON_DATA_FRIENDSHIP, &(partyData[i].friendship)); if (partyData[i].ball != ITEM_NONE) { ball = partyData[i].ball; - SetMonData(&gPlayerParty[i], MON_DATA_POKEBALL, &ball); + SetMonData(&gPlayerParty[i+3], MON_DATA_POKEBALL, &ball); } if (partyData[i].nickname != NULL) { - SetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, partyData[i].nickname); + SetMonData(&gPlayerParty[i+3], MON_DATA_NICKNAME, partyData[i].nickname); } - CalculateMonStats(&gPlayerParty[i]); + CalculateMonStats(&gPlayerParty[i+3]); } } diff --git a/test/trainer_control.c b/test/trainer_control.c index 3079422076..2a21dcdf61 100644 --- a/test/trainer_control.c +++ b/test/trainer_control.c @@ -81,7 +81,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon") EXPECT(GetMonData(&testParty[0], MON_DATA_HELD_ITEM, 0) == ITEM_ASSAULT_VEST); EXPECT(GetMonData(&testParty[1], MON_DATA_HELD_ITEM, 0) == ITEM_NONE); - + EXPECT(GetMonData(&testParty[0], MON_DATA_HP_IV, 0) == 25); EXPECT(GetMonData(&testParty[0], MON_DATA_ATK_IV, 0) == 26); EXPECT(GetMonData(&testParty[0], MON_DATA_DEF_IV, 0) == 27); From 4709d2b46fdc70eb1e02ba83abf5e6712e3bfebd Mon Sep 17 00:00:00 2001 From: Jaizu Date: Fri, 7 Apr 2023 10:53:44 +0200 Subject: [PATCH 065/131] Fix trainers having empty movesets --- src/battle_main.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index efbf1b8195..4bd0ce9078 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -122,6 +122,7 @@ static u32 Crc32B (const u8 *data, u32 size); static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i); static void ModifyPersonalityForNature(u32 *personality, u32 newNature); static u32 GeneratePersonalityForGender(u32 gender, u32 species); +static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry); EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0; @@ -1947,6 +1948,29 @@ static u32 GeneratePersonalityForGender(u32 gender, u32 species) return speciesInfo->genderRatio / 2; } +static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry) +{ + bool32 noMoveSet = TRUE; + u32 j; + + for (j = 0; j < MAX_MON_MOVES; ++j) + { + if (partyEntry->moves[j] != MOVE_NONE) + noMoveSet = FALSE; + } + if (noMoveSet) + { + // TODO: Figure out a default strategy when moves are not set, to generate a good moveset + return; + } + + for (j = 0; j < MAX_MON_MOVES; ++j) + { + SetMonData(mon, MON_DATA_MOVE1 + j, &partyEntry->moves[j]); + SetMonData(mon, MON_DATA_PP1 + j, &gBattleMoves[partyEntry->moves[j]].pp); + } +} + u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags) { u32 personalityValue; @@ -2049,12 +2073,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer CreateMon(&party[i], partyData[i].species, partyData[i].lvl, 0, TRUE, personalityValue, otIdType, fixedOtId); SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem); - // TODO: Figure out a default strategy when moves are not set, to generate a good moveset - for (j = 0; j < MAX_MON_MOVES; ++j) - { - SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); - SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); - } + CustomTrainerPartyAssignMoves(&party[i], &partyData[i]); SetMonData(&party[i], MON_DATA_IVS, &(partyData[i].iv)); if (partyData[i].ev != NULL) { From e1beb55a51406ab9f9932b82dbc5b668b3aa9287 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Fri, 7 Apr 2023 11:07:52 +0200 Subject: [PATCH 066/131] Fix overworld poison not working on newer generations config --- src/field_control_avatar.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index b784a2ab86..96e9173c9b 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -565,13 +565,11 @@ static bool8 TryStartStepCountScript(u16 metatileBehavior) if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED_MOVE) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior)) { - #if OW_POISON_DAMAGE < GEN_5 if (UpdatePoisonStepCounter() == TRUE) { ScriptContext_SetupScript(EventScript_FieldPoison); return TRUE; } - #endif if (ShouldEggHatch()) { IncrementGameStat(GAME_STAT_HATCHED_EGGS); From d57d8e6e71ddfee8fea737db5b2c30c540fd196e Mon Sep 17 00:00:00 2001 From: Philipp AUER Date: Fri, 7 Apr 2023 11:35:30 +0200 Subject: [PATCH 067/131] Revert "Fix overworld poison not working on newer generations config" This reverts commit e1beb55a51406ab9f9932b82dbc5b668b3aa9287. --- src/field_control_avatar.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 96e9173c9b..b784a2ab86 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -565,11 +565,13 @@ static bool8 TryStartStepCountScript(u16 metatileBehavior) if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED_MOVE) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior)) { + #if OW_POISON_DAMAGE < GEN_5 if (UpdatePoisonStepCounter() == TRUE) { ScriptContext_SetupScript(EventScript_FieldPoison); return TRUE; } + #endif if (ShouldEggHatch()) { IncrementGameStat(GAME_STAT_HATCHED_EGGS); From 59dfc7c3ad513ee2bc05b43e80eedf7dfccb43ee Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Fri, 7 Apr 2023 06:07:12 -0700 Subject: [PATCH 068/131] Update include/config/battle.h Took suggestions from https://github.com/rh-hideout/pokeemerald-expansion/pull/2875#discussion_r1160574308 Co-authored-by: LOuroboros --- include/config/battle.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index 77e0e0f4d9..790ad78cca 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -155,8 +155,8 @@ #define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active #define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15) -//Flag and Var settings -#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If set to TRUE, Flag and Var settings (B_FLAG_INVERSE_BATTLE,B_FLAG_FORCE_DOUBLE_WILD,B_SMART_WILD_AI_FLAG,B_FLAG_NO_BAG_USE,B_FLAG_NO_CATCHING,B_VAR_WILD_AI_FLAGS, and VAR_TERRAIN) will be reset when the player whites out. +// Flag and Var settings +#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If TRUE, Overworld_ResetBattleFlagsAndVars will reset battle-related Flags and Vars when the player whites out. // Terrain settings #define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades. From 903b56756d8ed1b860917e61e05528796e56cb01 Mon Sep 17 00:00:00 2001 From: sbird Date: Sat, 8 Apr 2023 02:21:19 +0200 Subject: [PATCH 069/131] fix an oversight that caused battles to continuesly be double battles --- src/battle_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/battle_main.c b/src/battle_main.c index efbf1b8195..9d4c9dc9cb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2111,7 +2111,13 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir return 0; retVal = CreateNPCTrainerPartyFromTrainer(party, &gTrainers[trainerNum], firstTrainer, gBattleTypeFlags); - gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_TRAINER_HILL))) + { + gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle; + } + return retVal; } void VBlankCB_Battle(void) From 02af4d0943ccd5f982808727deff6999bc3216e9 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 8 Apr 2023 18:53:04 +0200 Subject: [PATCH 070/131] Fixes Ominous Wind targeting --- src/data/battle_moves.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 64ce246862..3dc21a5382 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -7884,7 +7884,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .accuracy = 100, .pp = 5, .secondaryEffectChance = 10, - .target = MOVE_TARGET_BOTH, + .target = MOVE_TARGET_SELECTED, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST, .split = SPLIT_SPECIAL, From bd54c70020f732fd047018019867212c7c013141 Mon Sep 17 00:00:00 2001 From: aaghaht Date: Mon, 10 Apr 2023 10:47:31 +0530 Subject: [PATCH 071/131] Add PLA evo items --- .../items/icon_palettes/black_augurite.pal | 19 +++++++++ graphics/items/icon_palettes/linking_cord.pal | 19 +++++++++ graphics/items/icon_palettes/peat_block.pal | 19 +++++++++ graphics/items/icons/black_augurite.png | Bin 0 -> 385 bytes graphics/items/icons/linking_cord.png | Bin 0 -> 380 bytes graphics/items/icons/peat_block.png | Bin 0 -> 403 bytes include/constants/items.h | 6 ++- include/constants/pokemon.h | 1 + include/graphics.h | 6 +++ src/data/graphics/items.h | 9 ++++ src/data/item_icon_table.h | 3 ++ src/data/items.h | 36 ++++++++++++++++ src/data/pokemon/evolution.h | 40 ++++++++++++------ src/data/pokemon/item_effects.h | 3 ++ src/data/text/item_descriptions.h | 15 +++++++ src/pokemon.c | 5 +++ 16 files changed, 167 insertions(+), 14 deletions(-) create mode 100644 graphics/items/icon_palettes/black_augurite.pal create mode 100644 graphics/items/icon_palettes/linking_cord.pal create mode 100644 graphics/items/icon_palettes/peat_block.pal create mode 100644 graphics/items/icons/black_augurite.png create mode 100644 graphics/items/icons/linking_cord.png create mode 100644 graphics/items/icons/peat_block.png diff --git a/graphics/items/icon_palettes/black_augurite.pal b/graphics/items/icon_palettes/black_augurite.pal new file mode 100644 index 0000000000..0d67abee39 --- /dev/null +++ b/graphics/items/icon_palettes/black_augurite.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +120 192 168 +0 0 0 +111 108 124 +58 48 49 +206 206 214 +151 149 160 +142 93 117 +89 62 76 +255 255 255 +111 109 124 +194 192 202 +88 62 76 +80 74 88 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/items/icon_palettes/linking_cord.pal b/graphics/items/icon_palettes/linking_cord.pal new file mode 100644 index 0000000000..8be2b522f7 --- /dev/null +++ b/graphics/items/icon_palettes/linking_cord.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +128 192 168 +87 87 88 +155 158 156 +117 114 116 +0 0 0 +36 37 42 +62 66 68 +56 57 61 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/items/icon_palettes/peat_block.pal b/graphics/items/icon_palettes/peat_block.pal new file mode 100644 index 0000000000..8d4b5e3b6f --- /dev/null +++ b/graphics/items/icon_palettes/peat_block.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +128 198 168 +32 32 32 +230 217 213 +199 189 184 +156 135 143 +102 83 83 +143 118 130 +65 56 56 +179 162 151 +117 100 100 +210 183 192 +180 158 167 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/items/icons/black_augurite.png b/graphics/items/icons/black_augurite.png new file mode 100644 index 0000000000000000000000000000000000000000..8be2bc188c9b3d35e52d8fe0f09e3c6dcd62f9c5 GIT binary patch literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w_7YEDSN7*jl0s${dOxN}0fod% zTq88foYA|NsB|+?qoNPDR-H z1b9UN)j+_MpjF3#EXE{ncbET5**_fxa+Z3!IEGZrNls{Ba${s;5pa5BFiWAZ#Z^$o zFE|#N9}!~hJ-tw7fslgqF~-f^t!alWkERJN zOt3w4%%N=4!yp6qTQ_d#?7UN=b|gdLwuP>;iNKkgIXQEtO*73_JaW*XY}S>a4y(k? zTTBjLn;973o7on$I*iq6PGv+u+Ota%D^{oaottCnF7S-mQ6a&Bongs&%|BLa|9%1a N!_(EzWt~$(69B6(f(ZZs literal 0 HcmV?d00001 diff --git a/graphics/items/icons/linking_cord.png b/graphics/items/icons/linking_cord.png new file mode 100644 index 0000000000000000000000000000000000000000..a3f92da04b753298958b4a21333b3732d5ecabb4 GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w_7YEDSN7*jQtZl#rF9~^fkNUX zt`Q}{`DrEPiAAXl?mjL+V-(6#ixiCYObT0EHc6ehi9>Q98Tw zV!4Qf$#R>u38|0je70)el9zf?yJzz~6KBWA4u+ tk(HM8&b}7oSqW8k<^3Ob?Rr&I!_53wgT>=z`d5&TJYD@<);T3K0RRPqddL6( literal 0 HcmV?d00001 diff --git a/graphics/items/icons/peat_block.png b/graphics/items/icons/peat_block.png new file mode 100644 index 0000000000000000000000000000000000000000..9c106598756eeef0a1e141e71fd46d1569c72001 GIT binary patch literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w_7YEDSN7*jQXC@Uiu2R7fkNUX zt`Q}{`DrEPiAAXl?mjL+V-(6#ixiCYObT0Gowy z&x<4^#DqS2^hjz}*gHGc6E|h=J&JoY&2F>Ip_eP7-i28n6+ZHjPxt=bt!pkFJ<59I zrqtfsq9+QO3(N9v?!9eVljbFLLhj(*-R0Hq=S+LVQ6|%|UG=Oh!z)t-b=G%^j+x@_ fD(ktp9`K7Z97{B*?YwkR0OU7MS3j3^P6= 0 && gLocalTime.hours < 12 && gEvolutionTable[species][i].param == evolutionItem) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; } } break; From 0f958806eaba35ee9fe11eaf9609461b3ee92672 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Mon, 10 Apr 2023 14:39:14 +0200 Subject: [PATCH 072/131] Remove unused battle funcs --- include/battle_interface.h | 1 - src/battle_interface.c | 18 ------------------ 2 files changed, 19 deletions(-) diff --git a/include/battle_interface.h b/include/battle_interface.h index e0f30b3097..e2937748a4 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -81,7 +81,6 @@ u8 CreateSafariPlayerHealthboxSprites(void); void SetBattleBarStruct(u8 battler, u8 healthboxSpriteId, s32 maxVal, s32 currVal, s32 receivedValue); void SetHealthboxSpriteInvisible(u8 healthboxSpriteId); void SetHealthboxSpriteVisible(u8 healthboxSpriteId); -void DestoryHealthboxSprite(u8 healthboxSpriteId); void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly); void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHpBoxes); void InitBattlerHealthboxCoords(u8 battler); diff --git a/src/battle_interface.c b/src/battle_interface.c index 35c0e60c63..9138dcf6ee 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -186,7 +186,6 @@ static void MegaIndicator_SetVisibilities(u32 healthboxId, bool32 invisible); static void MegaIndicator_UpdateLevel(u32 healthboxId, u32 level); static void MegaIndicator_CreateSprites(u32 battlerId, u32 healthboxSpriteId); static void MegaIndicator_UpdateOamPriorities(u32 healthboxId, u32 oamPriority); -static void MegaIndicator_DestroySprites(u32 healthboxSpriteId); static void SpriteCb_MegaIndicator(struct Sprite *); static u8 GetStatusIconForBattlerId(u8, u8); @@ -884,14 +883,6 @@ static void UpdateSpritePos(u8 spriteId, s16 x, s16 y) gSprites[spriteId].y = y; } -void DestoryHealthboxSprite(u8 healthboxSpriteId) -{ - MegaIndicator_DestroySprites(healthboxSpriteId); - DestroySprite(&gSprites[gSprites[healthboxSpriteId].oam.affineParam]); - DestroySprite(&gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId]); - DestroySprite(&gSprites[healthboxSpriteId]); -} - void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBattlerOnly) { @@ -1599,15 +1590,6 @@ static void MegaIndicator_CreateSprites(u32 battlerId, u32 healthboxSpriteId) } } -static void MegaIndicator_DestroySprites(u32 healthboxSpriteId) -{ - u32 i; - u8 *spriteIds = MegaIndicator_GetSpriteIds(healthboxSpriteId); - - for (i = 0; i < INDICATOR_COUNT; i++) - DestroySprite(&gSprites[spriteIds[i]]); -} - static void SpriteCb_MegaIndicator(struct Sprite *sprite) { u32 battlerId = sprite->tBattler; From 5c0e5d213311c8c72c119b2450ad5b45d4716f3a Mon Sep 17 00:00:00 2001 From: Jaizu Date: Mon, 10 Apr 2023 14:40:56 +0200 Subject: [PATCH 073/131] Don't toggle mega indicator visibility on the Safari Zone --- src/battle_interface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/battle_interface.c b/src/battle_interface.c index 9138dcf6ee..7f7e1d20f0 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1531,6 +1531,9 @@ void MegaIndicator_SetVisibilities(u32 healthboxId, bool32 invisible) u8 *spriteIds = MegaIndicator_GetSpriteIds(healthboxId); u32 battlerId = gSprites[healthboxId].hMain_Battler; + if (GetSafariZoneFlag()) + return; + for (i = 0; i < INDICATOR_COUNT; i++) { if (invisible == TRUE) From e49bb21ee48e7e4dc6d1f14420622ddf50488a5e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 10 Apr 2023 09:48:44 -0400 Subject: [PATCH 074/131] some IsBattlerAIControlled replacements w BattlerHasAi --- src/battle_ai_util.c | 6 +++--- src/battle_script_commands.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 51f4ef0467..3160dfa3f5 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -537,7 +537,7 @@ void ClearBattlerItemEffectHistory(u8 battlerId) void SaveBattlerData(u8 battlerId) { - if (!IsBattlerAIControlled(battlerId)) + if (!BattlerHasAi(battlerId)) { u32 i; @@ -588,7 +588,7 @@ static bool32 ShouldFailForIllusion(u16 illusionSpecies, u32 battlerId) void SetBattlerData(u8 battlerId) { - if (!IsBattlerAIControlled(battlerId)) + if (!BattlerHasAi(battlerId)) { u32 i, species, illusionSpecies; @@ -631,7 +631,7 @@ void SetBattlerData(u8 battlerId) void RestoreBattlerData(u8 battlerId) { - if (!IsBattlerAIControlled(battlerId)) + if (!BattlerHasAi(battlerId)) { u32 i; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 28bf60c39b..22c20c698b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7036,7 +7036,7 @@ static void Cmd_switchineffects(void) gHitMarker &= ~HITMARKER_FAINTED(gActiveBattler); gSpecialStatuses[gActiveBattler].faintedHasReplacement = FALSE; - if (!IsBattlerAIControlled(gActiveBattler)) + if (!BattlerHasAi(gActiveBattler)) gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[gActiveBattler]]; // Neutralizing Gas announces itself before hazards From e3ca217d6412b4eccd325006904ca88a2f3a631c Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 10 Apr 2023 11:36:17 -0400 Subject: [PATCH 075/131] rename IsBattlerAIControlled --- include/battle_ai_util.h | 2 +- src/battle_ai_main.c | 2 +- src/battle_ai_util.c | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 68c0dbd993..d1319f0ca7 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -10,7 +10,7 @@ bool32 AI_RandLessThan(u8 val); void RecordLastUsedMoveByTarget(void); bool32 BattlerHasAi(u32 battlerId); -bool32 IsBattlerAIControlled(u32 battlerId); +bool32 IsAiBattlerAware(u32 battlerId); void ClearBattlerMoveHistory(u8 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); void RecordKnownMove(u8 battlerId, u32 move); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 95e85ab894..2fb9c2640d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -367,7 +367,7 @@ void GetAiLogicData(void) for (battlerAtk = 0; battlerAtk < gBattlersCount; battlerAtk++) { if (!IsBattlerAlive(battlerAtk) - || !IsBattlerAIControlled(battlerAtk)) { + || !IsAiBattlerAware(battlerAtk)) { continue; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 22c7bb633c..05e7aec58f 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -473,7 +473,7 @@ bool32 BattlerHasAi(u32 battlerId) } } -bool32 IsBattlerAIControlled(u32 battlerId) +bool32 IsAiBattlerAware(u32 battlerId) { if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT) return TRUE; @@ -1231,7 +1231,7 @@ s32 AI_GetAbility(u32 battlerId) return gBattleStruct->overwrittenAbilities[battlerId]; // The AI knows its own ability. - if (IsBattlerAIControlled(battlerId)) + if (IsAiBattlerAware(battlerId)) return knownAbility; // Check neutralizing gas, gastro acid @@ -1264,7 +1264,7 @@ u16 AI_GetHoldEffect(u32 battlerId) { u32 holdEffect; - if (!IsBattlerAIControlled(battlerId)) + if (!IsAiBattlerAware(battlerId)) holdEffect = AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect; else holdEffect = GetBattlerHoldEffect(battlerId, FALSE); @@ -1889,7 +1889,7 @@ bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHit u16 *GetMovesArray(u32 battler) { - if (IsBattlerAIControlled(battler) || IsBattlerAIControlled(BATTLE_PARTNER(battler))) + if (IsAiBattlerAware(battler) || IsAiBattlerAware(BATTLE_PARTNER(battler))) return gBattleMons[battler].moves; else return gBattleResources->battleHistory->usedMoves[battler]; @@ -3144,7 +3144,7 @@ u16 GetAllyChosenMove(u8 battlerId) { u8 partnerBattler = BATTLE_PARTNER(battlerId); - if (!IsBattlerAlive(partnerBattler) || !IsBattlerAIControlled(partnerBattler)) + if (!IsBattlerAlive(partnerBattler) || !IsAiBattlerAware(partnerBattler)) return MOVE_NONE; else if (partnerBattler > battlerId) // Battler with the lower id chooses the move first. return gLastMoves[partnerBattler]; From 86242c1c7097a66f66efa0ff4be4c0982d47e9c2 Mon Sep 17 00:00:00 2001 From: AgustinGDLV <103095241+AgustinGDLV@users.noreply.github.com> Date: Tue, 11 Apr 2023 17:14:25 -0700 Subject: [PATCH 076/131] MOVE_REVIVAL_BLESSING Effect (#2883) * implemented Revival Blessing --- asm/macros/battle_script.inc | 5 + data/battle_scripts_1.s | 19 ++++ include/battle_script_commands.h | 1 + include/constants/battle_move_effects.h | 3 +- include/constants/battle_script_commands.h | 1 + include/constants/battle_string_ids.h | 3 +- include/constants/party_menu.h | 1 + src/battle_ai_main.c | 13 +++ src/battle_controller_opponent.c | 16 ++- src/battle_controller_player.c | 3 +- src/battle_controller_player_partner.c | 36 ++++--- src/battle_controller_recorded_opponent.c | 2 + src/battle_controller_recorded_player.c | 2 + src/battle_main.c | 4 + src/battle_message.c | 2 + src/battle_script_commands.c | 81 ++++++++++++++ src/data/battle_moves.h | 2 +- src/party_menu.c | 19 ++++ test/move_effect_revival_blessing.c | 117 +++++++++++++++++++++ 19 files changed, 309 insertions(+), 21 deletions(-) create mode 100644 test/move_effect_revival_blessing.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 3419e2e560..30df11232b 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2263,3 +2263,8 @@ .macro hitswitchtargetfailed various 0, VARIOUS_HIT_SWITCH_TARGET_FAILED .endm + + .macro tryrevivalblessing, jumpInstr:req + various 0, VARIOUS_TRY_REVIVAL_BLESSING + .4byte \jumpInstr + .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ea7ef493c5..4848b73227 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -423,6 +423,25 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHitSetEntryHazard @ EFFECT_HIT_SET_ENTRY_HAZARD .4byte BattleScript_EffectDireClaw @ EFFECT_DIRE_CLAW .4byte BattleScript_EffectBarbBarrage @ EFFECT_BARB_BARRAGE + .4byte BattleScript_EffectRevivalBlessing @ EFFECT_REVIVAL_BLESSING + +BattleScript_EffectRevivalBlessing:: + attackcanceler + attackstring + ppreduce + attackanimation + waitanimation + tryrevivalblessing BattleScript_ButItFailed + printstring STRINGID_PKMNREVIVEDREADYTOFIGHT + waitmessage B_WAIT_TIME_LONG + jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_EffectRevivalBlessingSendOut + goto BattleScript_MoveEnd + +BattleScript_EffectRevivalBlessingSendOut: + switchinanim BS_SCRIPTING, FALSE + waitstate + switchineffects BS_SCRIPTING + goto BattleScript_MoveEnd BattleScript_StealthRockActivates:: setstealthrock BattleScript_MoveEnd diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index d657286289..dcf601e804 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -46,6 +46,7 @@ u8 GetCatchingBattler(void); u32 GetHighestStatId(u32 battlerId); bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType); bool32 DoSwitchInAbilitiesItems(u32 battlerId); +u8 GetFirstFaintedPartyIndex(u8 battlerId); extern void (* const gBattleScriptingCommandsTable[])(void); extern const u8 gBattlePalaceNatureToMoveGroupLikelihood[NUM_NATURES][4]; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 27ad6601ff..d1562dec93 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -404,7 +404,8 @@ #define EFFECT_HIT_SET_ENTRY_HAZARD 398 #define EFFECT_DIRE_CLAW 399 #define EFFECT_BARB_BARRAGE 400 +#define EFFECT_REVIVAL_BLESSING 401 -#define NUM_BATTLE_MOVE_EFFECTS 401 +#define NUM_BATTLE_MOVE_EFFECTS 402 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 26064bcfb1..be2410f946 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -259,6 +259,7 @@ #define VARIOUS_STORE_HEALING_WISH 167 #define VARIOUS_HIT_SWITCH_TARGET_FAILED 168 #define VARIOUS_JUMP_IF_SHELL_TRAP 169 +#define VARIOUS_TRY_REVIVAL_BLESSING 170 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index b941763340..1124c3a607 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -647,8 +647,9 @@ #define STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM 645 #define STRINGID_COULDNTFULLYPROTECT 646 #define STRINGID_STOCKPILEDEFFECTWOREOFF 647 +#define STRINGID_PKMNREVIVEDREADYTOFIGHT 648 -#define BATTLESTRINGS_COUNT 648 +#define BATTLESTRINGS_COUNT 649 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/constants/party_menu.h b/include/constants/party_menu.h index 2c632d30cf..f28b75122f 100644 --- a/include/constants/party_menu.h +++ b/include/constants/party_menu.h @@ -48,6 +48,7 @@ #define PARTY_ACTION_MOVE_TUTOR 12 #define PARTY_ACTION_MINIGAME 13 #define PARTY_ACTION_REUSABLE_ITEM 14 // Unused. The only reusable items are handled separately +#define PARTY_ACTION_CHOOSE_FAINTED_MON 15 // IDs for DisplayPartyMenuStdMessage, to display the message at the bottom of the party menu #define PARTY_MSG_CHOOSE_MON 0 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2fb9c2640d..6c60705d5a 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2623,6 +2623,15 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (gBattleMons[battlerAtk].hp <= gBattleMons[battlerAtk].maxHP / 3) score -= 10; break;*/ + case EFFECT_REVIVAL_BLESSING: + if (GetFirstFaintedPartyIndex(battlerAtk) == PARTY_SIZE) + score -= 10; + else if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) + score -= 10; + else if (CanTargetFaintAi(battlerDef, battlerAtk) + && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER) + score -= 10; + break; case EFFECT_PLACEHOLDER: return 0; // cannot even select } // move effect checks @@ -4808,6 +4817,10 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score++; } break; + case EFFECT_REVIVAL_BLESSING: + if (GetFirstFaintedPartyIndex(battlerAtk) != PARTY_SIZE) + score += 2; + break; //case EFFECT_EXTREME_EVOBOOST: // TODO //break; //case EFFECT_CLANGOROUS_SOUL: // TODO diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 79283b0674..7a5149313d 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -20,6 +20,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "random.h" @@ -33,6 +34,7 @@ #include "constants/battle_anim.h" #include "constants/items.h" #include "constants/moves.h" +#include "constants/party_menu.h" #include "constants/songs.h" #include "constants/trainers.h" #include "trainer_hill.h" @@ -1674,7 +1676,13 @@ static void OpponentHandleChoosePokemon(void) s32 chosenMonId; s32 pokemonInBattle = 1; - if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE) + // Choosing Revival Blessing target + if ((gBattleResources->bufferA[gActiveBattler][1] & 0xF) == PARTY_ACTION_CHOOSE_FAINTED_MON) + { + chosenMonId = gSelectedMonPartyId = GetFirstFaintedPartyIndex(gActiveBattler); + } + // Switching out + else if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE) { chosenMonId = GetMostSuitableMonToSwitchInto(); @@ -1709,17 +1717,17 @@ static void OpponentHandleChoosePokemon(void) } } } + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; } else { chosenMonId = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler); *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE; + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; } - - - *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; BtlController_EmitChosenMonReturnValue(BUFFER_B, chosenMonId, NULL); OpponentBufferExecCompleted(); + } static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 82a9d7b7a9..1065994164 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2907,7 +2907,8 @@ static void PlayerHandleChoosePokemon(void) for (i = 0; i < ARRAY_COUNT(gBattlePartyCurrentOrder); i++) gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[gActiveBattler][4 + i]; - if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[gActiveBattler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH) + if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[gActiveBattler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH + && (gBattleResources->bufferA[gActiveBattler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON) { BtlController_EmitChosenMonReturnValue(BUFFER_B, gBattlerPartyIndexes[gActiveBattler] + 1, gBattlePartyCurrentOrder); PlayerBufferExecCompleted(); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 88bc4f974d..4c54b68aa3 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -16,6 +16,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "reshow_battle_screen.h" @@ -27,6 +28,7 @@ #include "window.h" #include "constants/battle_anim.h" #include "constants/songs.h" +#include "constants/party_menu.h" #include "constants/trainers.h" static void PlayerPartnerHandleGetMonData(void); @@ -1549,25 +1551,33 @@ static void PlayerPartnerHandleChooseItem(void) static void PlayerPartnerHandleChoosePokemon(void) { - s32 chosenMonId = GetMostSuitableMonToSwitchInto(); - - if (chosenMonId == PARTY_SIZE) // just switch to the next mon + s32 chosenMonId; + // Choosing Revival Blessing target + if ((gBattleResources->bufferA[gActiveBattler][1] & 0xF) == PARTY_ACTION_CHOOSE_FAINTED_MON) { - u8 playerMonIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - u8 selfIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); - - for (chosenMonId = PARTY_SIZE / 2; chosenMonId < PARTY_SIZE; chosenMonId++) + chosenMonId = gSelectedMonPartyId = GetFirstFaintedPartyIndex(gActiveBattler); + } + // Switching out + else + { + chosenMonId = GetMostSuitableMonToSwitchInto(); + if (chosenMonId == PARTY_SIZE) // just switch to the next mon { - if (GetMonData(&gPlayerParty[chosenMonId], MON_DATA_HP) != 0 - && chosenMonId != gBattlerPartyIndexes[playerMonIdentity] - && chosenMonId != gBattlerPartyIndexes[selfIdentity]) + u8 playerMonIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + u8 selfIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + + for (chosenMonId = PARTY_SIZE / 2; chosenMonId < PARTY_SIZE; chosenMonId++) { - break; + if (GetMonData(&gPlayerParty[chosenMonId], MON_DATA_HP) != 0 + && chosenMonId != gBattlerPartyIndexes[playerMonIdentity] + && chosenMonId != gBattlerPartyIndexes[selfIdentity]) + { + break; + } } } + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; } - - *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; BtlController_EmitChosenMonReturnValue(BUFFER_B, chosenMonId, NULL); PlayerPartnerBufferExecCompleted(); } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index 2e93d625d7..1fe8addcc3 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -15,6 +15,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "recorded_battle.h" @@ -1442,6 +1443,7 @@ static void RecordedOpponentHandleChooseItem(void) static void RecordedOpponentHandleChoosePokemon(void) { *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, gActiveBattler); + gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[gActiveBattler]; // Revival Blessing BtlController_EmitChosenMonReturnValue(BUFFER_B, *(gBattleStruct->monToSwitchIntoId + gActiveBattler), NULL); RecordedOpponentBufferExecCompleted(); } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 1906df8a8a..869a5e18e4 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -12,6 +12,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "recorded_battle.h" @@ -1466,6 +1467,7 @@ static void RecordedPlayerHandleChooseItem(void) static void RecordedPlayerHandleChoosePokemon(void) { *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, gActiveBattler); + gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[gActiveBattler]; // Revival Blessing BtlController_EmitChosenMonReturnValue(BUFFER_B, *(gBattleStruct->monToSwitchIntoId + gActiveBattler), NULL); RecordedPlayerBufferExecCompleted(); } diff --git a/src/battle_main.c b/src/battle_main.c index b80042ee9c..7b6af8a23a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3196,6 +3196,7 @@ static void BattleStartClearSetData(void) } gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky + gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing } void SwitchInClearSetData(void) @@ -3308,6 +3309,9 @@ void SwitchInClearSetData(void) gBattleStruct->overwrittenAbilities[gActiveBattler] = ABILITY_NONE; + // Clear selected party ID so Revival Blessing doesn't get confused. + gSelectedMonPartyId = PARTY_SIZE; + Ai_UpdateSwitchInData(gActiveBattler); } diff --git a/src/battle_message.c b/src/battle_message.c index 2ecfac0c7d..cb1f640506 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -782,9 +782,11 @@ static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set a she static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell trap didn't work!"); static const u8 sText_CouldntFullyProtect[] = _("{B_DEF_NAME_WITH_PREFIX} couldn't fully protect\nitself and got hurt!"); static const u8 sText_StockpiledEffectWoreOff[] = _("{B_ATK_NAME_WITH_PREFIX}'s stockpiled\neffect wore off!"); +static const u8 sText_PkmnRevivedReadyToFight[] = _("{B_BUFF1} was revived and\nis ready to fight again!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_PKMNREVIVEDREADYTOFIGHT - BATTLESTRINGS_TABLE_START] = sText_PkmnRevivedReadyToFight, [STRINGID_STOCKPILEDEFFECTWOREOFF - BATTLESTRINGS_TABLE_START] = sText_StockpiledEffectWoreOff, [STRINGID_COULDNTFULLYPROTECT - BATTLESTRINGS_TABLE_START] = sText_CouldntFullyProtect, [STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN - BATTLESTRINGS_TABLE_START] = sText_AttackerGainedStrengthFromTheFallen, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index bba3bdd29e..a0d8181d67 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11225,6 +11225,50 @@ static void Cmd_various(void) gBattlescriptCurrInstr = cmd->nextInstr; return; } + case VARIOUS_TRY_REVIVAL_BLESSING: + { + VARIOUS_ARGS(const u8 *failInstr); + u32 side = GetBattlerSide(gBattlerAttacker); + u8 index = GetFirstFaintedPartyIndex(gBattlerAttacker); + + // Move fails if there are no battlers to revive. + if (index == PARTY_SIZE) + { + gBattlescriptCurrInstr = cmd->failInstr; + return; + } + + // Battler selected! Revive and go to next instruction. + if (gSelectedMonPartyId != PARTY_SIZE) + { + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + + u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HP_BATTLE, gBitTable[gSelectedMonPartyId], sizeof(hp), &hp); + MarkBattlerForControllerExec(gBattlerAttacker); + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES)); + + // If an on-field battler is revived, it needs to be sent out again. + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && + gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId) + { + gBattleScripting.battler = BATTLE_PARTNER(gBattlerAttacker); + gBattleCommunication[MULTIUSE_STATE] = TRUE; + } + + gSelectedMonPartyId = PARTY_SIZE; + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + + // Open party menu, wait to go to next instruction. + else + { + BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gActiveBattler]); + MarkBattlerForControllerExec(gBattlerAttacker); + } + return; + } } // End of switch (cmd->id) gBattlescriptCurrInstr = cmd->nextInstr; @@ -16346,3 +16390,40 @@ static void TryUpdateRoundTurnOrder(void) } } +u8 GetFirstFaintedPartyIndex(u8 battlerId) +{ + u32 i; + u32 start = 0; + u32 end = PARTY_SIZE; + struct Pokemon *party = (GetBattlerSide(battlerId) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + + // Check whether partner is separate trainer. + if ((GetBattlerSide(battlerId) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + || (GetBattlerSide(battlerId) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + { + if (GetBattlerPosition(battlerId) == B_POSITION_OPPONENT_LEFT + || GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT) + { + end = PARTY_SIZE / 2; + } + else + { + start = PARTY_SIZE / 2; + } + } + + // Loop through to find fainted battler. + for (i = start; i < end; ++i) + { + u32 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species != SPECIES_NONE + && species != SPECIES_EGG + && GetMonData(&party[i], MON_DATA_HP) == 0) + { + return i; + } + } + + // Returns PARTY_SIZE if none found. + return PARTY_SIZE; +} diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 3dc21a5382..4a89222a96 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -13048,7 +13048,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_REVIVAL_BLESSING] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_REVIVAL_BLESSING + .effect = EFFECT_REVIVAL_BLESSING, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, diff --git a/src/party_menu.c b/src/party_menu.c index 9185657a78..30f2f81501 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -1354,6 +1354,24 @@ static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr) TryEnterMonForMinigame(taskId, (u8)*slotPtr); } break; + case PARTY_ACTION_CHOOSE_FAINTED_MON: + { + u8 partyId = GetPartyIdFromBattleSlot((u8)*slotPtr); + if (GetMonData(&gPlayerParty[*slotPtr], MON_DATA_HP) > 0 + || GetMonData(&gPlayerParty[*slotPtr], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG + || ((gBattleTypeFlags & BATTLE_TYPE_MULTI) && partyId >= (PARTY_SIZE / 2))) + { + // Can't select if egg, alive, or doesn't belong to you + PlaySE(SE_FAILURE); + } + else + { + PlaySE(SE_SELECT); + gSelectedMonPartyId = partyId; + Task_ClosePartyMenu(taskId); + } + break; + } default: case PARTY_ACTION_ABILITY_PREVENTS: case PARTY_ACTION_SWITCHING: @@ -1379,6 +1397,7 @@ static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr) switch (gPartyMenu.action) { case PARTY_ACTION_SEND_OUT: + case PARTY_ACTION_CHOOSE_FAINTED_MON: PlaySE(SE_FAILURE); break; case PARTY_ACTION_SWITCH: diff --git a/test/move_effect_revival_blessing.c b/test/move_effect_revival_blessing.c new file mode 100644 index 0000000000..6bc76ec85e --- /dev/null +++ b/test/move_effect_revival_blessing.c @@ -0,0 +1,117 @@ +#include "global.h" +#include "test_battle.h" + +// Note: Since these tests are recorded battle, they don't test the right battle controller +// behaviors. These have been tested in-game, in double, in multi, and in link battles. AI will always +// revive their first fainted party member in order. + +#define MOVE_MESSAGE(name) \ + do { \ + if (B_EXPANDED_MOVE_NAMES == FALSE) \ + MESSAGE(name" used RevivlBlesng!"); \ + else \ + MESSAGE(name" used Revival Blessing!"); \ + } while (0); \ + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_REVIVAL_BLESSING].effect == EFFECT_REVIVAL_BLESSING); +} + +SINGLE_BATTLE_TEST("Revival Blessing revives a chosen fainted party member for the player") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_REVIVAL_BLESSING); SEND_OUT(player, 2); } + } SCENE { + MOVE_MESSAGE("Wobbuffet") + MESSAGE("Wynaut was revived and is ready to fight again!"); + } +} + +SINGLE_BATTLE_TEST("Revival Blessing revives a fainted party member for an opponent") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_RAICHU); + OPPONENT(SPECIES_PICHU) { HP(0); } + OPPONENT(SPECIES_PIKACHU) { HP(0); } + } WHEN { + TURN { MOVE(opponent, MOVE_REVIVAL_BLESSING); SEND_OUT(opponent, 1); } + } SCENE { + MOVE_MESSAGE("Foe Raichu") + MESSAGE("Pichu was revived and is ready to fight again!"); + } +} + +SINGLE_BATTLE_TEST("Revival Blessing fails if no party members are fainted") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_REVIVAL_BLESSING); } + } SCENE { + MOVE_MESSAGE("Wobbuffet") + MESSAGE("But it failed!"); + } +} + +// Note: There isn't a good way to test multi battles at the moment, but +// this PASSES in game! +TO_DO_BATTLE_TEST("Revival Blessing cannot revive a partner's party member"); +// DOUBLE_BATTLE_TEST("Revival Blessing cannot revive a partner's party member") +// { +// struct BattlePokemon *user; +// gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS; +// PARAMETRIZE { user = opponentLeft; } +// PARAMETRIZE { user = opponentRight; } +// GIVEN { +// ASSUME((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) != FALSE); +// PLAYER(SPECIES_WOBBUFFET); +// PLAYER(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WYNAUT); +// OPPONENT(SPECIES_WYNAUT) { HP(0); } +// OPPONENT(SPECIES_WYNAUT); +// } WHEN { +// TURN { MOVE(user, MOVE_REVIVAL_BLESSING); } +// } SCENE { +// if (user == opponentLeft) { +// MOVE_MESSAGE(Foe Wobbuffet) +// MESSAGE("But it failed!"); +// } else { +// MOVE_MESSAGE(Foe Wynaut) +// MESSAGE("Wynaut was revived and is ready to fight again!"); +// } +// } +// } + +// Note: The test runner gets upset about "sending out" a battler on the field, +// but this PASSES in game! +TO_DO_BATTLE_TEST("Revived battlers still lose their turn"); +// DOUBLE_BATTLE_TEST("Revived battlers still lose their turn") +// { +// GIVEN { +// PLAYER(SPECIES_WOBBUFFET); +// PLAYER(SPECIES_WYNAUT); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WYNAUT) { HP(1); } +// } WHEN { +// TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentRight); +// MOVE(opponentLeft, MOVE_REVIVAL_BLESSING); +// SEND_OUT(opponentLeft, 1); } +// } SCENE { +// MESSAGE("Wobbuffet used Tackle!"); +// MESSAGE("Foe Wynaut fainted!"); +// MOVE_MESSAGE("Foe Wobbuffet") +// MESSAGE("Wynaut was revived and is ready to fight again!"); +// NOT { MESSAGE("Wynaut used Celebrate!"); } +// } +// } From eaddeabe1688bca79a85174a2dd668f88839b5bd Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 13 Apr 2023 13:17:25 -0400 Subject: [PATCH 077/131] Improve PR Template --- .github/pull_request_template.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c381b50f1b..930d20a018 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,6 +3,14 @@ ## Description +## Images + + + +## Issue(s) that this PR fixes + + + ## **Discord contact info** - - \ No newline at end of file + + \ No newline at end of file From 958bc34cdf527f6c4130c0d13ed4a2f3b541f726 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 14 Apr 2023 09:42:48 -0400 Subject: [PATCH 078/131] Fixed AI not considering Hidden Abilities in its team during switching logic --- src/battle_ai_switch_items.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index d1272d67d7..113e14cb8a 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -198,9 +198,8 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void) if (GetMonData(&party[i], MON_DATA_HP) == 0) continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_NONE || species == SPECIES_EGG) continue; if (i == gBattlerPartyIndexes[battlerIn1]) continue; @@ -213,12 +212,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void) if (IsAceMon(gActiveBattler, i)) continue; - - species = GetMonData(&party[i], MON_DATA_SPECIES); - if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0) - monAbility = gSpeciesInfo[species].abilities[1]; - else - monAbility = gSpeciesInfo[species].abilities[0]; + monAbility = GetMonAbility(&party[i]); if (absorbingTypeAbility == monAbility && Random() & 1) { @@ -570,9 +564,8 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent) if (GetMonData(&party[i], MON_DATA_HP) == 0) continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_NONE || species == SPECIES_EGG) continue; if (i == gBattlerPartyIndexes[battlerIn1]) continue; @@ -585,12 +578,7 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent) if (IsAceMon(gActiveBattler, i)) continue; - - species = GetMonData(&party[i], MON_DATA_SPECIES); - if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0) - monAbility = gSpeciesInfo[species].abilities[1]; - else - monAbility = gSpeciesInfo[species].abilities[0]; + monAbility = GetMonAbility(&party[i]); CalcPartyMonTypeEffectivenessMultiplier(gLastLandedMoves[gActiveBattler], species, monAbility); if (gMoveResultFlags & flags) @@ -964,7 +952,9 @@ u8 GetMostSuitableMonToSwitchInto(void) // Get invalid slots ids. for (i = firstId; i < lastId; i++) { - if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE + u16 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_NONE + || species == SPECIES_EGG || GetMonData(&party[i], MON_DATA_HP) == 0 || gBattlerPartyIndexes[battlerIn1] == i || gBattlerPartyIndexes[battlerIn2] == i From 2eabcea86e2d4816a30ce7deb52d32ead3339448 Mon Sep 17 00:00:00 2001 From: AgustinGDLV <103095241+AgustinGDLV@users.noreply.github.com> Date: Fri, 14 Apr 2023 11:25:50 -0700 Subject: [PATCH 079/131] Battle Item Refactor (#2902) * items that can be used in battle now use battlescripts * removed ExecuteTableBasedItemEffect_ * taught AI how to use items, removed AI_itemtype/flag * X-Items store stages raised in holdEffectParam * USE_ITEM in tests --- asm/macros/battle_script.inc | 16 + data/battle_scripts_2.s | 381 ++++++++++++---------- include/battle.h | 3 +- include/battle_ai_switch_items.h | 30 -- include/constants/battle_string_ids.h | 5 +- include/constants/item_effects.h | 12 +- include/constants/items.h | 29 +- include/item.h | 4 +- include/item_use.h | 9 +- include/party_menu.h | 3 + include/recorded_battle.h | 1 + src/battle_ai_switch_items.c | 102 ++---- src/battle_controller_opponent.c | 2 +- src/battle_controller_recorded_opponent.c | 5 + src/battle_controller_recorded_player.c | 5 + src/battle_main.c | 4 +- src/battle_message.c | 23 +- src/battle_pyramid_bag.c | 17 +- src/battle_script_commands.c | 144 +++++++- src/battle_util.c | 88 +---- src/data/items.h | 337 ++++++++----------- src/data/pokemon/item_effects.h | 2 - src/item.c | 70 +++- src/item_menu.c | 17 +- src/item_use.c | 168 ++++++---- src/party_menu.c | 222 +++++++++---- src/pokemon.c | 220 +------------ test/item_effect_increase_stat.c | 25 ++ test/item_effect_restore_hp.c | 37 +++ test/item_effect_restore_pp.c | 19 ++ test/test_battle.h | 21 +- test/test_runner_battle.c | 38 +++ 32 files changed, 1102 insertions(+), 957 deletions(-) create mode 100644 test/item_effect_increase_stat.c create mode 100644 test/item_effect_restore_hp.c create mode 100644 test/item_effect_restore_pp.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 30df11232b..6e351e62fb 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1330,6 +1330,22 @@ .4byte \jumpInstr .endm + .macro itemrestorehp + callnative BS_ItemRestoreHP + .endm + + .macro itemcurestatus + callnative BS_ItemCureStatus + .endm + + .macro itemincreasestat + callnative BS_ItemIncreaseStat + .endm + + .macro itemrestorepp + callnative BS_ItemRestorePP + .endm + @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index f4c8bd5a77..dee482d1d3 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -3,219 +3,256 @@ #include "constants/battle_script_commands.h" #include "constants/battle_anim.h" #include "constants/battle_string_ids.h" -#include "constants/items.h" +#include "constants/moves.h" #include "constants/songs.h" #include "constants/game_stat.h" - .include "asm/macros.inc" - .include "asm/macros/battle_script.inc" - .include "constants/constants.inc" + .include "asm/macros.inc" + .include "asm/macros/battle_script.inc" + .include "constants/constants.inc" - .section script_data, "aw", %progbits + .section script_data, "aw", %progbits - .align 2 + .align 2 gBattlescriptsForUsingItem:: - .4byte BattleScript_PlayerUsesItem - .4byte BattleScript_OpponentUsesHealItem @ AI_ITEM_FULL_RESTORE - .4byte BattleScript_OpponentUsesHealItem @ AI_ITEM_HEAL_HP - .4byte BattleScript_OpponentUsesStatusCureItem @ AI_ITEM_CURE_CONDITION - .4byte BattleScript_OpponentUsesXItem @ AI_ITEM_X_STAT - .4byte BattleScript_OpponentUsesGuardSpec @ AI_ITEM_GUARD_SPEC + .4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_RESTORE_HP + .4byte BattleScript_ItemCureStatus @ EFFECT_ITEM_CURE_STATUS + .4byte BattleScript_ItemHealAndCureStatus @ EFFECT_ITEM_HEAL_AND_CURE_STATUS + .4byte BattleScript_ItemIncreaseStat @ EFFECT_ITEM_INCREASE_STAT + .4byte BattleScript_ItemSetMist @ EFFECT_ITEM_SET_MIST + .4byte BattleScript_ItemSetFocusEnergy @ EFFECT_ITEM_SET_FOCUS_ENERGY + .4byte BattleScript_RunByUsingItem @ EFFECT_ITEM_ESCAPE + .4byte BattleScript_BallThrow @ EFFECT_ITEM_THROW_BALL + .4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_REVIVE + .4byte BattleScript_ItemRestorePP @ EFFECT_ITEM_RESTORE_PP + .4byte BattleScript_ItemIncreaseAllStats @ EFFECT_ITEM_INCREASE_ALL_STATS - .align 2 -gBattlescriptsForRunningByItem:: - .4byte BattleScript_RunByUsingItem - - .align 2 + .align 2 gBattlescriptsForSafariActions:: - .4byte BattleScript_ActionWatchesCarefully - .4byte BattleScript_ActionGetNear - .4byte BattleScript_ActionThrowPokeblock - .4byte BattleScript_ActionWallyThrow + .4byte BattleScript_ActionWatchesCarefully + .4byte BattleScript_ActionGetNear + .4byte BattleScript_ActionThrowPokeblock + .4byte BattleScript_ActionWallyThrow + +BattleScript_ItemEnd: + end + +BattleScript_UseItemMessage: + printstring STRINGID_EMPTYSTRING3 + pause B_WAIT_TIME_MED + playse SE_USE_ITEM + getbattlerside BS_ATTACKER + copybyte cMULTISTRING_CHOOSER, gBattleCommunication + printfromtable gTrainerUsedItemStringIds + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_ItemRestoreHP:: + call BattleScript_UseItemMessage + itemrestorehp + printstring STRINGID_ITEMRESTOREDSPECIESHEALTH + waitmessage B_WAIT_TIME_LONG + jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_ItemRestoreHP_SendOutRevivedBattler + bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER + updatestatusicon BS_ATTACKER + end + +BattleScript_ItemRestoreHP_SendOutRevivedBattler: + switchinanim BS_ATTACKER, FALSE + waitstate + switchineffects BS_ATTACKER + end + +BattleScript_ItemCureStatus:: + call BattleScript_UseItemMessage + itemcurestatus + printstring STRINGID_ITEMCUREDSPECIESSTATUS + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_ATTACKER + end + +BattleScript_ItemHealAndCureStatus:: + call BattleScript_UseItemMessage + itemrestorehp + curestatus BS_ATTACKER + printstring STRINGID_ITEMRESTOREDSPECIESHEALTH + waitmessage B_WAIT_TIME_LONG + bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER + updatestatusicon BS_ATTACKER + end + +BattleScript_ItemIncreaseStat:: + call BattleScript_UseItemMessage + itemincreasestat + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_ItemEnd + setgraphicalstatchangevalues + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG + end + +BattleScript_ItemSetMist:: + call BattleScript_UseItemMessage + setmist + playmoveanimation BS_ATTACKER, MOVE_MIST + waitanimation + printfromtable gMistUsedStringIds + waitmessage B_WAIT_TIME_LONG + end + +BattleScript_ItemSetFocusEnergy:: + call BattleScript_UseItemMessage + jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY, BattleScript_ButItFailed + setfocusenergy + playmoveanimation BS_ATTACKER, MOVE_FOCUS_ENERGY + waitanimation + printstring STRINGID_PKMNUSEDXTOGETPUMPED + waitmessage B_WAIT_TIME_LONG + end + +BattleScript_ItemRestorePP:: + call BattleScript_UseItemMessage + itemrestorepp + printstring STRINGID_ITEMRESTOREDSPECIESPP + waitmessage B_WAIT_TIME_LONG + end + +BattleScript_ItemIncreaseAllStats:: + call BattleScript_UseItemMessage + call BattleScript_AllStatsUp + end BattleScript_BallThrow:: - jumpifword CMP_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_WALLY_TUTORIAL, BattleScript_BallThrowByWally - printstring STRINGID_PLAYERUSEDITEM - handleballthrow + jumpifword CMP_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_WALLY_TUTORIAL, BattleScript_BallThrowByWally + printstring STRINGID_PLAYERUSEDITEM + handleballthrow BattleScript_BallThrowByWally:: - printstring STRINGID_WALLYUSEDITEM - handleballthrow + printstring STRINGID_WALLYUSEDITEM + handleballthrow BattleScript_SafariBallThrow:: - printstring STRINGID_PLAYERUSEDITEM - updatestatusicon BS_ATTACKER - handleballthrow + printstring STRINGID_PLAYERUSEDITEM + updatestatusicon BS_ATTACKER + handleballthrow BattleScript_SuccessBallThrow:: - setbyte sMON_CAUGHT, TRUE - incrementgamestat GAME_STAT_POKEMON_CAPTURES + setbyte sMON_CAUGHT, TRUE + incrementgamestat GAME_STAT_POKEMON_CAPTURES BattleScript_PrintCaughtMonInfo:: - printstring STRINGID_GOTCHAPKMNCAUGHTPLAYER - jumpifbyte CMP_NOT_EQUAL, sEXP_CATCH, TRUE, BattleScript_TryPrintCaughtMonInfo - setbyte sGIVEEXP_STATE, 0 - getexp BS_TARGET - sethword gBattle_BG2_X, 0 + printstring STRINGID_GOTCHAPKMNCAUGHTPLAYER + jumpifbyte CMP_NOT_EQUAL, sEXP_CATCH, TRUE, BattleScript_TryPrintCaughtMonInfo + setbyte sGIVEEXP_STATE, 0 + getexp BS_TARGET + sethword gBattle_BG2_X, 0 BattleScript_TryPrintCaughtMonInfo: - trysetcaughtmondexflags BattleScript_TryNicknameCaughtMon - printstring STRINGID_PKMNDATAADDEDTODEX - waitstate - setbyte gBattleCommunication, 0 - displaydexinfo + trysetcaughtmondexflags BattleScript_TryNicknameCaughtMon + printstring STRINGID_PKMNDATAADDEDTODEX + waitstate + setbyte gBattleCommunication, 0 + displaydexinfo BattleScript_TryNicknameCaughtMon:: - printstring STRINGID_GIVENICKNAMECAPTURED - waitstate - setbyte gBattleCommunication, 0 - trygivecaughtmonnick BattleScript_GiveCaughtMonEnd - givecaughtmon - printfromtable gCaughtMonStringIds - waitmessage B_WAIT_TIME_LONG - goto BattleScript_SuccessBallThrowEnd + printstring STRINGID_GIVENICKNAMECAPTURED + waitstate + setbyte gBattleCommunication, 0 + trygivecaughtmonnick BattleScript_GiveCaughtMonEnd + givecaughtmon + printfromtable gCaughtMonStringIds + waitmessage B_WAIT_TIME_LONG + goto BattleScript_SuccessBallThrowEnd BattleScript_GiveCaughtMonEnd:: - givecaughtmon + givecaughtmon BattleScript_SuccessBallThrowEnd:: - setbyte gBattleOutcome, B_OUTCOME_CAUGHT - finishturn + setbyte gBattleOutcome, B_OUTCOME_CAUGHT + finishturn BattleScript_WallyBallThrow:: - printstring STRINGID_GOTCHAPKMNCAUGHTWALLY - setbyte gBattleOutcome, B_OUTCOME_CAUGHT - finishturn + printstring STRINGID_GOTCHAPKMNCAUGHTWALLY + setbyte gBattleOutcome, B_OUTCOME_CAUGHT + finishturn BattleScript_ShakeBallThrow:: - printfromtable gBallEscapeStringIds - waitmessage B_WAIT_TIME_LONG - jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_SAFARI, BattleScript_ShakeBallThrowEnd - jumpifbyte CMP_NOT_EQUAL, gNumSafariBalls, 0, BattleScript_ShakeBallThrowEnd - printstring STRINGID_OUTOFSAFARIBALLS - waitmessage B_WAIT_TIME_LONG - setbyte gBattleOutcome, B_OUTCOME_NO_SAFARI_BALLS + printfromtable gBallEscapeStringIds + waitmessage B_WAIT_TIME_LONG + jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_SAFARI, BattleScript_ShakeBallThrowEnd + jumpifbyte CMP_NOT_EQUAL, gNumSafariBalls, 0, BattleScript_ShakeBallThrowEnd + printstring STRINGID_OUTOFSAFARIBALLS + waitmessage B_WAIT_TIME_LONG + setbyte gBattleOutcome, B_OUTCOME_NO_SAFARI_BALLS BattleScript_ShakeBallThrowEnd:: - finishaction + finishaction BattleScript_TrainerBallBlock:: - waitmessage B_WAIT_TIME_LONG - printstring STRINGID_TRAINERBLOCKEDBALL - waitmessage B_WAIT_TIME_LONG - printstring STRINGID_DONTBEATHIEF - waitmessage B_WAIT_TIME_LONG - finishaction - -BattleScript_PlayerUsesItem:: - moveendcase MOVEEND_MIRROR_MOVE - end - -BattleScript_OpponentUsesHealItem:: - printstring STRINGID_EMPTYSTRING3 - pause B_WAIT_TIME_MED - playse SE_USE_ITEM - printstring STRINGID_TRAINER1USEDITEM - waitmessage B_WAIT_TIME_LONG - bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT - useitemonopponent - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - printstring STRINGID_PKMNSITEMRESTOREDHEALTH - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER - moveendcase MOVEEND_MIRROR_MOVE - finishaction - -BattleScript_OpponentUsesStatusCureItem:: - printstring STRINGID_EMPTYSTRING3 - pause B_WAIT_TIME_MED - playse SE_USE_ITEM - printstring STRINGID_TRAINER1USEDITEM - waitmessage B_WAIT_TIME_LONG - useitemonopponent - printfromtable gTrainerItemCuredStatusStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER - moveendcase MOVEEND_MIRROR_MOVE - finishaction - -BattleScript_OpponentUsesXItem:: - printstring STRINGID_EMPTYSTRING3 - pause B_WAIT_TIME_MED - playse SE_USE_ITEM - printstring STRINGID_TRAINER1USEDITEM - waitmessage B_WAIT_TIME_LONG - useitemonopponent - printfromtable gStatUpStringIds - waitmessage B_WAIT_TIME_LONG - moveendcase MOVEEND_MIRROR_MOVE - finishaction - -BattleScript_OpponentUsesGuardSpec:: - printstring STRINGID_EMPTYSTRING3 - pause B_WAIT_TIME_MED - playse SE_USE_ITEM - printstring STRINGID_TRAINER1USEDITEM - waitmessage B_WAIT_TIME_LONG - useitemonopponent - printfromtable gMistUsedStringIds - waitmessage B_WAIT_TIME_LONG - moveendcase MOVEEND_MIRROR_MOVE - finishaction + waitmessage B_WAIT_TIME_LONG + printstring STRINGID_TRAINERBLOCKEDBALL + waitmessage B_WAIT_TIME_LONG + printstring STRINGID_DONTBEATHIEF + waitmessage B_WAIT_TIME_LONG + finishaction BattleScript_RunByUsingItem:: - playse SE_FLEE - setbyte gBattleOutcome, B_OUTCOME_RAN - finishturn + playse SE_FLEE + setbyte gBattleOutcome, B_OUTCOME_RAN + finishturn BattleScript_ActionWatchesCarefully: - printstring STRINGID_PKMNWATCHINGCAREFULLY - waitmessage B_WAIT_TIME_LONG - end2 + printstring STRINGID_PKMNWATCHINGCAREFULLY + waitmessage B_WAIT_TIME_LONG + end2 BattleScript_ActionGetNear: - printfromtable gSafariGetNearStringIds - waitmessage B_WAIT_TIME_LONG - end2 + printfromtable gSafariGetNearStringIds + waitmessage B_WAIT_TIME_LONG + end2 BattleScript_ActionThrowPokeblock: - printstring STRINGID_THREWPOKEBLOCKATPKMN - waitmessage B_WAIT_TIME_LONG - playanimation BS_ATTACKER, B_ANIM_POKEBLOCK_THROW, NULL - printfromtable gSafariPokeblockResultStringIds - waitmessage B_WAIT_TIME_LONG - end2 + printstring STRINGID_THREWPOKEBLOCKATPKMN + waitmessage B_WAIT_TIME_LONG + playanimation BS_ATTACKER, B_ANIM_POKEBLOCK_THROW, NULL + printfromtable gSafariPokeblockResultStringIds + waitmessage B_WAIT_TIME_LONG + end2 BattleScript_ActionWallyThrow: - printstring STRINGID_RETURNMON - waitmessage B_WAIT_TIME_LONG - returnatktoball - waitstate - trainerslidein BS_TARGET - waitstate - printstring STRINGID_YOUTHROWABALLNOWRIGHT - waitmessage B_WAIT_TIME_LONG - end2 + printstring STRINGID_RETURNMON + waitmessage B_WAIT_TIME_LONG + returnatktoball + waitstate + trainerslidein BS_TARGET + waitstate + printstring STRINGID_YOUTHROWABALLNOWRIGHT + waitmessage B_WAIT_TIME_LONG + end2 BattleScript_TrainerASlideMsgRet:: - handletrainerslidemsg BS_SCRIPTING, 0 - trainerslidein B_POSITION_OPPONENT_LEFT - handletrainerslidemsg BS_SCRIPTING, 1 - waitstate - trainerslideout B_POSITION_OPPONENT_LEFT - waitstate - handletrainerslidemsg BS_SCRIPTING, 2 - return + handletrainerslidemsg BS_SCRIPTING, 0 + trainerslidein B_POSITION_OPPONENT_LEFT + handletrainerslidemsg BS_SCRIPTING, 1 + waitstate + trainerslideout B_POSITION_OPPONENT_LEFT + waitstate + handletrainerslidemsg BS_SCRIPTING, 2 + return BattleScript_TrainerASlideMsgEnd2:: - call BattleScript_TrainerASlideMsgRet - end2 - + call BattleScript_TrainerASlideMsgRet + end2 + BattleScript_TrainerBSlideMsgRet:: - handletrainerslidemsg BS_SCRIPTING, 0 - trainerslidein B_POSITION_OPPONENT_RIGHT - handletrainerslidemsg BS_SCRIPTING, 1 - waitstate - trainerslideout B_POSITION_OPPONENT_RIGHT - waitstate - handletrainerslidemsg BS_SCRIPTING, 2 - return + handletrainerslidemsg BS_SCRIPTING, 0 + trainerslidein B_POSITION_OPPONENT_RIGHT + handletrainerslidemsg BS_SCRIPTING, 1 + waitstate + trainerslideout B_POSITION_OPPONENT_RIGHT + waitstate + handletrainerslidemsg BS_SCRIPTING, 2 + return BattleScript_TrainerBSlideMsgEnd2:: - call BattleScript_TrainerBSlideMsgRet - end2 + call BattleScript_TrainerBSlideMsgRet + end2 diff --git a/include/battle.h b/include/battle.h index 19f9df13d8..46975bec3c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -581,8 +581,6 @@ struct BattleStruct void (*savedCallback)(void); u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle u16 chosenItem[MAX_BATTLERS_COUNT]; - u8 AI_itemType[2]; - u8 AI_itemFlags[2]; u16 choicedMove[MAX_BATTLERS_COUNT]; u16 changedItems[MAX_BATTLERS_COUNT]; u8 switchInItemsCounter; @@ -662,6 +660,7 @@ struct BattleStruct u8 storedHealingWish:4; // Each battler as a bit. u8 storedLunarDance:4; // Each battler as a bit. u16 supremeOverlordModifier[MAX_BATTLERS_COUNT]; + u8 itemPartyIndex[MAX_BATTLERS_COUNT]; }; #define F_DYNAMIC_TYPE_1 (1 << 6) diff --git a/include/battle_ai_switch_items.h b/include/battle_ai_switch_items.h index 70dc41b34b..622593b6dd 100644 --- a/include/battle_ai_switch_items.h +++ b/include/battle_ai_switch_items.h @@ -1,36 +1,6 @@ #ifndef GUARD_BATTLE_AI_SWITCH_ITEMS_H #define GUARD_BATTLE_AI_SWITCH_ITEMS_H -enum -{ - AI_ITEM_FULL_RESTORE = 1, - AI_ITEM_HEAL_HP, - AI_ITEM_CURE_CONDITION, - AI_ITEM_X_STAT, - AI_ITEM_GUARD_SPEC, - AI_ITEM_NOT_RECOGNIZABLE -}; - -enum { - AI_HEAL_CONFUSION, - AI_HEAL_PARALYSIS, - AI_HEAL_FREEZE, - AI_HEAL_BURN, - AI_HEAL_POISON, - AI_HEAL_SLEEP, -}; - -enum { - AI_X_ATTACK, - AI_X_DEFEND, - AI_X_SPEED, - AI_X_SPATK, - AI_X_SPDEF, // Unused - AI_X_ACCURACY, - AI_X_EVASION, // Unused - AI_DIRE_HIT, -}; - void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId); void AI_TrySwitchOrUseItem(void); u8 GetMostSuitableMonToSwitchInto(void); diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 1124c3a607..e552077534 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -648,8 +648,11 @@ #define STRINGID_COULDNTFULLYPROTECT 646 #define STRINGID_STOCKPILEDEFFECTWOREOFF 647 #define STRINGID_PKMNREVIVEDREADYTOFIGHT 648 +#define STRINGID_ITEMRESTOREDSPECIESHEALTH 649 +#define STRINGID_ITEMCUREDSPECIESSTATUS 650 +#define STRINGID_ITEMRESTOREDSPECIESPP 651 -#define BATTLESTRINGS_COUNT 649 +#define BATTLESTRINGS_COUNT 652 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/constants/item_effects.h b/include/constants/item_effects.h index c3970b9c1b..7cd4a58f48 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -7,12 +7,12 @@ #define ITEM0_INFATUATION 0x80 // new field 1 masks -#define ITEM1_X_ATTACK 0x1 -#define ITEM1_X_DEFENSE 0x2 -#define ITEM1_X_SPEED 0x4 -#define ITEM1_X_SPATK 0x8 -#define ITEM1_X_SPDEF 0x10 -#define ITEM1_X_ACCURACY 0x20 +#define ITEM1_X_ATTACK STAT_ATK +#define ITEM1_X_DEFENSE STAT_DEF +#define ITEM1_X_SPEED STAT_SPEED +#define ITEM1_X_SPATK STAT_SPATK +#define ITEM1_X_SPDEF STAT_SPDEF +#define ITEM1_X_ACCURACY STAT_ACC // field 3 masks #define ITEM3_CONFUSION 0x1 diff --git a/include/constants/items.h b/include/constants/items.h index 2b6ba5c8f2..4421181668 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -1030,14 +1030,27 @@ #define EXP_30000 5 // Item type IDs (used to determine the exit callback) -#define ITEM_USE_MAIL 0 -#define ITEM_USE_PARTY_MENU 1 -#define ITEM_USE_FIELD 2 -#define ITEM_USE_PBLOCK_CASE 3 -#define ITEM_USE_BAG_MENU 4 // No exit callback, stays in bag menu +#define ITEM_USE_MAIL 0 +#define ITEM_USE_PARTY_MENU 1 +#define ITEM_USE_FIELD 2 +#define ITEM_USE_PBLOCK_CASE 3 +#define ITEM_USE_BAG_MENU 4 // No exit callback, stays in bag menu +#define ITEM_USE_PARTY_MENU_MOVES 5 -// Item battle usage IDs (only checked to see if nonzero) -#define ITEM_B_USE_MEDICINE 1 -#define ITEM_B_USE_OTHER 2 +// Item battle script IDs (need to be non-zero) +#define EFFECT_ITEM_RESTORE_HP 1 +#define EFFECT_ITEM_CURE_STATUS 2 +#define EFFECT_ITEM_HEAL_AND_CURE_STATUS 3 +#define EFFECT_ITEM_INCREASE_STAT 4 +#define EFFECT_ITEM_SET_MIST 5 +#define EFFECT_ITEM_SET_FOCUS_ENERGY 6 +#define EFFECT_ITEM_ESCAPE 7 +#define EFFECT_ITEM_THROW_BALL 8 +#define EFFECT_ITEM_REVIVE 9 +#define EFFECT_ITEM_RESTORE_PP 10 +#define EFFECT_ITEM_INCREASE_ALL_STATS 11 + +// Enigma Berry dummy constant +#define EFFECT_ITEM_ENIGMA_BERRY_EREADER 1 #endif // GUARD_CONSTANTS_ITEMS_H diff --git a/include/item.h b/include/item.h index cf2209e0e6..a99782f803 100644 --- a/include/item.h +++ b/include/item.h @@ -19,7 +19,6 @@ struct Item u8 type; ItemUseFunc fieldUseFunc; u8 battleUsage; - ItemUseFunc battleUseFunc; u8 secondaryId; u8 flingPower; }; @@ -72,8 +71,9 @@ u8 ItemId_GetPocket(u16 itemId); u8 ItemId_GetType(u16 itemId); ItemUseFunc ItemId_GetFieldFunc(u16 itemId); u8 ItemId_GetBattleUsage(u16 itemId); -ItemUseFunc ItemId_GetBattleFunc(u16 itemId); u8 ItemId_GetSecondaryId(u16 itemId); u8 ItemId_GetFlingPower(u16 itemId); +u32 GetItemStatus1Mask(u16 itemId); +u32 GetItemStatus2Mask(u16 itemId); #endif // GUARD_ITEM_H diff --git a/include/item_use.h b/include/item_use.h index 812e984ec8..afa87c6973 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -30,12 +30,9 @@ void ItemUseOutOfBattle_FormChange(u8); void ItemUseOutOfBattle_FormChange_ConsumedOnUse(u8); void ItemUseOutOfBattle_Honey(u8); void ItemUseOutOfBattle_CannotUse(u8); -void ItemUseInBattle_PokeBall(u8); -void ItemUseInBattle_StatIncrease(u8); -void ItemUseInBattle_Medicine(u8); -void ItemUseInBattle_PPRecovery(u8); -void ItemUseInBattle_Escape(u8); -void ItemUseInBattle_EnigmaBerry(u8); +void ItemUseInBattle_BagMenu(u8 taskId); +void ItemUseInBattle_PartyMenu(u8 taskId); +void ItemUseInBattle_PartyMenuChooseMove(u8 taskId); void Task_UseDigEscapeRopeOnField(u8 taskId); u8 CanUseDigOrEscapeRopeOnCurMap(void); u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId); diff --git a/include/party_menu.h b/include/party_menu.h index afb320e18c..31e5910748 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -48,6 +48,8 @@ void LoadHeldItemIcons(void); void DrawHeldItemIconsForTrade(u8 *partyCounts, u8 *partySpriteIds, u8 whichParty); void LoadPartyMenuAilmentGfx(void); void CB2_ShowPartyMenuForItemUse(void); +void ItemUseCB_BattleScript(u8 taskId, TaskFunc task); +void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task); void ItemUseCB_Medicine(u8 taskId, TaskFunc task); void ItemUseCB_AbilityCapsule(u8 taskId, TaskFunc task); void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task); @@ -64,6 +66,7 @@ void ItemUseCB_SacredAsh(u8 taskId, TaskFunc task); void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task); void ItemUseCB_FormChange(u8 taskId, TaskFunc task); void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task); +const u8* GetItemEffect(u16 item); u8 GetItemEffectType(u16 item); void CB2_PartyMenuFromStartMenu(void); void CB2_ChooseMonToGiveItem(void); diff --git a/include/recorded_battle.h b/include/recorded_battle.h index fbe14a6569..d04e89c362 100644 --- a/include/recorded_battle.h +++ b/include/recorded_battle.h @@ -44,6 +44,7 @@ enum RECORDED_MOVE_TARGET, RECORDED_PARTY_INDEX, RECORDED_BATTLE_PALACE_ACTION, + RECORDED_ITEM_ID, }; extern u32 gRecordedBattleRngSeed; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 113e14cb8a..29911d798f 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -10,6 +10,8 @@ #include "constants/hold_effects.h" #include "battle_setup.h" #include "data.h" +#include "item.h" +#include "party_menu.h" #include "pokemon.h" #include "random.h" #include "util.h" @@ -995,22 +997,6 @@ u8 GetMostSuitableMonToSwitchInto(void) return PARTY_SIZE; } -static u8 GetAI_ItemType(u16 itemId, const u8 *itemEffect) -{ - if (itemId == ITEM_FULL_RESTORE) - return AI_ITEM_FULL_RESTORE; - else if (itemEffect[4] & ITEM4_HEAL_HP) - return AI_ITEM_HEAL_HP; - else if (itemEffect[3] & ITEM3_STATUS_ALL) - return AI_ITEM_CURE_CONDITION; - else if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1]) - return AI_ITEM_X_STAT; - else if (itemEffect[3] & ITEM3_GUARD_SPEC) - return AI_ITEM_GUARD_SPEC; - else - return AI_ITEM_NOT_RECOGNIZABLE; -} - static bool32 AiExpectsToFaintPlayer(void) { bool32 canFaintPlayer; @@ -1070,96 +1056,70 @@ static bool8 ShouldUseItem(void) u8 paramOffset; u8 battlerSide; - if (i != 0 && validMons > (gBattleResources->battleHistory->itemsNo - i) + 1) - continue; item = gBattleResources->battleHistory->trainerItems[i]; if (item == ITEM_NONE) continue; - if (gItemEffectTable[item] == NULL) + itemEffects = GetItemEffect(item); + if (itemEffects == NULL) continue; - if (item == ITEM_ENIGMA_BERRY_E_READER) - itemEffects = gSaveBlock1Ptr->enigmaBerry.itemEffect; - else - itemEffects = gItemEffectTable[item]; - - *(gBattleStruct->AI_itemType + gActiveBattler / 2) = GetAI_ItemType(item, itemEffects); - - switch (*(gBattleStruct->AI_itemType + gActiveBattler / 2)) + switch (ItemId_GetBattleUsage(item)) { - case AI_ITEM_FULL_RESTORE: + case EFFECT_ITEM_HEAL_AND_CURE_STATUS: shouldUse = AI_ShouldHeal(0); break; - case AI_ITEM_HEAL_HP: + case EFFECT_ITEM_RESTORE_HP: shouldUse = AI_ShouldHeal(itemEffects[GetItemEffectParamOffset(item, 4, 4)]); break; - case AI_ITEM_CURE_CONDITION: - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0; + case EFFECT_ITEM_CURE_STATUS: if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP) - { - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_SLEEP); shouldUse = TRUE; - } if (itemEffects[3] & ITEM3_POISON && (gBattleMons[gActiveBattler].status1 & STATUS1_POISON || gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON)) - { - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_POISON); shouldUse = TRUE; - } if (itemEffects[3] & ITEM3_BURN && gBattleMons[gActiveBattler].status1 & STATUS1_BURN) - { - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_BURN); shouldUse = TRUE; - } if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE) - { - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_FREEZE); shouldUse = TRUE; - } if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[gActiveBattler].status1 & STATUS1_PARALYSIS) - { - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_PARALYSIS); shouldUse = TRUE; - } if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION) - { - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_CONFUSION); shouldUse = TRUE; - } break; - case AI_ITEM_X_STAT: - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0; - if (gDisableStructs[gActiveBattler].isFirstTurn == 0) + case EFFECT_ITEM_INCREASE_STAT: + case EFFECT_ITEM_INCREASE_ALL_STATS: + if (!gDisableStructs[gActiveBattler].isFirstTurn + || AI_OpponentCanFaintAiWithMod(0)) break; - if (itemEffects[1] & ITEM1_X_ATTACK) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_ATTACK); - if (itemEffects[1] & ITEM1_X_DEFENSE) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_DEFEND); - if (itemEffects[1] & ITEM1_X_SPEED) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_SPEED); - if (itemEffects[1] & ITEM1_X_SPATK) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_SPATK); - if (itemEffects[1] & ITEM1_X_SPDEF) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_SPDEF); - if (itemEffects[1] & ITEM1_X_ACCURACY) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_ACCURACY); - if (itemEffects[0] & ITEM0_DIRE_HIT) - *(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_DIRE_HIT); shouldUse = TRUE; break; - case AI_ITEM_GUARD_SPEC: + case EFFECT_ITEM_SET_FOCUS_ENERGY: + if (!gDisableStructs[gActiveBattler].isFirstTurn + || gBattleMons[gActiveBattler].status2 & STATUS2_FOCUS_ENERGY + || AI_OpponentCanFaintAiWithMod(0)) + break; + shouldUse = TRUE; + break; + case EFFECT_ITEM_SET_MIST: battlerSide = GetBattlerSide(gActiveBattler); - if (gDisableStructs[gActiveBattler].isFirstTurn != 0 && gSideTimers[battlerSide].mistTimer == 0) + if (gDisableStructs[gActiveBattler].isFirstTurn && gSideTimers[battlerSide].mistTimer == 0) shouldUse = TRUE; break; - case AI_ITEM_NOT_RECOGNIZABLE: + case EFFECT_ITEM_REVIVE: + gBattleStruct->itemPartyIndex[gActiveBattler] = GetFirstFaintedPartyIndex(gActiveBattler); + if (gBattleStruct->itemPartyIndex[gActiveBattler] != PARTY_SIZE) // Revive if possible. + shouldUse = TRUE; + break; + default: return FALSE; } - if (shouldUse) { + // Set selected party ID to current battler if none chosen. + if (gBattleStruct->itemPartyIndex[gActiveBattler] == PARTY_SIZE) + gBattleStruct->itemPartyIndex[gActiveBattler] = gBattlerPartyIndexes[gActiveBattler]; BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_USE_ITEM, 0); - *(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2) = item; + gBattleStruct->chosenItem[gActiveBattler] = item; gBattleResources->battleHistory->trainerItems[i] = 0; return shouldUse; } diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 7a5149313d..cb0499ac8f 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1667,7 +1667,7 @@ static void OpponentHandleChooseMove(void) static void OpponentHandleChooseItem(void) { - BtlController_EmitOneReturnValue(BUFFER_B, *(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2)); + BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]); OpponentBufferExecCompleted(); } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index 1fe8addcc3..e7fc6fd84a 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -10,6 +10,7 @@ #include "battle_tv.h" #include "bg.h" #include "data.h" +#include "item_menu.h" #include "item_use.h" #include "link.h" #include "main.h" @@ -1437,6 +1438,10 @@ static void RecordedOpponentHandleChooseMove(void) static void RecordedOpponentHandleChooseItem(void) { + u8 byte1 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler); + u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler); + gBattleStruct->chosenItem[gActiveBattler] = (byte1 << 8) | byte2; + BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]); RecordedOpponentBufferExecCompleted(); } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 869a5e18e4..87f5758399 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -7,6 +7,7 @@ #include "battle_interface.h" #include "bg.h" #include "data.h" +#include "item_menu.h" #include "item_use.h" #include "link.h" #include "main.h" @@ -1461,6 +1462,10 @@ static void RecordedPlayerHandleChooseMove(void) static void RecordedPlayerHandleChooseItem(void) { + u8 byte1 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler); + u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler); + gBattleStruct->chosenItem[gActiveBattler] = (byte1 << 8) | byte2; + BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]); RecordedPlayerBufferExecCompleted(); } diff --git a/src/battle_main.c b/src/battle_main.c index 7b6af8a23a..a5a9b5bbf6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4162,6 +4162,7 @@ static void HandleTurnActionSelectionState(void) } else { + gBattleStruct->itemPartyIndex[gActiveBattler] = PARTY_SIZE; BtlController_EmitChooseAction(BUFFER_A, gChosenActionByBattler[0], gBattleResources->bufferB[0][1] | (gBattleResources->bufferB[0][2] << 8)); MarkBattlerForControllerExec(gActiveBattler); gBattleCommunication[gActiveBattler]++; @@ -4229,10 +4230,11 @@ static void HandleTurnActionSelectionState(void) return; } - if ((gBattleTypeFlags & (BATTLE_TYPE_LINK + if (((gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER_NO_PYRAMID | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK)) + && !gTestRunnerEnabled) // Or if currently held by Sky Drop || gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED) { diff --git a/src/battle_message.c b/src/battle_message.c index cb1f640506..7d10b19f11 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -467,7 +467,7 @@ const u8 *const gPokeblockWasTooXStringTable[FLAVOR_COUNT] = static const u8 sText_PlayerUsedItem[] = _("{B_PLAYER_NAME} used\n{B_LAST_ITEM}!"); static const u8 sText_WallyUsedItem[] = _("WALLY used\n{B_LAST_ITEM}!"); -static const u8 sText_Trainer1UsedItem[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nused {B_LAST_ITEM}!"); +static const u8 sText_Trainer1UsedItem[] = _("{B_ATK_TRAINER_CLASS} {B_ATK_TRAINER_NAME}\nused {B_LAST_ITEM}!"); static const u8 sText_TrainerBlockedBall[] = _("The TRAINER blocked the BALL!"); static const u8 sText_DontBeAThief[] = _("Don't be a thief!"); static const u8 sText_ItDodgedBall[] = _("It dodged the thrown BALL!\nThis POKéMON can't be caught!"); @@ -783,9 +783,15 @@ static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell static const u8 sText_CouldntFullyProtect[] = _("{B_DEF_NAME_WITH_PREFIX} couldn't fully protect\nitself and got hurt!"); static const u8 sText_StockpiledEffectWoreOff[] = _("{B_ATK_NAME_WITH_PREFIX}'s stockpiled\neffect wore off!"); static const u8 sText_PkmnRevivedReadyToFight[] = _("{B_BUFF1} was revived and\nis ready to fight again!"); +static const u8 sText_ItemRestoredSpeciesHealth[] = _("{B_LAST_ITEM} restored\n{B_BUFF1}'s health!"); +static const u8 sText_ItemCuredSpeciesStatus[] = _("{B_LAST_ITEM} cured\n{B_BUFF1}'s status!"); +static const u8 sText_ItemRestoredSpeciesPP[] = _("{B_LAST_ITEM} restored\n{B_BUFF1}'s PP!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_ITEMRESTOREDSPECIESHEALTH - BATTLESTRINGS_TABLE_START] = sText_ItemRestoredSpeciesHealth, + [STRINGID_ITEMCUREDSPECIESSTATUS - BATTLESTRINGS_TABLE_START] = sText_ItemCuredSpeciesStatus, + [STRINGID_ITEMRESTOREDSPECIESPP - BATTLESTRINGS_TABLE_START] = sText_ItemRestoredSpeciesPP, [STRINGID_PKMNREVIVEDREADYTOFIGHT - BATTLESTRINGS_TABLE_START] = sText_PkmnRevivedReadyToFight, [STRINGID_STOCKPILEDEFFECTWOREOFF - BATTLESTRINGS_TABLE_START] = sText_StockpiledEffectWoreOff, [STRINGID_COULDNTFULLYPROTECT - BATTLESTRINGS_TABLE_START] = sText_CouldntFullyProtect, @@ -1424,6 +1430,11 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_PKMNSABILITYPREVENTSABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilityPreventsAbility, }; +const u16 gTrainerUsedItemStringIds[] = +{ + STRINGID_PLAYERUSEDITEM, STRINGID_TRAINER1USEDITEM +}; + const u16 gZEffectStringIds[] = { [B_MSG_Z_RESET_STATS] = STRINGID_ZMOVERESETSSTATS, @@ -1820,16 +1831,6 @@ const u16 gSafariPokeblockResultStringIds[] = [B_MSG_MON_IGNORED] = STRINGID_PKMNIGNOREDX }; -const u16 gTrainerItemCuredStatusStringIds[] = -{ - [AI_HEAL_CONFUSION] = STRINGID_PKMNSITEMSNAPPEDOUT, - [AI_HEAL_PARALYSIS] = STRINGID_PKMNSITEMCUREDPARALYSIS, - [AI_HEAL_FREEZE] = STRINGID_PKMNSITEMDEFROSTEDIT, - [AI_HEAL_BURN] = STRINGID_PKMNSITEMHEALEDBURN, - [AI_HEAL_POISON] = STRINGID_PKMNSITEMCUREDPOISON, - [AI_HEAL_SLEEP] = STRINGID_PKMNSITEMWOKEIT -}; - const u16 gBerryEffectStringIds[] = { [B_MSG_CURED_PROBLEM] = STRINGID_PKMNSITEMCUREDPROBLEM, diff --git a/src/battle_pyramid_bag.c b/src/battle_pyramid_bag.c index d580cf6800..9d5cee94a5 100644 --- a/src/battle_pyramid_bag.c +++ b/src/battle_pyramid_bag.c @@ -1299,11 +1299,18 @@ static void TryCloseBagToGiveItem(u8 taskId) static void BagAction_UseInBattle(u8 taskId) { - if (ItemId_GetBattleFunc(gSpecialVar_ItemId) != NULL) - { - CloseMenuActionWindow(); - ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId); - } + // Safety check + u16 type = ItemId_GetType(gSpecialVar_ItemId); + if (!ItemId_GetBattleUsage(gSpecialVar_ItemId)) + return; + + CloseMenuActionWindow(); + if (type == ITEM_USE_BAG_MENU) + ItemUseInBattle_BagMenu(taskId); + else if (type == ITEM_USE_PARTY_MENU) + ItemUseInBattle_PartyMenu(taskId); + else if (type == ITEM_USE_PARTY_MENU_MOVES) + ItemUseInBattle_PartyMenuChooseMove(taskId); } static void Task_BeginItemSwap(u8 taskId) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a0d8181d67..d313697b0a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -52,6 +52,7 @@ #include "constants/battle_string_ids.h" #include "constants/hold_effects.h" #include "constants/items.h" +#include "constants/item_effects.h" #include "constants/map_types.h" #include "constants/moves.h" #include "constants/party_menu.h" @@ -11264,7 +11265,7 @@ static void Cmd_various(void) // Open party menu, wait to go to next instruction. else { - BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gActiveBattler]); + BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); MarkBattlerForControllerExec(gBattlerAttacker); } return; @@ -16427,3 +16428,144 @@ u8 GetFirstFaintedPartyIndex(u8 battlerId) // Returns PARTY_SIZE if none found. return PARTY_SIZE; } + +void BS_ItemRestoreHP(void) { + NATIVE_ARGS(); + u16 healAmount; + u32 battlerId = MAX_BATTLERS_COUNT; + u32 healParam = GetItemEffect(gLastUsedItem)[6]; + u32 side = GetBattlerSide(gBattlerAttacker); + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + u16 hp = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP); + u16 maxHP = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_MAX_HP); + gBattleCommunication[MULTIUSE_STATE] = 0; + + // Track the number of Revives used in a battle. + if (hp == 0 && side == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255) + gBattleResults.numRevivesUsed++; + + // Check if the recipient is an active battler. + if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) + battlerId = gBattlerAttacker; + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + battlerId = BATTLE_PARTNER(gBattlerAttacker); + + // Get amount to heal. + switch (healParam) + { + case ITEM6_HEAL_HP_FULL: + healAmount = maxHP; + break; + case ITEM6_HEAL_HP_HALF: + healAmount = maxHP / 2; + break; + case ITEM6_HEAL_HP_QUARTER: + healAmount = maxHP / 4; + break; + default: + healAmount = healParam; + break; + } + if (hp + healAmount > maxHP) + healAmount = maxHP - hp; + + // Heal is applied as move damage if battler is active. + if (battlerId != MAX_BATTLERS_COUNT && hp != 0) + { + gBattleMoveDamage = -healAmount; + } + else + { + hp += healAmount; + SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp); + + // Revived battlers on the field need to be brought back. + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && battlerId != MAX_BATTLERS_COUNT) + { + gAbsentBattlerFlags &= ~gBitTable[battlerId]; + gBattleCommunication[MULTIUSE_STATE] = TRUE; + } + } + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ItemCureStatus(void) { + NATIVE_ARGS(); + struct Pokemon *party = (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + + // Heal Status1 conditions. + HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], gBattleStruct->itemPartyIndex[gBattlerAttacker], GetItemStatus1Mask(gLastUsedItem), gBattlerAttacker); + + // Heal Status2 conditions if battler is active. + if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) + gBattleMons[gBattleStruct->itemPartyIndex[gBattlerAttacker]].status2 &= ~GetItemStatus2Mask(gLastUsedItem); + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + { + gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); + gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker); + if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + } + + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ItemIncreaseStat(void) { + NATIVE_ARGS(); + u16 statId = GetItemEffect(gLastUsedItem)[1]; + u16 stages = ItemId_GetHoldEffectParam(gLastUsedItem); + SET_STATCHANGER(statId, stages, FALSE); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ItemRestorePP(void) { + NATIVE_ARGS(); + const u8 *effect = GetItemEffect(gLastUsedItem); + u32 i, pp, maxPP, moveId; + u32 loopEnd = MAX_MON_MOVES; + u32 battlerId = MAX_BATTLERS_COUNT; + struct Pokemon *mon = (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) ? &gPlayerParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]] : &gEnemyParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]]; + + // Check whether to apply to all moves. + if (effect[4] & ITEM4_HEAL_PP_ONE) + { + i = gChosenMovePos; + loopEnd = gChosenMovePos + 1; + } + + // Check if the recipient is an active battler. + if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) + battlerId = gBattlerAttacker; + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + battlerId = BATTLE_PARTNER(gBattlerAttacker); + + // Heal PP! + for (i = 0; i < loopEnd; i++) + { + pp = GetMonData(mon, MON_DATA_PP1 + i, NULL); + moveId = GetMonData(mon, MON_DATA_MOVE1 + i, NULL); + maxPP = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), i); + if (pp != maxPP) + { + pp += effect[6]; + if (pp > maxPP) + pp = maxPP; + SetMonData(mon, MON_DATA_PP1 + i, &pp); + + // Update battler PP if needed. + if (battlerId != MAX_BATTLERS_COUNT + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[battlerId] + && MOVE_IS_PERMANENT(battlerId, i)) + { + gBattleMons[battlerId].pp[i] = pp; + } + } + } + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(mon, MON_DATA_SPECIES)); + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 46b2de4421..ac274bf0f8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -21,6 +21,7 @@ #include "sprite.h" #include "string_util.h" #include "task.h" +#include "test_runner.h" #include "trig.h" #include "window.h" #include "battle_message.h" @@ -550,93 +551,13 @@ void HandleAction_Switch(void) void HandleAction_UseItem(void) { - gBattlerAttacker = gBattlerTarget = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; gBattle_BG0_X = 0; gBattle_BG0_Y = 0; ClearFuryCutterDestinyBondGrudge(gBattlerAttacker); gLastUsedItem = gBattleResources->bufferB[gBattlerAttacker][1] | (gBattleResources->bufferB[gBattlerAttacker][2] << 8); - - if (gLastUsedItem <= LAST_BALL) // is ball - { - gBattlescriptCurrInstr = BattleScript_BallThrow; - } - else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL) - { - gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[0]; // BattleScript_RunByUsingItem - } - else if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - { - gBattlescriptCurrInstr = gBattlescriptsForUsingItem[0]; // BattleScript_PlayerUsesItem - } - else - { - gBattleScripting.battler = gBattlerAttacker; - - switch (*(gBattleStruct->AI_itemType + (gBattlerAttacker >> 1))) - { - case AI_ITEM_FULL_RESTORE: - case AI_ITEM_HEAL_HP: - break; - case AI_ITEM_CURE_CONDITION: - gBattleCommunication[MULTISTRING_CHOOSER] = AI_HEAL_CONFUSION; - if (*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & (1 << AI_HEAL_CONFUSION)) - { - if (*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 0x3E) - gBattleCommunication[MULTISTRING_CHOOSER] = AI_HEAL_SLEEP; - } - else - { - // Check for other statuses, stopping at first (shouldn't be more than one) - while (!(*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 1)) - { - *(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) >>= 1; - gBattleCommunication[MULTISTRING_CHOOSER]++; - // MULTISTRING_CHOOSER will be either AI_HEAL_PARALYSIS, AI_HEAL_FREEZE, - // AI_HEAL_BURN, AI_HEAL_POISON, or AI_HEAL_SLEEP - } - } - break; - case AI_ITEM_X_STAT: - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_ROSE_ITEM; - if (*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1)) & (1 << AI_DIRE_HIT)) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_USED_DIRE_HIT; - } - else - { - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK) - PREPARE_STRING_BUFFER(gBattleTextBuff2, CHAR_X) - - while (!((*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1))) & 1)) - { - *(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) >>= 1; - gBattleTextBuff1[2]++; - } - - gBattleScripting.animArg1 = gBattleTextBuff1[2] + 14; - gBattleScripting.animArg2 = 0; - } - break; - case AI_ITEM_GUARD_SPEC: - // It seems probable that at some point there was a special message for - // an AI trainer using Guard Spec in a double battle. - // There isn't now however, and the assignment to 2 below goes out of - // bounds for gMistUsedStringIds and instead prints "{mon} is getting pumped" - // from the next table, gFocusEnergyUsedStringIds. - // In any case this isn't an issue in the retail version, as no trainers - // are ever given any Guard Spec to use. -#ifndef UBFIX - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - gBattleCommunication[MULTISTRING_CHOOSER] = 2; - else -#endif - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MIST; - break; - } - - gBattlescriptCurrInstr = gBattlescriptsForUsingItem[*(gBattleStruct->AI_itemType + gBattlerAttacker / 2)]; - } + gBattlescriptCurrInstr = gBattlescriptsForUsingItem[ItemId_GetBattleUsage(gLastUsedItem) - 1]; gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } @@ -914,7 +835,7 @@ void HandleAction_ActionFinished(void) u32 i, j; bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou; #endif - *(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = PARTY_SIZE; + *(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = gSelectedMonPartyId = PARTY_SIZE; gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; SpecialStatusesClear(); @@ -8207,7 +8128,6 @@ u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating) return ItemId_GetHoldEffect(gBattleMons[battlerId].item); } -// static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item) { if (item == ITEM_ENIGMA_BERRY_E_READER) diff --git a/src/data/items.h b/src/data/items.h index 6998aa573f..fc99e10373 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -20,9 +20,8 @@ const struct Item gItems[] = .price = 200, .description = sPokeBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_POKE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_POKE_BALL - FIRST_BALL, }, @@ -33,9 +32,8 @@ const struct Item gItems[] = .price = 600, .description = sGreatBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_GREAT_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_GREAT_BALL - FIRST_BALL, }, @@ -46,9 +44,8 @@ const struct Item gItems[] = .price = 800, .description = sUltraBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_ULTRA_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_ULTRA_BALL - FIRST_BALL, }, @@ -59,9 +56,8 @@ const struct Item gItems[] = .price = 0, .description = sMasterBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_MASTER_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_MASTER_BALL - FIRST_BALL, }, @@ -72,9 +68,8 @@ const struct Item gItems[] = .price = 20, .description = sPremierBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_PREMIER_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_PREMIER_BALL - FIRST_BALL, }, @@ -85,9 +80,8 @@ const struct Item gItems[] = .price = 300, .description = sHealBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_HEAL_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_HEAL_BALL - FIRST_BALL, }, @@ -98,9 +92,8 @@ const struct Item gItems[] = .price = 1000, .description = sNetBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_NET_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_NET_BALL - FIRST_BALL, }, @@ -111,9 +104,8 @@ const struct Item gItems[] = .price = 1000, .description = sNestBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_NEST_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_NEST_BALL - FIRST_BALL, }, @@ -124,9 +116,8 @@ const struct Item gItems[] = .price = 1000, .description = sDiveBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_DIVE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_DIVE_BALL - FIRST_BALL, }, @@ -137,9 +128,8 @@ const struct Item gItems[] = .price = 1000, .description = sDuskBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_DUSK_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_DUSK_BALL - FIRST_BALL, }, @@ -150,9 +140,8 @@ const struct Item gItems[] = .price = 1000, .description = sTimerBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_TIMER_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_TIMER_BALL - FIRST_BALL, }, @@ -163,9 +152,8 @@ const struct Item gItems[] = .price = 1000, .description = sQuickBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_QUICK_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_QUICK_BALL - FIRST_BALL, }, @@ -176,9 +164,8 @@ const struct Item gItems[] = .price = 1000, .description = sRepeatBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_REPEAT_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_REPEAT_BALL - FIRST_BALL, }, @@ -189,9 +176,8 @@ const struct Item gItems[] = .price = 1000, .description = sLuxuryBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LUXURY_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LUXURY_BALL - FIRST_BALL, }, @@ -202,9 +188,8 @@ const struct Item gItems[] = .price = 0, .description = sLevelBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LEVEL_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LEVEL_BALL - FIRST_BALL, }, @@ -215,9 +200,8 @@ const struct Item gItems[] = .price = 0, .description = sLureBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LURE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LURE_BALL - FIRST_BALL, }, @@ -228,9 +212,8 @@ const struct Item gItems[] = .price = 0, .description = sMoonBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_MOON_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_MOON_BALL - FIRST_BALL, }, @@ -241,9 +224,8 @@ const struct Item gItems[] = .price = 0, .description = sFriendBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_FRIEND_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_FRIEND_BALL - FIRST_BALL, }, @@ -254,9 +236,8 @@ const struct Item gItems[] = .price = 0, .description = sLoveBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LOVE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LOVE_BALL - FIRST_BALL, }, @@ -267,9 +248,8 @@ const struct Item gItems[] = .price = 0, .description = sFastBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_FAST_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_FAST_BALL - FIRST_BALL, }, @@ -280,9 +260,8 @@ const struct Item gItems[] = .price = 0, .description = sHeavyBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_HEAVY_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_HEAVY_BALL - FIRST_BALL, }, @@ -293,9 +272,8 @@ const struct Item gItems[] = .price = 0, .description = sDreamBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_DREAM_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_DREAM_BALL - FIRST_BALL, }, @@ -306,9 +284,8 @@ const struct Item gItems[] = .price = 0, .description = sSafariBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_SAFARI_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_SAFARI_BALL - FIRST_BALL, }, @@ -319,9 +296,8 @@ const struct Item gItems[] = .price = 0, .description = sSportBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_SPORT_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_SPORT_BALL - FIRST_BALL, }, @@ -332,9 +308,8 @@ const struct Item gItems[] = .price = 0, .description = sParkBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_PARK_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_PARK_BALL - FIRST_BALL, }, @@ -345,9 +320,8 @@ const struct Item gItems[] = .price = 0, .description = sBeastBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_BEAST_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_BEAST_BALL - FIRST_BALL, }, @@ -358,9 +332,8 @@ const struct Item gItems[] = .price = 0, .description = sCherishBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_CHERISH_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_CHERISH_BALL - FIRST_BALL, }, @@ -376,8 +349,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -391,8 +363,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -406,8 +377,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -421,8 +391,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -436,8 +405,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_HEAL_AND_CURE_STATUS, .flingPower = 30, }, @@ -450,8 +418,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -464,8 +431,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -479,8 +445,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -494,8 +459,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -509,8 +473,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -524,8 +487,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -538,8 +500,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -552,8 +513,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -566,8 +526,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -580,8 +539,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -594,8 +552,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -608,8 +565,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -622,8 +578,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -636,8 +591,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -650,8 +604,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -664,8 +617,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -677,10 +629,9 @@ const struct Item gItems[] = .holdEffectParam = 10, .description = sEtherDesc, .pocket = POCKET_ITEMS, - .type = ITEM_USE_PARTY_MENU, + .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -692,10 +643,9 @@ const struct Item gItems[] = .holdEffectParam = 255, .description = sMaxEtherDesc, .pocket = POCKET_ITEMS, - .type = ITEM_USE_PARTY_MENU, + .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -709,8 +659,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -724,8 +673,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -740,8 +688,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -767,8 +714,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -781,8 +727,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -797,8 +742,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -811,8 +755,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -825,8 +768,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -839,8 +781,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -853,8 +794,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -867,8 +807,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -881,8 +820,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -895,8 +833,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1454,8 +1391,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1468,8 +1404,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1482,8 +1417,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1618,17 +1552,19 @@ const struct Item gItems[] = // X Items +#define X_ITEM_STAGES (B_X_ITEMS_BUFF >= GEN_7) ? 2 : 1 + [ITEM_X_ATTACK] = { .name = _("X Attack"), .itemId = ITEM_X_ATTACK, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXAttackDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1637,12 +1573,12 @@ const struct Item gItems[] = .name = _("X Defense"), .itemId = ITEM_X_DEFENSE, .price = 2000, + .holdEffectParam = X_ITEM_STAGES, .description = sXDefenseDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1651,12 +1587,12 @@ const struct Item gItems[] = .name = _("X Sp. Atk"), .itemId = ITEM_X_SP_ATK, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXSpAtkDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1665,12 +1601,12 @@ const struct Item gItems[] = .name = _("X Sp. Def"), .itemId = ITEM_X_SP_DEF, .price = 2000, + .holdEffectParam = X_ITEM_STAGES, .description = sXSpDefDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1679,12 +1615,12 @@ const struct Item gItems[] = .name = _("X Speed"), .itemId = ITEM_X_SPEED, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXSpeedDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1693,12 +1629,12 @@ const struct Item gItems[] = .name = _("X Accuracy"), .itemId = ITEM_X_ACCURACY, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXAccuracyDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1711,8 +1647,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_SET_FOCUS_ENERGY, .flingPower = 30, }, @@ -1725,8 +1660,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_SET_MIST, .flingPower = 30, }, @@ -1739,8 +1673,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_Escape, + .battleUsage = EFFECT_ITEM_ESCAPE, .flingPower = 30, }, @@ -1753,8 +1686,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_Escape, + .battleUsage = EFFECT_ITEM_ESCAPE, .flingPower = 30, }, @@ -1767,8 +1699,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_Escape, + .battleUsage = EFFECT_ITEM_ESCAPE, .flingPower = 30, }, @@ -1781,11 +1712,12 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, // Todo + .battleUsage = EFFECT_ITEM_INCREASE_ALL_STATS, .flingPower = 30, }, +#undef X_ITEM_STAGES + // Treasures [ITEM_BOTTLE_CAP] = @@ -6874,8 +6806,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6889,8 +6820,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6904,8 +6834,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6919,8 +6848,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6934,8 +6862,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6948,10 +6875,9 @@ const struct Item gItems[] = .holdEffectParam = 10, .description = sLeppaBerryDesc, .pocket = POCKET_BERRIES, - .type = ITEM_USE_PARTY_MENU, + .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 10, }, @@ -6966,8 +6892,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 10, }, @@ -6981,8 +6906,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6996,8 +6920,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -7017,8 +6940,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 10, }, @@ -7794,8 +7716,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_BAG_MENU, // Type handled by ItemUseOutOfBattle_EnigmaBerry .fieldUseFunc = ItemUseOutOfBattle_EnigmaBerry, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_EnigmaBerry, + .battleUsage = EFFECT_ITEM_ENIGMA_BERRY_EREADER, .flingPower = 10, }, diff --git a/src/data/pokemon/item_effects.h b/src/data/pokemon/item_effects.h index 632fb6b26e..087c6db0c2 100644 --- a/src/data/pokemon/item_effects.h +++ b/src/data/pokemon/item_effects.h @@ -533,8 +533,6 @@ const u8 *const gItemEffectTable[ITEMS_COUNT] = [ITEM_DIRE_HIT] = gItemEffect_DireHit, [ITEM_GUARD_SPEC] = gItemEffect_GuardSpec, - //[ITEM_MAX_MUSHROOMS] = gItemEffect_MaxMushrooms, // Todo - // Evolution Items [ITEM_FIRE_STONE] = gItemEffect_EvoItem, [ITEM_WATER_STONE] = gItemEffect_EvoItem, diff --git a/src/item.c b/src/item.c index db24cb82e9..da57c40766 100644 --- a/src/item.c +++ b/src/item.c @@ -7,12 +7,15 @@ #include "malloc.h" #include "secret_base.h" #include "item_menu.h" +#include "party_menu.h" #include "strings.h" #include "load_save.h" #include "item_use.h" #include "battle_pyramid.h" #include "battle_pyramid_bag.h" +#include "constants/battle.h" #include "constants/items.h" +#include "constants/item_effects.h" #include "constants/hold_effects.h" static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count); @@ -922,14 +925,36 @@ ItemUseFunc ItemId_GetFieldFunc(u16 itemId) return gItems[SanitizeItemId(itemId)].fieldUseFunc; } +// Returns an item's battle effect script ID. u8 ItemId_GetBattleUsage(u16 itemId) { - return gItems[SanitizeItemId(itemId)].battleUsage; -} - -ItemUseFunc ItemId_GetBattleFunc(u16 itemId) -{ - return gItems[SanitizeItemId(itemId)].battleUseFunc; + u16 item = SanitizeItemId(itemId); + // Handle E-Reader berries. + if (item == ITEM_ENIGMA_BERRY_E_READER) + { + switch (GetItemEffectType(gSpecialVar_ItemId)) + { + case ITEM_EFFECT_X_ITEM: + return EFFECT_ITEM_INCREASE_STAT; + case ITEM_EFFECT_HEAL_HP: + return EFFECT_ITEM_RESTORE_HP; + case ITEM_EFFECT_CURE_POISON: + case ITEM_EFFECT_CURE_SLEEP: + case ITEM_EFFECT_CURE_BURN: + case ITEM_EFFECT_CURE_FREEZE: + case ITEM_EFFECT_CURE_PARALYSIS: + case ITEM_EFFECT_CURE_ALL_STATUS: + case ITEM_EFFECT_CURE_CONFUSION: + case ITEM_EFFECT_CURE_INFATUATION: + return EFFECT_ITEM_CURE_STATUS; + case ITEM_EFFECT_HEAL_PP: + return EFFECT_ITEM_RESTORE_PP; + default: + return 0; + } + } + else + return gItems[item].battleUsage; } u8 ItemId_GetSecondaryId(u16 itemId) @@ -941,3 +966,36 @@ u8 ItemId_GetFlingPower(u16 itemId) { return gItems[SanitizeItemId(itemId)].flingPower; } + + +u32 GetItemStatus1Mask(u16 itemId) +{ + const u8 *effect = GetItemEffect(itemId); + switch (effect[3]) + { + case ITEM3_FREEZE: + return STATUS1_FREEZE; + case ITEM3_BURN: + return STATUS1_BURN; + case ITEM3_POISON: + return STATUS1_POISON | STATUS1_TOXIC_POISON; + case ITEM3_SLEEP: + return STATUS1_SLEEP; + case ITEM3_STATUS_ALL: + return STATUS1_ANY; + } + return 0; +} + +u32 GetItemStatus2Mask(u16 itemId) +{ + const u8 *effect = GetItemEffect(itemId); + if (effect[3] & ITEM3_STATUS_ALL) + return STATUS2_INFATUATION | STATUS2_CONFUSION; + else if (effect[0] & ITEM0_INFATUATION) + return STATUS2_INFATUATION; + else if (effect[3] & ITEM3_CONFUSION) + return STATUS2_CONFUSION; + else + return 0; +} diff --git a/src/item_menu.c b/src/item_menu.c index 4c66b09239..2a382b0645 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -1985,11 +1985,18 @@ static void ItemMenu_Cancel(u8 taskId) static void ItemMenu_UseInBattle(u8 taskId) { - if (ItemId_GetBattleFunc(gSpecialVar_ItemId)) - { - RemoveContextWindow(); - ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId); - } + // Safety check + u16 type = ItemId_GetType(gSpecialVar_ItemId); + if (!ItemId_GetBattleUsage(gSpecialVar_ItemId)) + return; + + RemoveContextWindow(); + if (type == ITEM_USE_BAG_MENU) + ItemUseInBattle_BagMenu(taskId); + else if (type == ITEM_USE_PARTY_MENU) + ItemUseInBattle_PartyMenu(taskId); + else if (type == ITEM_USE_PARTY_MENU_MOVES) + ItemUseInBattle_PartyMenuChooseMove(taskId); } void CB2_ReturnToBagMenuPocket(void) diff --git a/src/item_use.c b/src/item_use.c index 9c925945af..8bcadfb2eb 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -75,6 +75,7 @@ static void Task_CloseCantUseKeyItemMessage(u8); static void SetDistanceOfClosestHiddenItem(u8, s16, s16); static void CB2_OpenPokeblockFromBag(void); static void ItemUseOnFieldCB_Honey(u8 taskId); +static bool32 CannotUseBagBattleItem(u16 itemId); // EWRAM variables EWRAM_DATA static void(*sItemUseOnFieldCB)(u8 taskId) = NULL; @@ -86,9 +87,10 @@ EWRAM_DATA static void(*sItemUseOnFieldCB)(u8 taskId) = NULL; // Never occurs in vanilla, but can occur with improperly created items static const MainCallback sItemUseCallbacks[] = { - [ITEM_USE_PARTY_MENU - 1] = CB2_ShowPartyMenuForItemUse, - [ITEM_USE_FIELD - 1] = CB2_ReturnToField, - [ITEM_USE_PBLOCK_CASE - 1] = NULL, + [ITEM_USE_PARTY_MENU - 1] = CB2_ShowPartyMenuForItemUse, + [ITEM_USE_FIELD - 1] = CB2_ReturnToField, + [ITEM_USE_PBLOCK_CASE - 1] = NULL, + [ITEM_USE_PARTY_MENU_MOVES - 1] = CB2_ShowPartyMenuForItemUse, }; static const u8 sClockwiseDirections[] = {DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST}; @@ -1105,25 +1107,6 @@ static void Task_UseStatIncreaseItem(u8 taskId) } } -// e.g. X Attack, Guard Spec -void ItemUseInBattle_StatIncrease(u8 taskId) -{ - u16 partyId = gBattlerPartyIndexes[gBattlerInMenuId]; - - if (ExecuteTableBasedItemEffect(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE) - { - if (!InBattlePyramid()) - DisplayItemMessage(taskId, FONT_NORMAL, gText_WontHaveEffect, CloseItemMessage); - else - DisplayItemMessageInBattlePyramid(taskId, gText_WontHaveEffect, Task_CloseBattlePyramidBagMessage); - } - else - { - gTasks[taskId].func = Task_UseStatIncreaseItem; - gTasks[taskId].data[8] = 0; - } -} - static void ItemUseInBattle_ShowPartyMenu(u8 taskId) { if (!InBattlePyramid()) @@ -1138,41 +1121,119 @@ static void ItemUseInBattle_ShowPartyMenu(u8 taskId) } } -void ItemUseInBattle_Medicine(u8 taskId) +void ItemUseInBattle_PartyMenu(u8 taskId) { - gItemUseCB = ItemUseCB_Medicine; + gItemUseCB = ItemUseCB_BattleScript; ItemUseInBattle_ShowPartyMenu(taskId); } -// Unused. Sacred Ash cannot be used in battle -void ItemUseInBattle_SacredAsh(u8 taskId) +void ItemUseInBattle_PartyMenuChooseMove(u8 taskId) { - gItemUseCB = ItemUseCB_SacredAsh; + gItemUseCB = ItemUseCB_BattleChooseMove; ItemUseInBattle_ShowPartyMenu(taskId); } -void ItemUseInBattle_PPRecovery(u8 taskId) +// Returns whether an item can be used in battle and sets the fail text. +static bool32 CannotUseBagBattleItem(u16 itemId) { - gItemUseCB = ItemUseCB_PPRecovery; - ItemUseInBattle_ShowPartyMenu(taskId); -} + u8 cannotUse = FALSE; + u16 battleUsage = ItemId_GetBattleUsage(itemId); + const u8* failStr = NULL; -// Fluffy Tail / Poke Doll -void ItemUseInBattle_Escape(u8 taskId) -{ - - if((gBattleTypeFlags & BATTLE_TYPE_TRAINER) == FALSE) + // Embargo Check + if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) + || (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO)) { + return TRUE; + } + // X-Items + if (battleUsage == EFFECT_ITEM_INCREASE_STAT + && gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE) + { + cannotUse++; + } + // Dire Hit + if (battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY + && !(gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY)) + { + cannotUse++; + } + // Guard Spec + if (battleUsage == EFFECT_ITEM_SET_MIST + && gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST) + { + cannotUse++; + } + // Escape Items + if (battleUsage == EFFECT_ITEM_ESCAPE + && gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + cannotUse++; + } + // Poke Balls + if (battleUsage == EFFECT_ITEM_THROW_BALL) + { + switch (GetBallThrowableState()) + { + case BALL_THROW_UNABLE_TWO_MONS: + failStr = sText_CantThrowPokeBall_TwoMons; + cannotUse++; + break; + case BALL_THROW_UNABLE_NO_ROOM: + failStr = gText_BoxFull; + cannotUse++; + break; + #if B_SEMI_INVULNERABLE_CATCH >= GEN_4 + case BALL_THROW_UNABLE_SEMI_INVULNERABLE: + failStr = sText_CantThrowPokeBall_SemiInvulnerable; + cannotUse++; + break; + #endif + case BALL_THROW_UNABLE_DISABLED_FLAG: + failStr = sText_CantThrowPokeBall_Disabled; + cannotUse++; + break; + } + } + // Max Mushrooms + if (battleUsage == EFFECT_ITEM_INCREASE_ALL_STATS) + { + u32 i; + for (i = 1; i < NUM_STATS; i++) + { + if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL)) + { + cannotUse++; + break; + } + } + } + + if (failStr != NULL) + StringExpandPlaceholders(gStringVar4, failStr); + else + StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect); + return cannotUse; +} + +void ItemUseInBattle_BagMenu(u8 taskId) +{ + if (CannotUseBagBattleItem(gSpecialVar_ItemId)) + { + if (!InBattlePyramid()) + DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); + else + DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); + } + else + { + PlaySE(SE_SELECT); RemoveUsedItem(); if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, Task_FadeAndCloseBagMenu); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, CloseBattlePyramidBag); } - else - { - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); - } } void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) @@ -1219,33 +1280,6 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) } } -void ItemUseInBattle_EnigmaBerry(u8 taskId) -{ - switch (GetItemEffectType(gSpecialVar_ItemId)) - { - case ITEM_EFFECT_X_ITEM: - ItemUseInBattle_StatIncrease(taskId); - break; - case ITEM_EFFECT_HEAL_HP: - case ITEM_EFFECT_CURE_POISON: - case ITEM_EFFECT_CURE_SLEEP: - case ITEM_EFFECT_CURE_BURN: - case ITEM_EFFECT_CURE_FREEZE: - case ITEM_EFFECT_CURE_PARALYSIS: - case ITEM_EFFECT_CURE_ALL_STATUS: - case ITEM_EFFECT_CURE_CONFUSION: - case ITEM_EFFECT_CURE_INFATUATION: - ItemUseInBattle_Medicine(taskId); - break; - case ITEM_EFFECT_HEAL_PP: - ItemUseInBattle_PPRecovery(taskId); - break; - default: - ItemUseOutOfBattle_CannotUse(taskId); - break; - } -} - void ItemUseOutOfBattle_FormChange(u8 taskId) { gItemUseCB = ItemUseCB_FormChange; diff --git a/src/party_menu.c b/src/party_menu.c index 30f2f81501..dd46b10634 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -390,8 +390,8 @@ static void Task_DisplayHPRestoredMessage(u8); static u16 ItemEffectToMonEv(struct Pokemon *, u8); static void ItemEffectToStatString(u8, u8 *); static void ReturnToUseOnWhichMon(u8); -static void SetSelectedMoveForPPItem(u8); -static void TryUsePPItem(u8); +static void SetSelectedMoveForItem(u8); +static void TryUseItemOnMove(u8); static void Task_LearnedMove(u8); static void Task_ReplaceMoveYesNo(u8); static void Task_DoLearnedMoveFanfareAfterText(u8); @@ -480,6 +480,9 @@ static bool8 SetUpFieldMove_Fly(void); static bool8 SetUpFieldMove_Waterfall(void); static bool8 SetUpFieldMove_Dive(void); void TryItemHoldFormChange(struct Pokemon *mon); +static void ShowMoveSelectWindow(u8 slot); +static void Task_HandleWhichMoveInput(u8 taskId); +static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon); // static const data #include "data/party_menu.h" @@ -4301,12 +4304,7 @@ static void Task_SetSacredAshCB(u8 taskId) static bool8 IsHPRecoveryItem(u16 item) { - const u8 *effect; - - if (item == ITEM_ENIGMA_BERRY_E_READER) - effect = gSaveBlock1Ptr->enigmaBerry.itemEffect; - else - effect = gItemEffectTable[item]; + const u8 *effect = GetItemEffect(item); if (effect == NULL) return FALSE; @@ -4396,18 +4394,97 @@ static bool8 IsItemFlute(u16 item) return FALSE; } -static bool8 ExecuteTableBasedItemEffect_(u8 partyMonIndex, u16 item, u8 monMoveIndex) +static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon) { - if (gMain.inBattle) + u8 i; + u8 cannotUse = FALSE; + u16 battleUsage = ItemId_GetBattleUsage(itemId); + u16 hp = GetMonData(mon, MON_DATA_HP); + + // Embargo Check + if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) + || (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO)) { - if ((partyMonIndex == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) - || (partyMonIndex == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO)) - return TRUE; // cannot use on this mon - else - return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, GetPartyIdFromBattleSlot(partyMonIndex), monMoveIndex); + return FALSE; + } + // Items that restore HP (Potions, Sitrus Berry, etc.) + if (battleUsage == EFFECT_ITEM_RESTORE_HP && (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))) + { + cannotUse++; + } + // Items that cure status (Burn Heal, Awakening, etc.) + if (battleUsage == EFFECT_ITEM_CURE_STATUS + && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) + || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) + { + cannotUse++; + } + // Items that restore HP and cure status (Full Restore) + if (battleUsage == EFFECT_ITEM_HEAL_AND_CURE_STATUS + && (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)) + && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) + || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) + { + cannotUse++; + } + // Items that revive a party member + if (battleUsage == EFFECT_ITEM_REVIVE && hp != 0) + { + cannotUse++; + } + // Items that restore PP (Elixir, Ether, Leppa Berry) + if (battleUsage == EFFECT_ITEM_RESTORE_PP) + { + if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP) + { + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i)); + break; + } + if (i == MAX_MON_MOVES) + cannotUse++; + } + else if (GetMonData(mon, MON_DATA_PP1 + gPartyMenu.data1) == CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + gPartyMenu.data1), GetMonData(mon, MON_DATA_PP_BONUSES), gPartyMenu.data1)) + { + cannotUse++; + } + } + return cannotUse; +} + +// Battle scripts called in HandleAction_UseItem +void ItemUseCB_BattleScript(u8 taskId, TaskFunc task) +{ + struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; + if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon)) + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = task; } else - return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, partyMonIndex, monMoveIndex); + { + gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId); + gPartyMenuUseExitCallback = TRUE; + PlaySE(SE_SELECT); + CopyItemName(gSpecialVar_ItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); + DisplayPartyMenuMessage(gStringVar4, TRUE); + ScheduleBgCopyTilemapToVram(2); + RemoveBagItem(gSpecialVar_ItemId, 1); + gTasks[taskId].func = task; + } +} + +void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task) +{ + PlaySE(SE_SELECT); + DisplayPartyMenuStdMessage(PARTY_MSG_RESTORE_WHICH_MOVE); + ShowMoveSelectWindow(gPartyMenu.slotId); + gTasks[taskId].func = Task_HandleWhichMoveInput; } void ItemUseCB_Medicine(u8 taskId, TaskFunc task) @@ -4430,7 +4507,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) if (hp == GetMonData(mon, MON_DATA_MAX_HP)) canHeal = FALSE; } - cannotUse = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0); + cannotUse = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0); } if (cannotUse != FALSE) @@ -4691,7 +4768,7 @@ void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task) u8 effectType = GetItemEffectType(item); u16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP); u16 ev = ItemEffectToMonEv(mon, effectType); - bool8 cannotUseEffect = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0); + bool8 cannotUseEffect = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0); u16 newFriendship = GetMonData(mon, MON_DATA_FRIENDSHIP); u16 newEv = ItemEffectToMonEv(mon, effectType); @@ -4807,25 +4884,19 @@ static void Task_HandleWhichMoveInput(u8 taskId) else { PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]); - SetSelectedMoveForPPItem(taskId); + SetSelectedMoveForItem(taskId); } } } void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task) { - const u8 *effect; - u16 item = gSpecialVar_ItemId; - - if (item == ITEM_ENIGMA_BERRY_E_READER) - effect = gSaveBlock1Ptr->enigmaBerry.itemEffect; - else - effect = gItemEffectTable[item]; + const u8 *effect = GetItemEffect(gSpecialVar_ItemId); if (effect == NULL || !(effect[4] & ITEM4_HEAL_PP_ONE)) { gPartyMenu.data1 = 0; - TryUsePPItem(taskId); + TryUseItemOnMove(taskId); } else { @@ -4836,11 +4907,11 @@ void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task) } } -static void SetSelectedMoveForPPItem(u8 taskId) +static void SetSelectedMoveForItem(u8 taskId) { PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]); gPartyMenu.data1 = Menu_GetCursorPos(); - TryUsePPItem(taskId); + TryUseItemOnMove(taskId); } static void ReturnToUseOnWhichMon(u8 taskId) @@ -4851,34 +4922,61 @@ static void ReturnToUseOnWhichMon(u8 taskId) DisplayPartyMenuStdMessage(PARTY_MSG_USE_ON_WHICH_MON); } -static void TryUsePPItem(u8 taskId) +static void TryUseItemOnMove(u8 taskId) { - u16 move = MOVE_NONE; - s16 *moveSlot = &gPartyMenu.data1; - u16 item = gSpecialVar_ItemId; struct PartyMenu *ptr = &gPartyMenu; - struct Pokemon *mon; - - if (ExecuteTableBasedItemEffect_(ptr->slotId, item, *moveSlot)) + struct Pokemon *mon = &gPlayerParty[ptr->slotId]; + // In battle, set appropriate variables to be used in battle script. + if (gMain.inBattle) { - gPartyMenuUseExitCallback = FALSE; - PlaySE(SE_SELECT); - DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); - ScheduleBgCopyTilemapToVram(2); - gTasks[taskId].func = Task_ClosePartyMenuAfterText; + if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon)) + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + } + else + { + gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId); + gChosenMovePos = ptr->data1; + gPartyMenuUseExitCallback = TRUE; + RemoveBagItem(gSpecialVar_ItemId, 1); + CopyItemName(gSpecialVar_ItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); + DisplayPartyMenuMessage(gStringVar4, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + } } + // Outside of battle, only PP items are used on moves. else { - gPartyMenuUseExitCallback = TRUE; - mon = &gPlayerParty[ptr->slotId]; - PlaySE(SE_USE_ITEM); - RemoveBagItem(item, 1); - move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot); - StringCopy(gStringVar1, gMoveNames[move]); - GetMedicineItemEffectMessage(item); - DisplayPartyMenuMessage(gStringVar4, TRUE); - ScheduleBgCopyTilemapToVram(2); - gTasks[taskId].func = Task_ClosePartyMenuAfterText; + u16 move = MOVE_NONE; + s16 *moveSlot = &gPartyMenu.data1; + u16 item = gSpecialVar_ItemId; + + if (ExecuteTableBasedItemEffect(mon, item, ptr->slotId, *moveSlot)) + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + } + else + { + gPartyMenuUseExitCallback = TRUE; + PlaySE(SE_USE_ITEM); + RemoveBagItem(item, 1); + move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot); + StringCopy(gStringVar1, gMoveNames[move]); + GetMedicineItemEffectMessage(item); + DisplayPartyMenuMessage(gStringVar4, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + } } } @@ -5192,7 +5290,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task) if (sInitialLevel != MAX_LEVEL) { BufferMonStatsToTaskData(mon, arrayPtr); - cannotUseEffect = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, *itemPtr, 0); + cannotUseEffect = ExecuteTableBasedItemEffect(mon, gPartyMenu.slotId, *itemPtr, 0); BufferMonStatsToTaskData(mon, &ptr->data[NUM_STATS]); } else @@ -5459,7 +5557,7 @@ static void UseSacredAsh(u8 taskId) } hp = GetMonData(mon, MON_DATA_HP); - if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0)) + if (ExecuteTableBasedItemEffect(mon, gSpecialVar_ItemId, gPartyMenu.slotId, 0)) { gTasks[taskId].func = Task_SacredAshLoop; return; @@ -5526,7 +5624,7 @@ void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task) { PlaySE(SE_SELECT); gCB2_AfterEvolution = gPartyMenu.exitCallback; - if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0)) + if (ExecuteTableBasedItemEffect(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId, gPartyMenu.slotId, 0)) { gPartyMenuUseExitCallback = FALSE; DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); @@ -5691,16 +5789,18 @@ void TryItemHoldFormChange(struct Pokemon *mon) #undef tAnimWait #undef tNextFunc +const u8* GetItemEffect(u16 item) +{ + if (item == ITEM_ENIGMA_BERRY_E_READER) + return gSaveBlock1Ptr->enigmaBerry.itemEffect; + else + return gItemEffectTable[item]; +} + u8 GetItemEffectType(u16 item) { - const u8 *itemEffect; u32 statusCure; - - // Read the item's effect properties. - if (item == ITEM_ENIGMA_BERRY_E_READER) - itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect; - else - itemEffect = gItemEffectTable[item]; + const u8 *itemEffect = GetItemEffect(item); if (itemEffect == NULL) return ITEM_EFFECT_NONE; diff --git a/src/pokemon.c b/src/pokemon.c index 10a4d0efd3..d985ef95d3 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5736,55 +5736,16 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov // Get item hold effect heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL); if (heldItem == ITEM_ENIGMA_BERRY_E_READER) - { - if (gMain.inBattle) - holdEffect = gEnigmaBerries[gBattlerInMenuId].holdEffect; - else - holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; - } + holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; else - { holdEffect = ItemId_GetHoldEffect(heldItem); - } - - // Get battler id (if relevant) - gPotentialItemEffectBattler = gBattlerInMenuId; - if (gMain.inBattle) - { - gActiveBattler = gBattlerInMenuId; - i = (GetBattlerSide(gActiveBattler) != B_SIDE_PLAYER); - while (i < gBattlersCount) - { - if (gBattlerPartyIndexes[i] == partyIndex) - { - battlerId = i; - break; - } - i += 2; - } - } - else - { - gActiveBattler = 0; - battlerId = MAX_BATTLERS_COUNT; - } // Skip using the item if it won't do anything if (gItemEffectTable[item] == NULL && item != ITEM_ENIGMA_BERRY_E_READER) return TRUE; // Get item effect - if (item == ITEM_ENIGMA_BERRY_E_READER) - { - if (gMain.inBattle) - itemEffect = gEnigmaBerries[gActiveBattler].itemEffect; - else - itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect; - } - else - { - itemEffect = gItemEffectTable[item]; - } + itemEffect = GetItemEffect(item); // Do item effect for (i = 0; i < ITEM_EFFECT_ARG_START; i++) @@ -5793,85 +5754,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov { // Handle ITEM0 effects (infatuation, Dire Hit, X Attack). ITEM0_SACRED_ASH is handled in party_menu.c + // Now handled in item battle scripts. case 0: - // Cure infatuation - if ((itemEffect[i] & ITEM0_INFATUATION) - && gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && (gBattleMons[battlerId].status2 & STATUS2_INFATUATION)) - { - gBattleMons[battlerId].status2 &= ~STATUS2_INFATUATION; - retVal = FALSE; - } - - // Dire Hit - if ((itemEffect[i] & ITEM0_DIRE_HIT) - && !(gBattleMons[gActiveBattler].status2 & STATUS2_FOCUS_ENERGY)) - { - gBattleMons[gActiveBattler].status2 |= STATUS2_FOCUS_ENERGY; - retVal = FALSE; - } break; // Handle ITEM1 effects (in-battle stat boosting effects) + // Now handled in item battle scripts. case 1: - // X Attack - if ((itemEffect[i] & ITEM1_X_ATTACK) - && gBattleMons[gActiveBattler].statStages[STAT_ATK] < MAX_STAT_STAGE) - { - gBattleMons[gActiveBattler].statStages[STAT_ATK] += X_ITEM_STAGES; - if (gBattleMons[gActiveBattler].statStages[STAT_ATK] > MAX_STAT_STAGE) - gBattleMons[gActiveBattler].statStages[STAT_ATK] = MAX_STAT_STAGE; - retVal = FALSE; - } - - // X Defense - if ((itemEffect[i] & ITEM1_X_DEFENSE) - && gBattleMons[gActiveBattler].statStages[STAT_DEF] < MAX_STAT_STAGE) - { - gBattleMons[gActiveBattler].statStages[STAT_DEF] += X_ITEM_STAGES; - if (gBattleMons[gActiveBattler].statStages[STAT_DEF] > MAX_STAT_STAGE) - gBattleMons[gActiveBattler].statStages[STAT_DEF] = MAX_STAT_STAGE; - retVal = FALSE; - } - - // X Speed - if ((itemEffect[i] & ITEM1_X_SPEED) - && gBattleMons[gActiveBattler].statStages[STAT_SPEED] < MAX_STAT_STAGE) - { - gBattleMons[gActiveBattler].statStages[STAT_SPEED] += X_ITEM_STAGES; - if (gBattleMons[gActiveBattler].statStages[STAT_SPEED] > MAX_STAT_STAGE) - gBattleMons[gActiveBattler].statStages[STAT_SPEED] = MAX_STAT_STAGE; - retVal = FALSE; - } - - // X Sp Attack - if ((itemEffect[i] & ITEM1_X_SPATK) - && gBattleMons[gActiveBattler].statStages[STAT_SPATK] < MAX_STAT_STAGE) - { - gBattleMons[gActiveBattler].statStages[STAT_SPATK] += X_ITEM_STAGES; - if (gBattleMons[gActiveBattler].statStages[STAT_SPATK] > MAX_STAT_STAGE) - gBattleMons[gActiveBattler].statStages[STAT_SPATK] = MAX_STAT_STAGE; - retVal = FALSE; - } - - // X Sp Defense - if ((itemEffect[i] & ITEM1_X_SPDEF) - && gBattleMons[gActiveBattler].statStages[STAT_SPDEF] < MAX_STAT_STAGE) - { - gBattleMons[gActiveBattler].statStages[STAT_SPDEF] += X_ITEM_STAGES; - if (gBattleMons[gActiveBattler].statStages[STAT_SPDEF] > MAX_STAT_STAGE) - gBattleMons[gActiveBattler].statStages[STAT_SPDEF] = MAX_STAT_STAGE; - retVal = FALSE; - } - - // X Accuracy - if ((itemEffect[i] & ITEM1_X_ACCURACY) - && gBattleMons[gActiveBattler].statStages[STAT_ACC] < MAX_STAT_STAGE) - { - gBattleMons[gActiveBattler].statStages[STAT_ACC] += X_ITEM_STAGES; - if (gBattleMons[gActiveBattler].statStages[STAT_ACC] > MAX_STAT_STAGE) - gBattleMons[gActiveBattler].statStages[STAT_ACC] = MAX_STAT_STAGE; - retVal = FALSE; - } break; // Formerly used by the item effects of the X Sp. Atk and the X Accuracy case 2: @@ -5879,14 +5768,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov // Handle ITEM3 effects (Guard Spec, Rare Candy, cure status) case 3: - // Guard Spec - if ((itemEffect[i] & ITEM3_GUARD_SPEC) - && gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer == 0) - { - gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer = 5; - retVal = FALSE; - } - // Rare Candy / EXP Candy if ((itemEffect[i] & ITEM3_LEVEL_UP) && GetMonData(mon, MON_DATA_LEVEL, NULL) != MAX_LEVEL) @@ -5915,13 +5796,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov } // Cure status - if ((itemEffect[i] & ITEM3_SLEEP) - && HealStatusConditions(mon, partyIndex, STATUS1_SLEEP, battlerId) == 0) - { - if (battlerId != MAX_BATTLERS_COUNT) - gBattleMons[battlerId].status2 &= ~STATUS2_NIGHTMARE; + if ((itemEffect[i] & ITEM3_SLEEP) && HealStatusConditions(mon, partyIndex, STATUS1_SLEEP, battlerId) == 0) retVal = FALSE; - } if ((itemEffect[i] & ITEM3_POISON) && HealStatusConditions(mon, partyIndex, STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER, battlerId) == 0) retVal = FALSE; if ((itemEffect[i] & ITEM3_BURN) && HealStatusConditions(mon, partyIndex, STATUS1_BURN, battlerId) == 0) @@ -5930,12 +5806,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov retVal = FALSE; if ((itemEffect[i] & ITEM3_PARALYSIS) && HealStatusConditions(mon, partyIndex, STATUS1_PARALYSIS, battlerId) == 0) retVal = FALSE; - if ((itemEffect[i] & ITEM3_CONFUSION) // heal confusion - && gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && (gBattleMons[battlerId].status2 & STATUS2_CONFUSION)) - { - gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; - retVal = FALSE; - } break; // Handle ITEM4 effects (Change HP/Atk EVs, HP heal, PP heal, PP up, Revive, and evolution stones) @@ -6022,38 +5892,12 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov break; case 2: // ITEM4_HEAL_HP - // If Revive, update number of times revive has been used - if (effectFlags & (ITEM4_REVIVE >> 2)) + // Check use validity. + if ((effectFlags & (ITEM4_REVIVE >> 2) && GetMonData(mon, MON_DATA_HP, NULL) != 0) + || (!(effectFlags & (ITEM4_REVIVE >> 2)) && GetMonData(mon, MON_DATA_HP, NULL) == 0)) { - if (GetMonData(mon, MON_DATA_HP, NULL) != 0) - { - itemEffectParam++; - break; - } - if (gMain.inBattle) - { - if (battlerId != MAX_BATTLERS_COUNT) - { - gAbsentBattlerFlags &= ~gBitTable[battlerId]; - CopyPlayerPartyMonToBattleData(battlerId, GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[battlerId])); - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255) - gBattleResults.numRevivesUsed++; - } - else - { - gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2]; - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255) - gBattleResults.numRevivesUsed++; - } - } - } - else - { - if (GetMonData(mon, MON_DATA_HP, NULL) == 0) - { - itemEffectParam++; - break; - } + itemEffectParam++; + break; } // Get amount of HP to restore @@ -6081,35 +5925,11 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov // Only restore HP if not at max health if (GetMonData(mon, MON_DATA_MAX_HP, NULL) != GetMonData(mon, MON_DATA_HP, NULL)) { - if (!usedByAI) - { - // 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); - SetMonData(mon, MON_DATA_HP, &dataUnsigned); - - // Update battler (if applicable) - if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT) - { - gBattleMons[battlerId].hp = dataUnsigned; - if (!(effectFlags & (ITEM4_REVIVE >> 2)) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) - { - if (gBattleResults.numHealingItemsUsed < 255) - gBattleResults.numHealingItemsUsed++; - - temp2 = gActiveBattler; - gActiveBattler = battlerId; - BtlController_EmitGetMonData(BUFFER_A, REQUEST_ALL_BATTLE, 0); - MarkBattlerForControllerExec(gActiveBattler); - gActiveBattler = temp2; - } - } - } - else - { - gBattleMoveDamage = -dataUnsigned; - } + // 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); + SetMonData(mon, MON_DATA_HP, &dataUnsigned); retVal = FALSE; } effectFlags &= ~(ITEM4_REVIVE >> 2); @@ -6134,11 +5954,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), temp2); } SetMonData(mon, MON_DATA_PP1 + temp2, &dataUnsigned); - - // Heal battler PP too (if applicable) - if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && MOVE_IS_PERMANENT(battlerId, temp2)) - gBattleMons[battlerId].pp[temp2] = dataUnsigned; - retVal = FALSE; } } @@ -6160,11 +5975,6 @@ 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 && MOVE_IS_PERMANENT(battlerId, moveIndex)) - gBattleMons[battlerId].pp[moveIndex] = dataUnsigned; - retVal = FALSE; } } diff --git a/test/item_effect_increase_stat.c b/test/item_effect_increase_stat.c new file mode 100644 index 0000000000..70c89bdd4e --- /dev/null +++ b/test/item_effect_increase_stat.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("X-Attack sharply raises battler's attack stat", s16 damage) +{ + u16 useItem; + PARAMETRIZE { useItem = FALSE; } + PARAMETRIZE { useItem = TRUE; } + GIVEN { + ASSUME(gItems[ITEM_X_ATTACK].battleUsage == EFFECT_ITEM_INCREASE_STAT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (useItem) TURN { USE_ITEM(player, ITEM_X_ATTACK); } + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + MESSAGE("Wobbuffet used Tackle!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_X_ITEMS_BUFF >= GEN_7) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} diff --git a/test/item_effect_restore_hp.c b/test/item_effect_restore_hp.c new file mode 100644 index 0000000000..971ec2400b --- /dev/null +++ b/test/item_effect_restore_hp.c @@ -0,0 +1,37 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Potion restores a battler's HP by 20") +{ + s16 damage; + GIVEN { + ASSUME(gItems[ITEM_POTION].battleUsage == EFFECT_ITEM_RESTORE_HP); + PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { USE_ITEM(player, ITEM_POTION, partyIndex: 0); } + } SCENE { + HP_BAR(player, captureDamage: &damage); + } FINALLY { + EXPECT_EQ(damage, -20); + } +} + +SINGLE_BATTLE_TEST("Sitrus Berry restores a battler's HP") +{ + s16 damage; + GIVEN { + ASSUME(gItems[ITEM_SITRUS_BERRY].battleUsage == EFFECT_ITEM_RESTORE_HP); + PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { USE_ITEM(player, ITEM_SITRUS_BERRY, partyIndex: 0); } + } SCENE { + HP_BAR(player, captureDamage: &damage); + } FINALLY { + if (I_SITRUS_BERRY_HEAL >= GEN_4) + EXPECT_EQ(damage, -25); + else + EXPECT_EQ(damage, -30); + } +} diff --git a/test/item_effect_restore_pp.c b/test/item_effect_restore_pp.c new file mode 100644 index 0000000000..234d4ae4e5 --- /dev/null +++ b/test/item_effect_restore_pp.c @@ -0,0 +1,19 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Ether restores the PP of one of a battler's moves") +{ + GIVEN { + ASSUME(gItems[ITEM_ETHER].battleUsage == EFFECT_ITEM_RESTORE_PP); + ASSUME(gItems[ITEM_ETHER].type == ITEM_USE_PARTY_MENU_MOVES); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_CONFUSION); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { MOVE(player, MOVE_CONFUSION); } + TURN { USE_ITEM(player, ITEM_ETHER, partyIndex: 0, move: MOVE_TACKLE); } + } FINALLY { + EXPECT_EQ(player->pp[0], 35); + EXPECT_EQ(player->pp[1], 24); + } +} diff --git a/test/test_battle.h b/test/test_battle.h index 60d0dc33cc..967bb661dd 100644 --- a/test/test_battle.h +++ b/test/test_battle.h @@ -333,6 +333,13 @@ * Used when the battler chooses to switch to another Pokémon but not * via Switch, e.g. after fainting or due to a U-turn. * SEND_OUT(player, 1); + * + * USE_ITEM(battler, itemId, [partyIndex:], [move:]) + * Used when the battler chooses to use an item from the Bag. The item + * ID must be specified, and party index and move slot if applicable, e.g: + * USE_ITEM(player, ITEM_X_ATTACK); + * USE_ITEM(player, ITEM_POTION, partyIndex: 0); + * USE_ITEM(player, ITEM_LEPPA_BERRY, partyIndex: 0, move: MOVE_TACKLE); * * SCENE * Contains an abridged description of the UI during the THEN. The order @@ -765,7 +772,7 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING }; #define SWITCH(battler, partyIndex) Switch(__LINE__, battler, partyIndex) #define SKIP_TURN(battler) SkipTurn(__LINE__, battler) #define SEND_OUT(battler, partyIndex) SendOut(__LINE__, battler, partyIndex) - +#define USE_ITEM(battler, ...) UseItem(__LINE__, battler, (struct ItemContext) { APPEND_TRUE(__VA_ARGS__) }) #define WITH_RNG(tag, value) rng: ((struct TurnRNG) { tag, value }) struct MoveContext @@ -791,13 +798,23 @@ struct MoveContext bool8 explicitRNG; }; +struct ItemContext +{ + u16 itemId; + u16 explicitItemId:1; + u16 partyIndex; + u16 explicitPartyIndex:1; + u16 move; + u16 explicitMove:1; +}; + void OpenTurn(u32 sourceLine); void CloseTurn(u32 sourceLine); void Move(u32 sourceLine, struct BattlePokemon *, struct MoveContext); void ForcedMove(u32 sourceLine, struct BattlePokemon *); void Switch(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); void SkipTurn(u32 sourceLine, struct BattlePokemon *); - +void UseItem(u32 sourceLine, struct BattlePokemon *, struct ItemContext); void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); /* Scene */ diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 1b03341a45..365120f137 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -3,6 +3,7 @@ #include "battle_anim.h" #include "battle_controllers.h" #include "characters.h" +#include "item_menu.h" #include "main.h" #include "malloc.h" #include "random.h" @@ -1251,6 +1252,9 @@ void BattleTest_CheckBattleRecordActionType(u32 battlerId, u32 recordIndex, u32 case B_ACTION_SWITCH: actualMacro = "SWITCH"; break; + case B_ACTION_USE_ITEM: + actualMacro = "USE_ITEM"; + break; } break; case RECORDED_PARTY_INDEX: @@ -1508,6 +1512,40 @@ void SendOut(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex) DATA.currentMonIndexes[battlerId] = partyIndex; } +void UseItem(u32 sourceLine, struct BattlePokemon *battler, struct ItemContext ctx) +{ + s32 i; + s32 battlerId = battler - gBattleMons; + bool32 requirePartyIndex = ItemId_GetType(ctx.itemId) == ITEM_USE_PARTY_MENU || ItemId_GetType(ctx.itemId) == ITEM_USE_PARTY_MENU_MOVES; + // Check general bad use. + INVALID_IF(DATA.turnState == TURN_CLOSED, "USE_ITEM outside TURN"); + INVALID_IF(DATA.actionBattlers & (1 << battlerId), "Multiple battler actions"); + INVALID_IF(ctx.itemId >= ITEMS_COUNT, "Illegal item: %d", ctx.itemId); + // Check party menu items. + INVALID_IF(requirePartyIndex && !ctx.explicitPartyIndex, "%S requires explicit party index", ItemId_GetName(ctx.itemId)); + INVALID_IF(requirePartyIndex && ctx.partyIndex >= ((battlerId & BIT_SIDE) == B_SIDE_PLAYER ? DATA.playerPartySize : DATA.opponentPartySize), \ + "USE_ITEM to invalid party index"); + // Check move slot items. + if (ItemId_GetType(ctx.itemId) == ITEM_USE_PARTY_MENU_MOVES) + { + INVALID_IF(!ctx.explicitMove, "%S requires an explicit move", ItemId_GetName(ctx.itemId)); + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (GetMonData(CurrentMon(battlerId), MON_DATA_MOVE1 + i, NULL) == ctx.move) + break; + } + INVALID_IF(i == MAX_MON_MOVES, "USE_ITEM on invalid move: %d", ctx.move); + } + PushBattlerAction(sourceLine, battlerId, RECORDED_ACTION_TYPE, B_ACTION_USE_ITEM); + PushBattlerAction(sourceLine, battlerId, RECORDED_ITEM_ID, (ctx.itemId >> 8) & 0xFF); + PushBattlerAction(sourceLine, battlerId, RECORDED_ITEM_ID, ctx.itemId & 0xFF); + if (ctx.explicitPartyIndex) + gBattleStruct->itemPartyIndex[battlerId] = ctx.partyIndex; + if (ctx.explicitMove) + gBattleStruct->itemPartyIndex[battlerId] = i; + DATA.actionBattlers |= 1 << battlerId; +} + static const char *const sQueueGroupTypeMacros[] = { [QUEUE_GROUP_NONE] = NULL, From dacd0785db12a41df50a0b12989d58c54ae41f3b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 14 Apr 2023 15:17:19 -0400 Subject: [PATCH 080/131] Fixed Mega Evolution script name --- data/battle_scripts_1.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ebb23d2014..30a80bf193 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7872,7 +7872,7 @@ BattleScript_FocusPunchSetUp:: BattleScript_MegaEvolution:: printstring STRINGID_MEGAEVOREACTING -BattleScript_MegaEvolutionAfeterString: +BattleScript_MegaEvolutionAfterString: waitmessage B_WAIT_TIME_LONG setbyte gIsCriticalHit, 0 handlemegaevo BS_ATTACKER, 0 @@ -7886,7 +7886,7 @@ BattleScript_MegaEvolutionAfeterString: BattleScript_WishMegaEvolution:: printstring STRINGID_FERVENTWISHREACHED - goto BattleScript_MegaEvolutionAfeterString + goto BattleScript_MegaEvolutionAfterString BattleScript_PrimalReversion:: printstring STRINGID_EMPTYSTRING3 From 82dc1e3e93810f74f7abd377f76c2f4ceab70976 Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Sat, 15 Apr 2023 09:27:28 -0700 Subject: [PATCH 081/131] fixed dupe strings in battle item use --- data/battle_scripts_2.s | 12 ++++++------ src/item_use.c | 5 +++-- src/party_menu.c | 8 +------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index dee482d1d3..71d88ae84b 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -49,14 +49,13 @@ BattleScript_UseItemMessage: BattleScript_ItemRestoreHP:: call BattleScript_UseItemMessage itemrestorehp - printstring STRINGID_ITEMRESTOREDSPECIESHEALTH - waitmessage B_WAIT_TIME_LONG jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_ItemRestoreHP_SendOutRevivedBattler bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER - updatestatusicon BS_ATTACKER + printstring STRINGID_ITEMRESTOREDSPECIESHEALTH + waitmessage B_WAIT_TIME_LONG end BattleScript_ItemRestoreHP_SendOutRevivedBattler: @@ -68,22 +67,22 @@ BattleScript_ItemRestoreHP_SendOutRevivedBattler: BattleScript_ItemCureStatus:: call BattleScript_UseItemMessage itemcurestatus + updatestatusicon BS_ATTACKER printstring STRINGID_ITEMCUREDSPECIESSTATUS waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER end BattleScript_ItemHealAndCureStatus:: call BattleScript_UseItemMessage itemrestorehp curestatus BS_ATTACKER - printstring STRINGID_ITEMRESTOREDSPECIESHEALTH - waitmessage B_WAIT_TIME_LONG bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER updatestatusicon BS_ATTACKER + printstring STRINGID_ITEMRESTOREDSPECIESHEALTH + waitmessage B_WAIT_TIME_LONG end BattleScript_ItemIncreaseStat:: @@ -256,3 +255,4 @@ BattleScript_TrainerBSlideMsgRet:: BattleScript_TrainerBSlideMsgEnd2:: call BattleScript_TrainerBSlideMsgRet end2 + end2 diff --git a/src/item_use.c b/src/item_use.c index 8bcadfb2eb..26b48ac80b 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1229,10 +1229,11 @@ void ItemUseInBattle_BagMenu(u8 taskId) { PlaySE(SE_SELECT); RemoveUsedItem(); + ScheduleBgCopyTilemapToVram(2); if (!InBattlePyramid()) - DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, Task_FadeAndCloseBagMenu); + gTasks[taskId].func = Task_FadeAndCloseBagMenu; else - DisplayItemMessageInBattlePyramid(taskId, gStringVar4, CloseBattlePyramidBag); + gTasks[taskId].func = CloseBattlePyramidBag; } } diff --git a/src/party_menu.c b/src/party_menu.c index dd46b10634..95d64e5463 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4470,11 +4470,8 @@ void ItemUseCB_BattleScript(u8 taskId, TaskFunc task) gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId); gPartyMenuUseExitCallback = TRUE; PlaySE(SE_SELECT); - CopyItemName(gSpecialVar_ItemId, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); - DisplayPartyMenuMessage(gStringVar4, TRUE); - ScheduleBgCopyTilemapToVram(2); RemoveBagItem(gSpecialVar_ItemId, 1); + ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = task; } } @@ -4943,9 +4940,6 @@ static void TryUseItemOnMove(u8 taskId) gChosenMovePos = ptr->data1; gPartyMenuUseExitCallback = TRUE; RemoveBagItem(gSpecialVar_ItemId, 1); - CopyItemName(gSpecialVar_ItemId, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); - DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = Task_ClosePartyMenuAfterText; } From aefe5825964e5cd4d10dae3bad63a4bf5a33b4b2 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Sat, 15 Apr 2023 00:52:14 +0100 Subject: [PATCH 082/131] GetSideParty/GetBattlerParty Inline GetBattlerPartyData into its callers because its name is confusing and we couldn't think of a better one. This seems to fix a bug in one place where GetBattlerPartyData was being used as if it had GetBattlerParty semantics. --- include/battle.h | 11 ++++++++ include/battle_util.h | 1 - src/battle_ai_util.c | 2 +- src/battle_anim_new.c | 3 -- src/battle_main.c | 7 +++-- src/battle_script_commands.c | 53 +++++++++------------------------- src/battle_util.c | 55 ++++++++---------------------------- 7 files changed, 42 insertions(+), 90 deletions(-) diff --git a/include/battle.h b/include/battle.h index 46975bec3c..afa02a8f21 100644 --- a/include/battle.h +++ b/include/battle.h @@ -719,6 +719,17 @@ struct BattleStruct #define SET_STATCHANGER(statId, stage, goesDown)(gBattleScripting.statChanger = (statId) + ((stage) << 3) + (goesDown << 7)) #define SET_STATCHANGER2(dst, statId, stage, goesDown)(dst = (statId) + ((stage) << 3) + (goesDown << 7)) +static inline struct Pokemon *GetSideParty(u32 side) +{ + return side == B_SIDE_PLAYER ? gPlayerParty : gEnemyParty; +} + +static inline struct Pokemon *GetBattlerParty(u32 battlerId) +{ + extern u8 GetBattlerSide(u8 battler); + return GetSideParty(GetBattlerSide(battlerId)); +} + // NOTE: The members of this struct have hard-coded offsets // in include/constants/battle_script_commands.h struct BattleScripting diff --git a/include/battle_util.h b/include/battle_util.h index 0661081e43..3086394877 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -188,7 +188,6 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId); bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); u8 GetBattleMoveSplit(u32 moveId); bool32 TestMoveFlags(u16 move, u32 flag); -struct Pokemon *GetBattlerPartyData(u8 battlerId); bool32 CanFling(u8 battlerId); bool32 IsTelekinesisBannedSpecies(u16 species); bool32 IsHealBlockPreventingMove(u32 battler, u32 move); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 05e7aec58f..1128f385bb 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3420,7 +3420,7 @@ bool32 IsPartyFullyHealedExceptBattler(u8 battlerId) bool32 PartyHasMoveSplit(u8 battlerId, u8 split) { u8 firstId, lastId; - struct Pokemon* party = GetBattlerPartyData(battlerId); + struct Pokemon *party = GetBattlerParty(battlerId); u32 i, j; for (i = 0; i < PARTY_SIZE; i++) diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index b3502fcb9e..715e5b3e26 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -7897,9 +7897,6 @@ void AnimTask_TerrainPulse(u8 taskId) void AnimTask_AffectionHangedOn(u8 taskId) { - int side = GetBattlerSide(gBattleAnimTarget); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - gBattleAnimArgs[0] = GetBattlerFriendshipScore(gBattleAnimTarget); DestroyAnimVisualTask(taskId); } diff --git a/src/battle_main.c b/src/battle_main.c index a5a9b5bbf6..0babba241a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3799,7 +3799,9 @@ static void TryDoEventsBeforeFirstTurn(void) { for (i = 0; i < gBattlersCount; i++) { - if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE || GetMonData(GetBattlerPartyData(i), MON_DATA_IS_EGG)) + struct Pokemon *party = GetBattlerParty(i); + struct Pokemon *mon = &party[gBattlerPartyIndexes[i]]; + if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG)) gAbsentBattlerFlags |= gBitTable[i]; } } @@ -5033,7 +5035,8 @@ static void CheckMegaEvolutionBeforeTurn(void) if (gBattleStruct->mega.toEvolve & gBitTable[gActiveBattler] && !(gProtectStructs[gActiveBattler].noValidMoves)) { - struct Pokemon *mon = GetBattlerPartyData(gActiveBattler); + struct Pokemon *party = GetBattlerParty(gActiveBattler); + struct Pokemon *mon = &party[gBattlerPartyIndexes[gActiveBattler]]; gBattleStruct->mega.toEvolve &= ~(gBitTable[gActiveBattler]); gLastUsedItem = gBattleMons[gActiveBattler].item; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d313697b0a..2a7e2916d7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6468,10 +6468,7 @@ bool32 CanBattlerSwitch(u32 battlerId) } else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { - if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT) - party = gEnemyParty; - else - party = gPlayerParty; + party = GetBattlerParty(battlerId); lastMonId = 0; if (battlerId & 2) @@ -6512,10 +6509,7 @@ bool32 CanBattlerSwitch(u32 battlerId) } else { - if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT) - party = gEnemyParty; - else - party = gPlayerParty; + party = GetBattlerParty(battlerId); lastMonId = 0; if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(battlerId)) == TRUE) @@ -7669,10 +7663,7 @@ static void Cmd_drawpartystatussummary(void) gActiveBattler = GetBattlerForBattleScript(cmd->battler); - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; + party = GetBattlerParty(gActiveBattler); for (i = 0; i < PARTY_SIZE; i++) { @@ -8746,7 +8737,8 @@ static bool32 CourtChangeSwapSideStatuses(void) static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega) { - struct Pokemon *mon = GetBattlerPartyData(battlerId); + struct Pokemon *party = GetBattlerParty(battlerId); + struct Pokemon *mon = &party[gBattlerPartyIndexes[battlerId]]; u32 position = GetBattlerPosition(battlerId); u32 side = GET_BATTLER_SIDE(battlerId); @@ -8814,8 +8806,7 @@ static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega) static bool32 CanTeleport(u8 battlerId) { - u8 side = GetBattlerSide(battlerId); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetBattlerParty(battlerId); u32 species, count, i; for (i = 0; i < PARTY_SIZE; i++) @@ -11242,7 +11233,7 @@ static void Cmd_various(void) // Battler selected! Revive and go to next instruction. if (gSelectedMonPartyId != PARTY_SIZE) { - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetSideParty(side); u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2; BtlController_EmitSetMonData(BUFFER_A, REQUEST_HP_BATTLE, gBitTable[gSelectedMonPartyId], sizeof(hp), &hp); @@ -12326,10 +12317,7 @@ static void Cmd_forcerandomswitch(void) || redCardForcedSwitch ) { - if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; + party = GetBattlerParty(gBattlerTarget); if (BATTLE_TWO_VS_ONE_OPPONENT && GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT) { @@ -13528,16 +13516,11 @@ static void Cmd_healpartystatus(void) if (gCurrentMove == MOVE_HEAL_BELL) { - struct Pokemon *party; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); s32 i; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL; - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF) { gBattleMons[gBattlerAttacker].status1 = 0; @@ -14165,12 +14148,7 @@ static void Cmd_trydobeatup(void) gBattleStruct->beatUpSlot++; gBattlescriptCurrInstr = cmd->nextInstr; #else - struct Pokemon *party; - - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); if (gBattleMons[gBattlerTarget].hp == 0) { @@ -14864,10 +14842,7 @@ static void Cmd_assistattackselect(void) if (validMoves != NULL) { - if (GET_BATTLER_SIDE(gBattlerAttacker) != B_SIDE_PLAYER) - party = gEnemyParty; - else - party = gPlayerParty; + party = GetBattlerParty(gBattlerAttacker); for (monId = 0; monId < PARTY_SIZE; monId++) { @@ -16396,7 +16371,7 @@ u8 GetFirstFaintedPartyIndex(u8 battlerId) u32 i; u32 start = 0; u32 end = PARTY_SIZE; - struct Pokemon *party = (GetBattlerSide(battlerId) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetBattlerParty(battlerId); // Check whether partner is separate trainer. if ((GetBattlerSide(battlerId) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) @@ -16435,7 +16410,7 @@ void BS_ItemRestoreHP(void) { u32 battlerId = MAX_BATTLERS_COUNT; u32 healParam = GetItemEffect(gLastUsedItem)[6]; u32 side = GetBattlerSide(gBattlerAttacker); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetSideParty(side); u16 hp = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP); u16 maxHP = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_MAX_HP); gBattleCommunication[MULTIUSE_STATE] = 0; @@ -16493,7 +16468,7 @@ void BS_ItemRestoreHP(void) { void BS_ItemCureStatus(void) { NATIVE_ARGS(); - struct Pokemon *party = (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); // Heal Status1 conditions. HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], gBattleStruct->itemPartyIndex[gBattlerAttacker], GetItemStatus1Mask(gLastUsedItem), gBattlerAttacker); diff --git a/src/battle_util.c b/src/battle_util.c index ac274bf0f8..0a4fd61a17 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -225,14 +225,9 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] = static u8 CalcBeatUpPower(void) { - struct Pokemon *party; u8 basePower; u16 species; - - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); // Party slot is incremented by the battle script for Beat Up after this damage calculation species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES); @@ -1988,7 +1983,7 @@ u8 GetImprisonedMovesCount(u8 battlerId, u16 move) u32 GetBattlerFriendshipScore(u8 battlerId) { u8 side = GetBattlerSide(battlerId); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetSideParty(side); u16 species = GetMonData(&party[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); if (side != B_SIDE_PLAYER) @@ -3747,14 +3742,9 @@ u8 AtkCanceller_UnableToUseMove(void) #if B_BEAT_UP >= GEN_5 else if (gBattleMoves[gCurrentMove].effect == EFFECT_BEAT_UP) { - struct Pokemon* party; + struct Pokemon* party = GetBattlerParty(gBattlerAttacker); int i; - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; - for (i = 0; i < PARTY_SIZE; i++) { if (GetMonData(&party[i], MON_DATA_HP) @@ -3851,10 +3841,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) } else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { - if (GetBattlerSide(battler) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; + party = GetBattlerParty(battler); playerId = ((battler & BIT_FLANK) / 2); for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++) @@ -3888,12 +3875,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) else { flankId = GetBattlerMultiplayerId(battler); - - if (GetBattlerSide(battler) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; - + party = GetBattlerParty(battler); playerId = GetLinkTrainerFlankId(flankId); } @@ -4062,7 +4044,7 @@ static void ShouldChangeFormInWeather(u8 battler) { int i; int side = GetBattlerSide(battler); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetSideParty(side); for (i = 0; i < PARTY_SIZE; i++) { @@ -4253,8 +4235,7 @@ bool8 ChangeTypeBasedOnTerrain(u8 battlerId) static u16 GetSupremeOverlordModifier(u8 battlerId) { u32 i; - u8 side = GetBattlerSide(battlerId); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetBattlerParty(battlerId); u16 modifier = UQ_4_12(1.0); bool8 appliedFirstBoost = FALSE; @@ -7253,11 +7234,11 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) case HOLD_EFFECT_RESTORE_PP: if (!moveTurn) { - struct Pokemon *mon; + struct Pokemon *party = GetBattlerParty(battlerId); + struct Pokemon *mon = &party[gBattlerPartyIndexes[battlerId]]; u8 ppBonuses; u16 move; - mon = GetBattlerPartyData(battlerId); for (i = 0; i < MAX_MON_MOVES; i++) { move = GetMonData(mon, MON_DATA_MOVE1 + i); @@ -10112,7 +10093,7 @@ void UndoMegaEvolution(u32 monId) void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) { u32 i, currSpecies, targetSpecies; - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetSideParty(side); static const u16 species[][3] = { // Changed Form ID Default Form ID Should change on switch @@ -10247,10 +10228,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId) if (GetMonAbility(mon) != ABILITY_ILLUSION) return FALSE; - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) - party = gPlayerParty; - else - party = gEnemyParty; + party = GetBattlerParty(battlerId); if (IsBattlerAlive(BATTLE_PARTNER(battlerId))) partnerMon = &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]]; @@ -10375,17 +10353,6 @@ bool32 TestMoveFlags(u16 move, u32 flag) return FALSE; } -struct Pokemon *GetBattlerPartyData(u8 battlerId) -{ - struct Pokemon *mon; - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) - mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]]; - else - mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]]; - - return mon; -} - static u8 GetFlingPowerFromItemId(u16 itemId) { if (itemId >= ITEM_TM01 && itemId <= ITEM_HM08) From d3a090020bb062d88c0c162bc62292e4debfcd95 Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Sat, 15 Apr 2023 15:30:07 -0700 Subject: [PATCH 083/131] added code review --- data/battle_scripts_2.s | 1 - src/battle_message.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 71d88ae84b..9ffad7d843 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -255,4 +255,3 @@ BattleScript_TrainerBSlideMsgRet:: BattleScript_TrainerBSlideMsgEnd2:: call BattleScript_TrainerBSlideMsgRet end2 - end2 diff --git a/src/battle_message.c b/src/battle_message.c index 7d10b19f11..640e7900da 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -465,7 +465,7 @@ const u8 *const gPokeblockWasTooXStringTable[FLAVOR_COUNT] = [FLAVOR_SOUR] = sText_PokeblockWasTooSour }; -static const u8 sText_PlayerUsedItem[] = _("{B_PLAYER_NAME} used\n{B_LAST_ITEM}!"); +static const u8 sText_PlayerUsedItem[] = _("You used\n{B_LAST_ITEM}!"); static const u8 sText_WallyUsedItem[] = _("WALLY used\n{B_LAST_ITEM}!"); static const u8 sText_Trainer1UsedItem[] = _("{B_ATK_TRAINER_CLASS} {B_ATK_TRAINER_NAME}\nused {B_LAST_ITEM}!"); static const u8 sText_TrainerBlockedBall[] = _("The TRAINER blocked the BALL!"); @@ -783,9 +783,9 @@ static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell static const u8 sText_CouldntFullyProtect[] = _("{B_DEF_NAME_WITH_PREFIX} couldn't fully protect\nitself and got hurt!"); static const u8 sText_StockpiledEffectWoreOff[] = _("{B_ATK_NAME_WITH_PREFIX}'s stockpiled\neffect wore off!"); static const u8 sText_PkmnRevivedReadyToFight[] = _("{B_BUFF1} was revived and\nis ready to fight again!"); -static const u8 sText_ItemRestoredSpeciesHealth[] = _("{B_LAST_ITEM} restored\n{B_BUFF1}'s health!"); -static const u8 sText_ItemCuredSpeciesStatus[] = _("{B_LAST_ITEM} cured\n{B_BUFF1}'s status!"); -static const u8 sText_ItemRestoredSpeciesPP[] = _("{B_LAST_ITEM} restored\n{B_BUFF1}'s PP!"); +static const u8 sText_ItemRestoredSpeciesHealth[] = _("{B_BUFF1} had its\nHP restored!"); +static const u8 sText_ItemCuredSpeciesStatus[] = _("{B_BUFF1} had\nits status healed!"); +static const u8 sText_ItemRestoredSpeciesPP[] = _("{B_BUFF1} had its\nPP restored!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { From 7d4807d956c391e480c2be39afbeb4117ba431da Mon Sep 17 00:00:00 2001 From: CallmeEchoo <65783283+CallmeEchoo@users.noreply.github.com> Date: Sun, 16 Apr 2023 13:11:49 +0200 Subject: [PATCH 084/131] fix nightmare status only being healed in doubles this came up in a conversation on discord. its not tested. --- src/battle_script_commands.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d313697b0a..dcfaf0da4d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16506,10 +16506,11 @@ void BS_ItemCureStatus(void) { { gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker); - if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; } + if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); gBattlescriptCurrInstr = cmd->nextInstr; } From 73ba8264e0f6d9a4e98f9ef3ded2c527c3f6ab5d Mon Sep 17 00:00:00 2001 From: Jaizu Date: Sun, 16 Apr 2023 21:34:07 +0200 Subject: [PATCH 085/131] Fix Rare Candies --- src/party_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/party_menu.c b/src/party_menu.c index dd46b10634..a7ab305450 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4948,7 +4948,7 @@ static void TryUseItemOnMove(u8 taskId) DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = Task_ClosePartyMenuAfterText; - } + } } // Outside of battle, only PP items are used on moves. else @@ -5290,7 +5290,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task) if (sInitialLevel != MAX_LEVEL) { BufferMonStatsToTaskData(mon, arrayPtr); - cannotUseEffect = ExecuteTableBasedItemEffect(mon, gPartyMenu.slotId, *itemPtr, 0); + cannotUseEffect = ExecuteTableBasedItemEffect(mon, *itemPtr, gPartyMenu.slotId, 0); BufferMonStatsToTaskData(mon, &ptr->data[NUM_STATS]); } else From efd7465c12a2ab52335bb0a90f1c6325f5af1aba Mon Sep 17 00:00:00 2001 From: CallmeEchoo Date: Mon, 17 Apr 2023 13:34:11 +0200 Subject: [PATCH 086/131] fix gBattleMons using party indices instead of battle indices --- src/battle_script_commands.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index dcfaf0da4d..4e1494ce38 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16500,7 +16500,9 @@ void BS_ItemCureStatus(void) { // Heal Status2 conditions if battler is active. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - gBattleMons[gBattleStruct->itemPartyIndex[gBattlerAttacker]].status2 &= ~GetItemStatus2Mask(gLastUsedItem); + { + gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); + } else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) { From 0531ab5d87ecdc959a331535719fabe180cddd81 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 17 Apr 2023 18:47:54 +0200 Subject: [PATCH 087/131] Fix Ability PopUp freeze --- data/battle_scripts_1.s | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4848b73227..91bc37f76f 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5612,7 +5612,7 @@ BattleScript_EffectStockpileSpDef:: BattleScript_EffectStockpileEnd: stockpile 1 goto BattleScript_MoveEnd - + BattleScript_MoveEffectStockpileWoreOff:: .if B_STOCKPILE_RAISES_DEFS >= GEN_4 dostockpilestatchangeswearoff BS_ATTACKER, BattleScript_StockpileStatChangeDown @@ -5620,7 +5620,7 @@ BattleScript_MoveEffectStockpileWoreOff:: waitmessage B_WAIT_TIME_SHORT .endif return - + BattleScript_StockpileStatChangeDown: statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_StockpileStatChangeDown_Ret setgraphicalstatchangevalues @@ -6943,7 +6943,7 @@ BattleScript_MagicRoomEnds:: printstring STRINGID_MAGICROOMENDS waitmessage B_WAIT_TIME_LONG end2 - + BattleScript_GrassyTerrainEnds: setbyte cMULTISTRING_CHOOSER, B_MSG_TERRAINENDS_GRASS BattleScript_TerrainEnds_Ret:: @@ -6951,7 +6951,7 @@ BattleScript_TerrainEnds_Ret:: waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG return - + BattleScript_TerrainEnds:: call BattleScript_TerrainEnds_Ret end2 @@ -7496,7 +7496,7 @@ BattleScript_StealthRockFree:: printstring STRINGID_PKMNBLEWAWAYSTEALTHROCK waitmessage B_WAIT_TIME_LONG return - + BattleScript_SpikesDefog:: printstring STRINGID_SPIKESDISAPPEAREDFROMTEAM waitmessage B_WAIT_TIME_LONG @@ -9181,6 +9181,7 @@ BattleScript_WanderingSpiritActivates:: destroyabilitypopup pause 40 + copybyte gBattlerAbility, gBattlerAttacker setbyte sFIXED_ABILITY_POPUP, TRUE copyhword sABILITY_OVERWRITE, gLastUsedAbility showabilitypopup BS_ATTACKER From 60c88d8fccb0c0fa3b1a44273b7210f228412a26 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 17 Apr 2023 19:12:39 +0200 Subject: [PATCH 088/131] Update data/battle_scripts_1.s Co-authored-by: Eduardo Quezada D'Ottone --- data/battle_scripts_1.s | 1 - 1 file changed, 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 91bc37f76f..0be8934127 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -9180,7 +9180,6 @@ BattleScript_WanderingSpiritActivates:: pause 20 destroyabilitypopup pause 40 - copybyte gBattlerAbility, gBattlerAttacker setbyte sFIXED_ABILITY_POPUP, TRUE copyhword sABILITY_OVERWRITE, gLastUsedAbility From 9d93af2261101aee307ca6cc82c4c04dec36ab74 Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:28:02 -0400 Subject: [PATCH 089/131] Fixed Budew evolution method (#2928) --- src/data/pokemon/evolution.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/pokemon/evolution.h b/src/data/pokemon/evolution.h index 6ec3c0a14c..f222148178 100644 --- a/src/data/pokemon/evolution.h +++ b/src/data/pokemon/evolution.h @@ -316,7 +316,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_KRICKETOT] = {{EVO_LEVEL, 10, SPECIES_KRICKETUNE}}, [SPECIES_SHINX] = {{EVO_LEVEL, 15, SPECIES_LUXIO}}, [SPECIES_LUXIO] = {{EVO_LEVEL, 30, SPECIES_LUXRAY}}, - [SPECIES_BUDEW] = {{EVO_FRIENDSHIP, 0, SPECIES_ROSELIA}}, + [SPECIES_BUDEW] = {{EVO_FRIENDSHIP_DAY, 0, SPECIES_ROSELIA}}, [SPECIES_CRANIDOS] = {{EVO_LEVEL, 30, SPECIES_RAMPARDOS}}, [SPECIES_SHIELDON] = {{EVO_LEVEL, 30, SPECIES_BASTIODON}}, [SPECIES_BURMY] = {{EVO_LEVEL_FEMALE, 20, SPECIES_WORMADAM}, From 76d0d8a94eeab0aa2e0943ab5581c31cb893462a Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 18 Apr 2023 23:02:51 +0200 Subject: [PATCH 090/131] Fix battle message strings for stats (#2927) * Fix battle message strings for stats --- include/config/battle.h | 4 ++-- src/battle_message.c | 12 ++++++------ src/pokemon.c | 4 ++-- test/ability_contrary.c | 18 +++++++++--------- test/ability_download.c | 12 ++++++------ test/ability_intimidate.c | 2 +- test/ability_magic_bounce.c | 6 +++--- test/ability_oblivious.c | 2 +- test/ability_speed_boost.c | 2 +- test/ability_volt_absorb.c | 2 +- test/item_effect_increase_stat.c | 2 +- test/move.c | 4 ++-- test/move_effect_attack_down.c | 2 +- test/move_effect_attack_up.c | 2 +- test/move_effect_attack_up_user_ally.c | 6 +++--- test/move_effect_defense_down.c | 2 +- test/move_effect_defense_up.c | 2 +- test/move_effect_defog.c | 4 ++-- test/move_effect_special_attack_down.c | 2 +- test/move_effect_special_attack_up_3.c | 2 +- test/move_effect_stockpile.c | 20 ++++++++++---------- test/status1.c | 4 ++-- test/terrain_electric.c | 2 +- test/terrain_grassy.c | 2 +- test/terrain_misty.c | 2 +- test/terrain_psychic.c | 2 +- 26 files changed, 62 insertions(+), 62 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index 24f4ad4f15..ad31621623 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -98,7 +98,7 @@ #define B_HEALING_WISH_SWITCH GEN_LATEST // In Gen5+, the mon receiving Healing Wish is sent out at the end of the turn. // Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon. #define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain. -#define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp.Defense stats. Once Spit Up / Swallow is used, these stat changes are lost. +#define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost. // Ability settings #define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters. @@ -183,7 +183,7 @@ // Other settings #define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. -#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD. +#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD. #define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. #define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. #define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) diff --git a/src/battle_message.c b/src/battle_message.c index 7d10b19f11..7df30cb296 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -435,11 +435,11 @@ static const u8 sText_ExclamationMark3[] = _("!"); static const u8 sText_ExclamationMark4[] = _("!"); static const u8 sText_ExclamationMark5[] = _("!"); static const u8 sText_HP[] = _("HP"); -static const u8 sText_Attack[] = _("attack"); -static const u8 sText_Defense[] = _("defense"); -static const u8 sText_Speed[] = _("speed"); -static const u8 sText_SpAttack[] = _("sp. attack"); -static const u8 sText_SpDefense[] = _("sp. defense"); +static const u8 sText_Attack[] = _("Attack"); +static const u8 sText_Defense[] = _("Defense"); +static const u8 sText_Speed[] = _("Speed"); +static const u8 sText_SpAttack[] = _("Sp. Atk"); +static const u8 sText_SpDefense[] = _("Sp. Def"); static const u8 sText_Accuracy[] = _("accuracy"); static const u8 sText_Evasiveness[] = _("evasiveness"); @@ -555,7 +555,7 @@ static const u8 sText_VanishedInstantly[] =_("{B_ATK_NAME_WITH_PREFIX} vanished\ static const u8 sText_ProtectedTeam[] =_("{B_CURRENT_MOVE} protected\n{B_ATK_TEAM2} team!"); static const u8 sText_SharedItsGuard[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\nguard with the target!"); static const u8 sText_SharedItsPower[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\npower with the target!"); -static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp.Def stats are swapped!"); +static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp. Def stats are swapped!"); static const u8 sText_BecameNimble[] =_("{B_ATK_NAME_WITH_PREFIX} became nimble!"); static const u8 sText_HurledIntoTheAir[] =_("{B_DEF_NAME_WITH_PREFIX} was hurled\ninto the air!"); static const u8 sText_HeldItemsLoseEffects[] =_("It created a bizarre area in which\nPokémon's held items lose their effects!"); diff --git a/src/pokemon.c b/src/pokemon.c index d985ef95d3..46eca90b29 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1919,7 +1919,7 @@ const struct SpindaSpot gSpindaSpotGraphics[] = #include "data/pokemon/item_effects.h" const s8 gNatureStatTable[NUM_NATURES][NUM_NATURE_STATS] = -{ // Attack Defense Speed Sp.Atk Sp.Def +{ // Attack Defense Speed Sp.Atk Sp. Def [NATURE_HARDY] = { 0, 0, 0, 0, 0 }, [NATURE_LONELY] = { +1, -1, 0, 0, 0 }, [NATURE_BRAVE] = { +1, 0, -1, 0, 0 }, @@ -6626,7 +6626,7 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s RtcCalcLocalTime(); if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && gEvolutionTable[species][i].param == evolutionItem) targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; + break; } } break; diff --git a/test/ability_contrary.c b/test/ability_contrary.c index 7fd902280b..33cfa7ce87 100644 --- a/test/ability_contrary.c +++ b/test/ability_contrary.c @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated", s16 damage) if (ability == ABILITY_CONTRARY) { ABILITY_POPUP(opponent, ABILITY_CONTRARY); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's attack rose!"); + MESSAGE("Foe Spinda's Attack rose!"); } HP_BAR(player, captureDamage: &results[i].damage); } @@ -49,11 +49,11 @@ SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normall if (ability == ABILITY_CONTRARY) { // ABILITY_POPUP(opponent, ABILITY_CONTRARY); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's sp. attack sharply rose!"); + MESSAGE("Foe Spinda's Sp. Atk sharply rose!"); } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's sp. attack harshly fell!"); + MESSAGE("Foe Spinda's Sp. Atk harshly fell!"); } // MESSAGE("Foe Spinda used Overheat!"); @@ -61,11 +61,11 @@ SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normall if (ability == ABILITY_CONTRARY) { // ABILITY_POPUP(opponent, ABILITY_CONTRARY); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's sp. attack sharply rose!"); + MESSAGE("Foe Spinda's Sp. Atk sharply rose!"); } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's sp. attack harshly fell!"); + MESSAGE("Foe Spinda's Sp. Atk harshly fell!"); } } FINALLY { @@ -95,11 +95,11 @@ SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normal if (ability == ABILITY_CONTRARY) { // ABILITY_POPUP(opponent, ABILITY_CONTRARY); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's attack harshly fell!"); + MESSAGE("Foe Spinda's Attack harshly fell!"); } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's attack sharply rose!"); + MESSAGE("Foe Spinda's Attack sharply rose!"); } // MESSAGE("Foe Spinda used Tackle!"); @@ -127,11 +127,11 @@ SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normal if (ability == ABILITY_CONTRARY) { // ABILITY_POPUP(opponent, ABILITY_CONTRARY); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's attack rose!"); + MESSAGE("Foe Spinda's Attack rose!"); } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Spinda's attack fell!"); + MESSAGE("Foe Spinda's Attack fell!"); } MESSAGE("Foe Spinda used Tackle!"); diff --git a/test/ability_download.c b/test/ability_download.c index 132c0eb5ba..d83d90196e 100644 --- a/test/ability_download.c +++ b/test/ability_download.c @@ -7,7 +7,7 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_TRI_ATTACK].split == SPLIT_SPECIAL); } -SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp.Def", s16 damage) +SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp. Def", s16 damage) { u32 ability; PARAMETRIZE { ability = ABILITY_TRACE; } @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp.Def", { ABILITY_POPUP(opponent, ABILITY_DOWNLOAD); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Porygon's Download raised its attack!"); + MESSAGE("Foe Porygon's Download raised its Attack!"); } HP_BAR(player, captureDamage: &results[i].damage); } FINALLY { @@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp.Def", } } -SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp.Def than Def", s16 damage) +SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp. Def than Def", s16 damage) { u32 ability; PARAMETRIZE { ability = ABILITY_TRACE; } @@ -45,7 +45,7 @@ SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp.Def than Def { ABILITY_POPUP(player, ABILITY_DOWNLOAD); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Porygon's Download raised its sp. attack!"); + MESSAGE("Porygon's Download raised its Sp. Atk!"); } HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { @@ -79,10 +79,10 @@ SINGLE_BATTLE_TEST("Download doesn't activate if target hasn't been sent out yet { ABILITY_POPUP(player, ABILITY_DOWNLOAD); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Porygon's Download raised its attack!"); + MESSAGE("Porygon's Download raised its Attack!"); ABILITY_POPUP(opponent, ABILITY_DOWNLOAD); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Porygon2's Download raised its sp. attack!"); + MESSAGE("Foe Porygon2's Download raised its Sp. Atk!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); HP_BAR(opponent, captureDamage: &results[i].damagePhysical); diff --git a/test/ability_intimidate.c b/test/ability_intimidate.c index a891f9af87..40804cbb19 100644 --- a/test/ability_intimidate.c +++ b/test/ability_intimidate.c @@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack") OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_BUTTON); }; OPPONENT(SPECIES_HITMONTOP) { Moves(MOVE_TACKLE); }; } WHEN { - TURN { + TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_TACKLE); SEND_OUT(opponent, 1); diff --git a/test/ability_magic_bounce.c b/test/ability_magic_bounce.c index d52b93c4a5..848f632ab5 100644 --- a/test/ability_magic_bounce.c +++ b/test/ability_magic_bounce.c @@ -74,11 +74,11 @@ DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting both foes at two foe MESSAGE("Abra's Leer was bounced back by Foe Espeon's Magic Bounce!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, opponentLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - MESSAGE("Abra's defense fell!"); + MESSAGE("Abra's Defense fell!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); - MESSAGE("Kadabra's defense fell!"); + MESSAGE("Kadabra's Defense fell!"); // Also check if second original target gets hit by Leer as this was once bugged ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); - MESSAGE("Foe Wynaut's defense fell!"); + MESSAGE("Foe Wynaut's Defense fell!"); } } diff --git a/test/ability_oblivious.c b/test/ability_oblivious.c index 0708845ed1..efe2901eca 100644 --- a/test/ability_oblivious.c +++ b/test/ability_oblivious.c @@ -63,6 +63,6 @@ SINGLE_BATTLE_TEST("Oblivious prevents Intimidate") ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); ABILITY_POPUP(player, ABILITY_OBLIVIOUS); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } - MESSAGE("Slowpoke's attack was not lowered!"); + MESSAGE("Slowpoke's Attack was not lowered!"); } } diff --git a/test/ability_speed_boost.c b/test/ability_speed_boost.c index b3e128931a..39219a5cc7 100644 --- a/test/ability_speed_boost.c +++ b/test/ability_speed_boost.c @@ -1,7 +1,7 @@ #include "global.h" #include "test_battle.h" -SINGLE_BATTLE_TEST("Speed Boost gradually boosts speed") +SINGLE_BATTLE_TEST("Speed Boost gradually boosts Speed") { GIVEN { PLAYER(SPECIES_TORCHIC) { Ability(ABILITY_SPEED_BOOST); Speed(99); }; diff --git a/test/ability_volt_absorb.c b/test/ability_volt_absorb.c index bef35e2b4b..18902eaa20 100644 --- a/test/ability_volt_absorb.c +++ b/test/ability_volt_absorb.c @@ -102,7 +102,7 @@ SINGLE_BATTLE_TEST("Volt Absorb prevents Cell Battery from activating") NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Cell Battery, the attack of Jolteon rose!"); + MESSAGE("Using Cell Battery, the Attack of Jolteon rose!"); } } diff --git a/test/item_effect_increase_stat.c b/test/item_effect_increase_stat.c index 70c89bdd4e..b459e3ac88 100644 --- a/test/item_effect_increase_stat.c +++ b/test/item_effect_increase_stat.c @@ -1,7 +1,7 @@ #include "global.h" #include "test_battle.h" -SINGLE_BATTLE_TEST("X-Attack sharply raises battler's attack stat", s16 damage) +SINGLE_BATTLE_TEST("X-Attack sharply raises battler's Attack stat", s16 damage) { u16 useItem; PARAMETRIZE { useItem = FALSE; } diff --git a/test/move.c b/test/move.c index 9ad336330f..9e23c2bd00 100644 --- a/test/move.c +++ b/test/move.c @@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Turn order is determined by priority") } } -SINGLE_BATTLE_TEST("Turn order is determined by speed if priority ties") +SINGLE_BATTLE_TEST("Turn order is determined by Speed if priority ties") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { Speed(2); } @@ -67,7 +67,7 @@ SINGLE_BATTLE_TEST("Turn order is determined by speed if priority ties") } } -SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and speed tie") +SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie") { KNOWN_FAILING; // The algorithm is significantly biased. PASSES_RANDOMLY(1, 2); diff --git a/test/move_effect_attack_down.c b/test/move_effect_attack_down.c index 6333bbea1f..0df14f701a 100644 --- a/test/move_effect_attack_down.c +++ b/test/move_effect_attack_down.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Growl lowers Attack", s16 damage) if (lowerAttack) { ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Wobbuffet's attack fell!"); + MESSAGE("Foe Wobbuffet's Attack fell!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); HP_BAR(player, captureDamage: &results[i].damage); diff --git a/test/move_effect_attack_up.c b/test/move_effect_attack_up.c index 7b57fa0d26..4978d03f96 100644 --- a/test/move_effect_attack_up.c +++ b/test/move_effect_attack_up.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Meditate raises Attack", s16 damage) if (raiseAttack) { ANIMATION(ANIM_TYPE_MOVE, MOVE_MEDITATE, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's attack rose!"); + MESSAGE("Wobbuffet's Attack rose!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); HP_BAR(opponent, captureDamage: &results[i].damage); diff --git a/test/move_effect_attack_up_user_ally.c b/test/move_effect_attack_up_user_ally.c index e98df30d8e..e920752dec 100644 --- a/test/move_effect_attack_up_user_ally.c +++ b/test/move_effect_attack_up_user_ally.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Howl raises user's Attack", s16 damage) if (raiseAttack) { ANIMATION(ANIM_TYPE_MOVE, MOVE_HOWL, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's attack rose!"); + MESSAGE("Wobbuffet's Attack rose!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); HP_BAR(opponent, captureDamage: &results[i].damage); @@ -50,9 +50,9 @@ DOUBLE_BATTLE_TEST("Howl raises user's and partner's Attack", s16 damageLeft, s1 if (raiseAttack) { ANIMATION(ANIM_TYPE_MOVE, MOVE_HOWL, playerLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - MESSAGE("Wobbuffet's attack rose!"); + MESSAGE("Wobbuffet's Attack rose!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); - MESSAGE("Wynaut's attack rose!"); + MESSAGE("Wynaut's Attack rose!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); HP_BAR(opponentLeft, captureDamage: &results[i].damageLeft); diff --git a/test/move_effect_defense_down.c b/test/move_effect_defense_down.c index 6e5a45e848..9ecd1c25f2 100644 --- a/test/move_effect_defense_down.c +++ b/test/move_effect_defense_down.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Tail Whip lowers Defense", s16 damage) if (lowerDefense) { ANIMATION(ANIM_TYPE_MOVE, MOVE_TAIL_WHIP, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Wobbuffet's defense fell!"); + MESSAGE("Foe Wobbuffet's Defense fell!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); HP_BAR(opponent, captureDamage: &results[i].damage); diff --git a/test/move_effect_defense_up.c b/test/move_effect_defense_up.c index 8db9a7f7e4..492ce7bc93 100644 --- a/test/move_effect_defense_up.c +++ b/test/move_effect_defense_up.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Harden raises Defense", s16 damage) if (raiseDefense) { ANIMATION(ANIM_TYPE_MOVE, MOVE_HARDEN, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's defense rose!"); + MESSAGE("Wobbuffet's Defense rose!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); HP_BAR(player, captureDamage: &results[i].damage); diff --git a/test/move_effect_defog.c b/test/move_effect_defog.c index e9e55d57fe..751ddf60f6 100644 --- a/test/move_effect_defog.c +++ b/test/move_effect_defog.c @@ -165,7 +165,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S MESSAGE("Pointed stones dug into Wobbuffet!"); MESSAGE("Wobbuffet was caught in a Sticky Web!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - MESSAGE("Wobbuffet's speed fell!"); + MESSAGE("Wobbuffet's Speed fell!"); } else { NONE_OF { @@ -173,7 +173,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S MESSAGE("Pointed stones dug into Wobbuffet!"); MESSAGE("Wobbuffet was caught in a Sticky Web!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - MESSAGE("Wobbuffet's speed fell!"); + MESSAGE("Wobbuffet's Speed fell!"); } } } diff --git a/test/move_effect_special_attack_down.c b/test/move_effect_special_attack_down.c index a20b8558e7..0511692d46 100644 --- a/test/move_effect_special_attack_down.c +++ b/test/move_effect_special_attack_down.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Confide lowers Special Attack", s16 damage) if (lowerSpecialAttack) { ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFIDE, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Wobbuffet's sp. attack fell!"); + MESSAGE("Foe Wobbuffet's Sp. Atk fell!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, opponent); HP_BAR(player, captureDamage: &results[i].damage); diff --git a/test/move_effect_special_attack_up_3.c b/test/move_effect_special_attack_up_3.c index f7e7e11d14..ad53bedb9e 100644 --- a/test/move_effect_special_attack_up_3.c +++ b/test/move_effect_special_attack_up_3.c @@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Tail Glow drastically raises Special Attack", s16 damage) if (raiseSpecialAttack) { ANIMATION(ANIM_TYPE_MOVE, MOVE_TAIL_GLOW, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's sp. attack drastically rose!"); + MESSAGE("Wobbuffet's Sp. Atk drastically rose!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, player); HP_BAR(opponent, captureDamage: &results[i].damage); diff --git a/test/move_effect_stockpile.c b/test/move_effect_stockpile.c index 0530355efb..bd0d3a113d 100644 --- a/test/move_effect_stockpile.c +++ b/test/move_effect_stockpile.c @@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Swallow heals HP depending on Stockpile's count", s16 hpHeal } } -SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp.Def", s16 dmgPyhsical, s16 dmgSpecial) +SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp. Def", s16 dmgPyhsical, s16 dmgSpecial) { u16 move; PARAMETRIZE {move = MOVE_STOCKPILE;} @@ -161,8 +161,8 @@ SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp.Def", s16 dmgPyhsica if (move == MOVE_STOCKPILE) { MESSAGE("Wobbuffet stockpiled 1!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Wobbuffet's defense rose!"); - MESSAGE("Wobbuffet's sp. defense rose!"); + MESSAGE("Wobbuffet's Defense rose!"); + MESSAGE("Wobbuffet's Sp. Def rose!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); @@ -176,7 +176,7 @@ SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp.Def", s16 dmgPyhsica } } -DOUBLE_BATTLE_TEST("Stockpile's Def and Sp.Def boost is lost after using Spit Up or Swallow", s16 dmgPyhsicalBefore, s16 dmgPhysicalAfter, s16 dmgSpecialBefore, s16 dmgSpecialAfter) +DOUBLE_BATTLE_TEST("Stockpile's Def and Sp. Def boost is lost after using Spit Up or Swallow", s16 dmgPyhsicalBefore, s16 dmgPhysicalAfter, s16 dmgSpecialBefore, s16 dmgSpecialAfter) { u8 count; u16 move; @@ -217,24 +217,24 @@ DOUBLE_BATTLE_TEST("Stockpile's Def and Sp.Def boost is lost after using Spit Up ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); if (count == 1) { - MESSAGE("Wobbuffet's defense fell!"); + MESSAGE("Wobbuffet's Defense fell!"); } else if (count == 2) { - MESSAGE("Wobbuffet's defense harshly fell!"); + MESSAGE("Wobbuffet's Defense harshly fell!"); } else { - MESSAGE("Wobbuffet's defense severely fell!"); + MESSAGE("Wobbuffet's Defense severely fell!"); } ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); if (count == 1) { - MESSAGE("Wobbuffet's sp. defense fell!"); + MESSAGE("Wobbuffet's Sp. Def fell!"); } else if (count == 2) { - MESSAGE("Wobbuffet's sp. defense harshly fell!"); + MESSAGE("Wobbuffet's Sp. Def harshly fell!"); } else { - MESSAGE("Wobbuffet's sp. defense severely fell!"); + MESSAGE("Wobbuffet's Sp. Def severely fell!"); } MESSAGE("Wobbuffet's stockpiled effect wore off!"); diff --git a/test/status1.c b/test/status1.c index f4d3c7d944..c244b9a604 100644 --- a/test/status1.c +++ b/test/status1.c @@ -53,7 +53,7 @@ SINGLE_BATTLE_TEST("Burn deals 1/16th damage per turn") } } -SINGLE_BATTLE_TEST("Burn reduces attack by 50%", s16 damage) +SINGLE_BATTLE_TEST("Burn reduces Attack by 50%", s16 damage) { bool32 burned; PARAMETRIZE { burned = FALSE; } @@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("Freeze is thawed by user's Flame Wheel") } } -SINGLE_BATTLE_TEST("Paralysis reduces speed by 50%") +SINGLE_BATTLE_TEST("Paralysis reduces Speed by 50%") { u16 playerSpeed; bool32 playerFirst; diff --git a/test/terrain_electric.c b/test/terrain_electric.c index b5608e661b..bb397fdf9b 100644 --- a/test/terrain_electric.c +++ b/test/terrain_electric.c @@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Electric Terrain activates Electric Seed and Mimicry") TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Electric Seed, the defense of Wobbuffet rose!"); + MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!"); ABILITY_POPUP(opponent); MESSAGE("Foe Stunfisk's type changed to Electr!"); } FINALLY { diff --git a/test/terrain_grassy.c b/test/terrain_grassy.c index cf83048750..ae6e6d9e92 100644 --- a/test/terrain_grassy.c +++ b/test/terrain_grassy.c @@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Grassy Terrain activates Grassy Seed and Mimicry") TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Grassy Seed, the defense of Wobbuffet rose!"); + MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!"); ABILITY_POPUP(opponent); MESSAGE("Foe Stunfisk's type changed to Grass!"); } FINALLY { diff --git a/test/terrain_misty.c b/test/terrain_misty.c index dda5253f23..668b036992 100644 --- a/test/terrain_misty.c +++ b/test/terrain_misty.c @@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Misty Terrain activates Misty Seed and Mimicry") TURN { MOVE(player, MOVE_MISTY_TERRAIN); } } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Misty Seed, the sp. defense of Wobbuffet rose!"); + MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!"); ABILITY_POPUP(opponent); MESSAGE("Foe Stunfisk's type changed to Fairy!"); } FINALLY { diff --git a/test/terrain_psychic.c b/test/terrain_psychic.c index eb5103f314..2cddef070f 100644 --- a/test/terrain_psychic.c +++ b/test/terrain_psychic.c @@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Psychic Terrain activates Psychic Seed and Mimicry") TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Using Psychic Seed, the sp. defense of Wobbuffet rose!"); + MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!"); ABILITY_POPUP(opponent); MESSAGE("Foe Stunfisk's type changed to Psychc!"); } FINALLY { From e6505bda4bc9ebb23573ac9703ab09261742c110 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Wed, 19 Apr 2023 01:49:42 +0200 Subject: [PATCH 091/131] Fix some sprites (#2926) * Fix hisuian typlosion * Fix mega metagross backsprite * Fix shiny Reuniclus * Fix Duosion mouth * Fix front mega metagross * Fix front Yanmega * Fix Electivire front sprite * Fix shiny duskull * Fix Hariyama sprite * Fix Shiny masquerain --- graphics/pokemon/duosion/anim_front.png | Bin 802 -> 738 bytes graphics/pokemon/duosion/normal.pal | 2 +- graphics/pokemon/duskull/anim_front.png | Bin 725 -> 737 bytes graphics/pokemon/duskull/back.png | Bin 562 -> 524 bytes graphics/pokemon/duskull/shiny.pal | 2 +- graphics/pokemon/electivire/anim_front.png | Bin 1898 -> 1908 bytes graphics/pokemon/electivire/normal.pal | 2 +- graphics/pokemon/hariyama/anim_front.png | Bin 1405 -> 1405 bytes graphics/pokemon/hariyama/normal.pal | 2 +- graphics/pokemon/masquerain/anim_front.png | Bin 1282 -> 1284 bytes graphics/pokemon/masquerain/normal.pal | 2 +- graphics/pokemon/metagross/mega/back.png | Bin 966 -> 897 bytes graphics/pokemon/metagross/mega/front.png | Bin 1366 -> 1311 bytes graphics/pokemon/reuniclus/anim_front.png | Bin 1176 -> 1210 bytes .../pokemon/typhlosion/hisuian/normal.pal | 2 +- graphics/pokemon/typhlosion/hisuian/pal.pal | 19 ------------------ graphics/pokemon/yanmega/anim_front.png | Bin 1210 -> 1103 bytes 17 files changed, 6 insertions(+), 25 deletions(-) delete mode 100755 graphics/pokemon/typhlosion/hisuian/pal.pal diff --git a/graphics/pokemon/duosion/anim_front.png b/graphics/pokemon/duosion/anim_front.png index e8c48d6c05fa3b8fd5dfcce88789aae67968b2a4..c265b42524e803d4fe8096c459643f42f4aa2114 100644 GIT binary patch delta 692 zcmV;l0!#g(2I2*f7#0Wv0001tU!Pb20004VQb$4nuFf3kks&63us}d?I5>dVpa1{> z00000005ZOL^l8c0$@o*K~!jg?U>n;gCGz^MUc)U|Np;3vtvMSH6>(N}lIW#2*oX0XzYYALMtTLfjM5 z^7##ndHxF~L_mlZz@b6HC|?L5z>;;D9^i&x;sA*BVc#F|5b_Mjjo|ZsyJ7gT)a!@> zIL|{Mq84yT$N=l+&jgzRRssmS5Y`|9tPG(2yg%W}HlGN8IKUBXT74S|ydes~?L%GY zJ(&SyHStjt<5m9Vo0J|VoVNbQDSrP=ECfsXGdYyZaq&Fe|=e;6>*e}VreeQ)g__kW-7*uO;o z`}U9P|H%GP{U6&uX73mF4+1XiA2E(g`$x3#(*99@z}Wr)cfPiNtbcG}{|MmH{=xpi z*#5!(!AbvNd++PN;GQ-e{U?dO1Nsk6;jI54V5tB20Q&l0^&g-abo3v!*Q(Rd>i>>) zFoyb{+6Qn;G_GTAAE5n*t*if%{zE{V)Lqnn_?`#60pIg@05~IN`VR#$-GA6t|6$dC as$Vt}u^^N#nQ>$Q0000I!7zqRe0000=*q&4Ew`VenmEfg*hAf@C4+b2!Zrt=G2Vb^Z_ zbeY+On1dO*=%mO~SeEDW%$@I|zRz zzy(N@DrF#rK&iami9H6Om4FOa5UW~CQ&Jv4W1a_|;MaE;V$0+=@a6Oy;#eDkDdEHE zgcE3G2xg%^c8FD>lqD7=aF1w>9RjN5N)XTuz=11~0z}Gmz}N{uQyuQWyaxiEPQG2$ z*kcBm5p;EXQ%!}PB;a_yDBW3LHiUlxN_9I|1T;K=tH2o$$ORy%)Diz((ScwAc*gng zywn^(%Y;DJCK~R65)hSr(__Bn0D5Jjy6>AYzu3tw{@B;A!vO47`O90b8y?6%%5cU@*3TN=>OyP4%C16XBqoon>`+k28xOQ>c zw&IR`W;0+a%}2CEmaYTXW*{>01~EjKIT>Goh%A$nk9fp?8ynC2w3heq1>LR?o~VjL zebQd>-F3_@5v!QJ9&A{3Uoj9V`G>j`dt}C7&{fF;B>zE@(`C&9)*eK<6_(*n>;Z6F z<)b|a;;+0IIJ8HnQ;-y0(aL}J;73B@UT}(KZ`#C)d%>1)C+fcw?7?UsME}tDD!Bto z&5DZG{37}X8lmWq=PK`c6JvnxcD@#R0A@oFkSE9U8v(f>?&u3HiU3LdpOv~QoPia0 z*QzFlp#DbF;=vxU>OZju)(_5sm%sL4$S*3)?E%+fvm9?za9)v)^yuidBg!J*W$df&|y91_xGwhXJ4S#`*_CW+jB24)X mBa!XhOvqbpsd7#0Wv0001tU!Pb20004VQb$4nuFf3kks&{SUr9tkRA_Ds;JOjc^&*QW(J8^^0`mcY?J#&{SrAxD{bs=h3#MB^h;q;D z%YBR%EGFQSUe40Nf(tC>3W0!CWb8!`Uyd^V;0l4_x}N>lH^NV_Y#~!JqIdl6Xj3xI z{^#clsRt#vU0(qZytDuTBnQ$%CItEI-68_b0r0K*2;fM6;Og>PSXP~)E|fOWgNv$O zZ5iS$7JSer15JQ%lvf=?Tt68=#N79v^~FKn8wif7a?!7TDF8r|eZ5N3y#RbXPHp=a z2~Zchb2x1v^azv9MOgX-(4Ry$8$jCm;{+S}P)4CayMDJ($jLOv6QgtWg0XjD8o(O@ zf}1XV?4whEI%?FYQKSC78u`J<58CpB!?UtIKhP%;XGC*;kX}^Vd#p7-*dAp0MR&>% zYF|lEWqy%K8>jpL)%PlN*!%Y+9rJ_D$1S0dE1=8|_MNyPNRP5?23+%px(BU9DDwlj zd=?GU*Z^gIfUtk&ai)*@GCzpl>x~x9`GNgTQTnuaKjjAvw=#_4k{<*M@d01Il|+>7@w^#@&k%`TMO^<1EYbzKR>WB zZt??TCV7(|SfAi;^8@>T$&nuvgpnVN8fB|ru;LwU7|-Y200000NkvXXu0mjflw~=5 delta 653 zcmV;80&@M~1=R(R7zqRe0000c#H5ELlz0jGlyxHHMv zJ-KG#*3bh&UDkp=KmjUc5C^vYf?=qMTMPL^+PorpO!n?f%i`@(O@I{PwmY1ey(76Z znT++1N?Z>2r*~%vZq5NdFV09ri@P(3uVOaXj}tL8#}slQ#Ft`8?7~+Wb$dpaKyC( zkcPb22_F%^8U?L)W)R}>RHFM@x3IS+#6A%-53%0pCqQe0dw4QF(wHg$i0iF>B7#;ysXPZ%_wJ;v0!exOc)PcNM)3lZ z_&e4u8Ua(@2vitv8(6(rRF@IMad_?kB@`L+ZX@|e=!$#!WB0fUxgZ3-^$ULteLaW+ z&pQ%oBV2_66LLBU3OFA_-Lb~{KWoen1Nk9xTQZm*qC^@*Fh4}(%dEIielUFj#e063 z_kU8A%*~EVyZlh~mu|ci_UD|s{4ghyp3Tbry;GMTtc_C&T&4!#@`LUBr=8L7+2)5v z=7O8V09<~kM9Pjz8^Gm<29c0004VQb$4nuFf3kkv=bf_;^?V000000H#zU zHUIztib+I4R9J=Wmd&<aiz#R_^$u9N)MelJ7@K%4k)!zV5S=d{LW+gW=S+C<} zCKJMyg2ma$OHByzns)qzxH(CEE6r`r@qv+4SFtyI-h@vOJoPgY@ z27oyL_$1Qwv4;r(<4hTVnFTZra1Rp#ng-?;=rBfq#tKP6pE|&40Qlv2mI^+>x*iNd zt1tD~0yppuz`tL;2U#C`&^81cfNE?Q<;j8y=p*nN(63>C?m?RaY&+=Rd|ObXWM;4s ztPNEI2KyP$X;uh`p`>`6zA)-w_xA>82U~{oJD^Ky^*l^Rfa+h~@z(fRX|`Tm4NXjW!R+VL2s$ zamJ5nkOmtv03k^$7Q{G;7PPBc(90WICTROfCJax<1^DW#;|HNU7!Dx>jer0E002ov JPDHLkV1hoL$4CGG delta 505 zcmV7$yV*00013M{Ml?0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuEQPXjo7H000000H#D0gFjQK~zY`<&;5c z!!Qs(GeYB9KL{Ta9c*GqEl2Tdj=e@&D+Lq~fow zRrQ{&?{~V{X6mYjgI;Hd4uFVx0MR2_+l&c+l12tlWMXVy05IdQBoF{-ss#(J=i^jJ zLFi1Jo*+Q4ZN|gb;V=`Yg3!c#T45LcDksX-KGi4UT2-0}n9J=IXm!a1jQbw>ACLjf z2w2s?8~{#Vx7QsS30%eiufyA`hXNG9sLR$IoxA#qI}gBB3UtQNx_fNchPz3JlZ$JA z=u!f$SpYgi{tv33<2Lv}Ro#ZaAJ4k)QUEc=Md0YtG0=5t<(GM4>+YHH|9N_Jaia zV?(zOcNp*P{fP6M780_6Zm#UPJvx?w3v37{28#t_p`Y%v1F={IQ>Pi4^r v3%i^2uv7D968z0nOd@`o+@t&NR#E%{b%xFx8N_#800000NkvXXu0mjfv=ZOe diff --git a/graphics/pokemon/duskull/shiny.pal b/graphics/pokemon/duskull/shiny.pal index 2c59d3ae14..16dc97f5a8 100644 --- a/graphics/pokemon/duskull/shiny.pal +++ b/graphics/pokemon/duskull/shiny.pal @@ -14,6 +14,6 @@ JASC-PAL 248 232 176 248 120 88 152 40 72 -104 88 80 +248 120 88 0 0 0 0 0 0 diff --git a/graphics/pokemon/electivire/anim_front.png b/graphics/pokemon/electivire/anim_front.png index a5f05a7e8b9552604a2c1903e92628e449dac87e..9aae7e5b5c7ef8497b1c49c6a0b2321a0309b3ed 100644 GIT binary patch delta 1865 zcmV-P2e$a?4)hL?7#0Wv0001tU!Pb20004VQb$4nuFf3kks&O9SV%xyfXKkib1MiZ0Vb9a92S?A72r==_qiPS91 z-y5&jzcQ!S`}1Rj$y&s(&-i9iRBLWX_7sxoqtf9GhJ^F@yUOX8fwJaBM`CFRk6 zpm6X&5nvf)P9>4SV>uvP10*#Qd-o#daNLymhK+KtX0GPa2^Is6&Z^bwu>_KED(D@LAdiaQakYCJyD}Ua`gAV{y*B8d%;0Voc zB@ohk3LxeNz_K<7RDdwpw;1XwvP`pwnUYrei7Nmy&Y~_Uob!m1u{mAT6_2?Tm{Z1H zrW|b7zuShN5WXEqPzYVrXk$$-hz7|w@{A*=s1V<6{jU16b-9p|ZiQP{fTHFCU^6ud zlR5x51S5BU>q{t@S*G(Kupah^Z>HO7A;LoG63E;((F-- z6d;+;bvpH~_GlrJexlR&;tEG`AP}&3**v*VjxWuC2J&7ksdfjeDE!KX(3LpG5lUVxdw?N|Rs{ExI@C!0=_pJ9YSraz z$MW>5X#haj0jfFY2EdAO0l-K-F-toDVt``M-ej1SuI=^EB_LRJ(*XM}@AEF~msW~^ zP&2gU>GR+gW3f-^7xv9a1J?swaqdR4Q&?Sp;IXtmQ%H7rYfV2PYnq(TrOgrdlP2`VeuhkTP+QCG=Kv6eDLm6wq9Dvabm3Gk$y%%_Ya2o@A zSk&~T4375w&0_`-{DxKd{ozqJkY|G3-Lhu(-V!SNwciNu*~)(R(W}!5KwBBJdpmnL zBS*(C9k`;f7S{PK#`a&MApT446#TvNM*)gnnyqKNc+D3WY0~xE{~-uC_E1}5??)%g z7qzt?~PGetBAi8qHX;-&PBs@7(a+?sp~} z;675U;ncX|-dE~vSJyA&$@0$5C3-$To zEid|&mXA_t5Gax#>|_B*%SQs8D#tC2LM2{fLl7@;7{Ol#w?LA)gL}F@aRI^scpp|p zytfZsTS3*Xmh~nd9Q6x-ol;`sc2Q=jRn>gZFN`X|0ceOvg#Fc70n&b~^`nYB2!LWt z+p`^^mk-RGT_rMmg#M}n(>SSokPV>IAGD&8Z9}=ZwX)U~MSu^x{vZI757<$Lk_%Vn z=H9=W4_)g`dhQ6VneM5OnDnT(`T=EAaLH@?3E)XTfb*WS7K+(_e{0<72flr|k)YH1 zGyTBDSTx2|?65Zy2Y}uCW!DdanwWy1|0Q7RF}^+6pXGzaMMov#3POFnoZ1h*ln<7l zDG2?EnF5%Ca1C&+9vFOIwyxH&uuoI`NkO<%4;-L+I0d*<51ikvgm9-G=y;M4Zq)-r zc#;rq)B|_nK|;7FQ4jq4X9?j_J#ZiXmk^A^L_+unt&nm=yg7=+00000NkvXXu0mjf D)t`z) delta 1855 zcmV-F2f+CB4(bk&7zqRe0000wHcbNQTpjV>kT)}uR@!x(G?`|lnUCJQdGlu8cM17V?d^Ym z8UNt3w{Gcut?ASret8@4-X})&WWqc0*ZZ~uy!(Y!1L~p2W>rVelZM|1WkRcd{Zlqn zfX|N9fYk*~_)*XEJkoo5QdV=z5v`i4$IG72SeW#Ruxx)?10*i}gAo!(DL*2uIm{Z^ z^4SC!VB4#mV5K;8u)Nu)1Z@YRSN0D#YjZ9q>f1ps`G z9!$Qv52MP2auS?`3ZOUf9@xGQ7hj^0;cA(B5<6BT!zbFo&@sj%1a!GhJOd*H9Gn~5XeV$=Dw^0;yHEh&m?Luz5-WdzVus_f%vH2t zRDdlF09eA&S=1M~x0Rp^qy~Z-&? zCoK>n_f`Qq8Hx<{SAZk3nWwxtK{CZh3J~M20CKl%13CxhNMHhKDh|p}FNZAvcd&?K z4B<4-F)Zp_kS@SW#}0pGQe|YL>B8wePE^(zn}8#Ra&Qzd+!#+;jB}JwCjBKAC+Av zi1u;or5`2ny=(H%t^ecoH`gyVb7p1k-sLwJmv;a}du9Gi?*a%l=v~AAQ~NIxWKBJE znvftX^`P2oZBc)sp#)i}2c<7o0);4@;GZZ}K}3Q4wk=SIs=zIQ^7LfZ5-6muz)3_r zp+691`(!0hNFy}dUqwM&lC6Rn^~4=u`SkSkgfZ`BM%&%Z)0mx}o}!6EX0&H+0Nt)C zcae3}LxYa7T8<v+YpU=QRl9?Y?j7lc9s=uqGq@1q0o@ZAS^mGHtcXzR|w z7zATBu@{TU-q#P%A6^8R*}4MWuorBhG|<-{-X9Ao=5o3^tz>*CD!Eu9z^5{xc&oOq zF?|uvb9aA{Uqh{v7D4BV&=>stC$R13Hxp25YK{P#HivKglAn*cO^ffJUy2EWLzIOF zMX+)K??nuaX`(0)v78(V9W!t0k)C6b0Dfk=yI5429lB$oF9PyLwTvAsl>8jUg@^jW z3;^fH@k7g4C_sBDB!~5o(z8c&douE*{5TAFR%L(IuFKC6&`gVGO2J4+>G|}@ToSt| zq0Yh3Fd6pgKvX5%)t!BgDeg-^yHa&fNCUbff@$qDD;TgRzcLxj-MRQq2#isH*3o0j z+5xJaEthlY=B`CFHMo$bIA+hd>+($7Hz{0=mqu$`h*78nhM_T-6bnA t=&OrYdlz>A`~A!Js9*`yOD7=$#Al5CekuM{*gq32ICFXAkhN zd0J`i4UM1m&vm_j4lsG`B)~I7clQ*aCeCmH#{mDD0QAHg=TZV4VFK`?j|m_i0k+Z1 zgh#3bY$-uo#*n~Z7ClwmP5^ZZqYD zmS&+@r67@i>K6gLaT@{`Y<`Ht{?Y`lidAbRNU@rOHazTL-Wd?aCIpApX3&BD;dgNF z&-?TFyx-fN5qao*0OG-WECAp`@dns{=OGYK)(Xm!>k3!{-fspN1mFy)z{qnHvqw03 ziTQnF!rO!lB7hJ)AIzD_eSD2k3Nf}l?}mo~$TK~ER)?Dz5%O00{V3a7%|Qqnd6Hky zD|JM8$bTGGO9J*T0)d%6RMB%B6QE+ypPP!5)gdG^KpwsOA}`fBuS8BI>t$xH5kem6 z2;ej%d)O7?gaBm&KGH~1P7!fZ%yb6CrOQh$4eI6dDml}?>ZQYkaP_}?gE%EdVouWqY%UmKt$Xk5aM(xpCWDo{-yZq zef(V){=00vnci~^Fs+lh=;9{;WAK`bpVY}<`~o}!OokagNKrnZeg-h|F^OXj-|BmS z=;cfN7%-``;ZIocO||oD4l=XYVFHN7`|1CGw(i|mey!-!CvfLI2LL7*(*xWEfXCW5 zw}6rL)OW7QFf{~TLNo6Ql|B-ddbLy~Yyhf%uolnOe6AadWA|M34_0ORTt^t!pc;V& zw2o&s3mTBDFOC7xJl6ni|Fd<*i&Ue?_QiQjsT$yXl?3n zRs91~oA*!w92!?KsDu82vD$j`?-S!H2m^Khz$oi&Q>|wwFMp#q{ey*@BiVT4`N`e& z54gGFig#X)^@IL_h0o1F|3EcZF2tyR z@Kuca2j3Bf{evq?c@h4ge;{I?T=tj!gGbv!__BZS7_<;{|KL*oRSThMAb5YF2T>Sp z1EKT}E~KKGCw|aBI8P$_!`L}=zsJ6KMvy;!njWp7q3jH00000NkvXXu0mjf(Gf^w delta 1231 zcmV;=1Tg!A3W5rd7zqRe0000 zzl-BW6vri82wdH2*XeIg-X@LMNn)0`i89t7V4qZ^+>?ea7fe<-=kB;5(q3_ha}fvu zbJdY8Lbz)Z6~^5BQF(7>^xL+I%!0vws zdTR6mCg}le!e%F%7%>(e1<`AgD_LveE!asHzC#d_6j4*;9_{Pw4x4*{l} z5CUoH9s+EFzy%9yz^Vr5{eKqm+cbUA1uRqu&|O;DU73J$uLkHQ ztgL8exD5d~Qvg2zY||e(lRfy61XO<$s{(kNmOv2sRhI=YOiKWsm5(WYb!7zw47U>S z0|YLx2_6Ru*tn_z4J>e8jL$d^@w>HBzz-NtL(V)2_?*q+7_+UiOaNfrN`M0(kJ>0= z%yD39$v)c)7}R~NDn!gXLtrpxvm1|)$sbv^+2qEV&x165$$7**wI}NMFm`_%3P6V3 zbS}ACjNj;~(D9r+nLs?-h(B$Qsd&WvpqMMA)U^~~6UXsY0>&1#(_>5#$i!cSFgY0( z=uH%BncE2DSHxj4Lnvy#v+J)Mhmj9RTtfPog>mzRTT{k7`XKTF2_iOw=>^T#X$`f% zSxiN4&|pq{?v1I@1b%baV+wyIU{f|32c#ai;DxiGe*!&V-gDS@J)W#ZVhjYtKNq6= z9$Sfkl^9cj@w^j2+CP{~YCG&~UXv#v&b5EArMAOI*ic?d3;*CS2c;B=$s`-b*tL`7VE4e%2A0V8F zU2=EKKWKv?c1QdJDy3RG=^xsvZD@M{24O1w!|&iQIuLk_e4_k;^bZ|(0BvBM=cRvW zyA-LFU>%P82bBL!!#^|$IPTdiD*Z!Y51MVPvNxr?qdhxVPFh8lwZ|*%fko+oc~rn@ t>85>vL9hGl!QlF60|n9ZAMF2c{S9y!fv3C#-A@1j002ovPDHLkV1gfqJcs}Q diff --git a/graphics/pokemon/masquerain/normal.pal b/graphics/pokemon/masquerain/normal.pal index bd8d9c4c7c..3d0291badc 100644 --- a/graphics/pokemon/masquerain/normal.pal +++ b/graphics/pokemon/masquerain/normal.pal @@ -14,6 +14,6 @@ JASC-PAL 136 32 72 136 160 200 192 200 224 -16 16 16 224 104 40 248 144 96 +16 16 16 diff --git a/graphics/pokemon/metagross/mega/back.png b/graphics/pokemon/metagross/mega/back.png index 00bfdd18181e129eb963e142b922ecec66bcb9bb..86c2b6e145655c2717d7ad305e9625253be03337 100644 GIT binary patch delta 828 zcmV-C1H=5r2Z0BW7#0Wv0001;w}I>c0004VQb$4nuFf3kkv=|u0{=-wK~z|U?U&tB z>o5$2W2siAA-wRjMqU?}-kYyH?^S^n0~Rg?i_n5==kEmxY

siT0sTOUYnhTZ)g zuFrD^YhSJr0zB&Q{pOK*2q+pqMDS@BtpvjJ1>X_L!O%$s?F%o&_qcV>G?2V0Fx>Dx zFB1#{;)_$@x(mskDh9*@b6DV8UM4StH#2U5Z+JH_@sWdn?gD%}MWh2H=kTGR0@u7I zY6%=Rya%fQU-4+RLGZ|a5xC^XLelfejbLE56pzP7_@G!uK&?q_GTCWDUI@gB2^*wL` z$`dEt2>ok+33dAtKBp~qPUA*o+V|tryPa1@1?q*@*hEq;B>Jcd`~HdRqAC#QabdW9 z%L~nWa-Rx{e}0h7obbs2c;Lz>&elGf%TNHm>lW<7sRH5$9-g(zcgLZ{h-On9_>P44 zs(=&7_?b?eZ}PUCsi=>tE-{g@9RT_z%Pc@D6Dfq;8=5QPuEnhC`N*3NT;-t;JYDfQtc( z=`V*ZkLpo!6VGd00SRML_t(Y$K8}qYZE~j#y2T=^58UdOM-{E zA@yo@m<{$U^qej;hn(CF`+_~0SQz>-ltS5~gyb-vp$GA*egeOY&pQ(<*|eU;Hzb5S zzkUBbGfDp4=m_!tFLGBLH_hU4r2F!^;aEI>s$acvZXr0HJ)jd^ojJ!v5TEw-6Tg_x~z2-4?2k>5LZM4>8y*JZax7;0n zLHQK`3&7B+*Hh>XeH?C5@Lxqby?V2Pg@C+6D^Uv z)`U+>N>AHHjJZOM7osFpW-UD#$r>}70O&%Uw-V4>=;#1zj6mMf{f5Gfm>>XhH^Bkh zL%OU@%uw2k-2_h<(5Ao+Ljq}AEe=?J*OlH@utmOGp#y){p?l&IBrjSC1kE==M+M$< z*4{z79gd8c}Cw{Z-fX@dBs#IL(w=Y5ed2+dbiS>@) z0d(rIE=5n?1^xTj_z2*rQ6?untXoqhFE=u0{i`zbRRBhkE{5ExUJ+HeQ=3vu?!JH3 z`Z6{#qI`HDah@bvg{|wl^ktSY5NmX^Veiy?Au(!o%ID_P8)ZlLK$6JlH7r90*gEiJ z>oLsnv5Af^Cj!8Xfi-L$tf`8BKpeCa_88qBz}C{>TLAzyBm)Y~v7e}6Q$DfAN|BEE zi8v_Nu4sZKQpL}ev-w)j4r59_n<>`VPb-Bcs&MZH-1ID5^O^y%psEpc1Yp8|@GBvd z7W_}6altw_FzRMO?8y-W%BNLIy%`Rf)#m^{3hLjwG{yf)1U}QT3;qF6D2GXZ0l+QN z%ESsYg^Fh%$QEI?Jn0KTFqr_z(Bq8WHMfgOMBqF*7V$a&2o-uIGTas-O}D^*5J~b2 XR@sk%RP-X-00000NkvXXu0mjfiYlXX diff --git a/graphics/pokemon/metagross/mega/front.png b/graphics/pokemon/metagross/mega/front.png index 6ed2cfbebc30f33e2e42d8de98a8817ab2324de0..1ebb0470aad180f323818652db2c8c4356ba1cb2 100644 GIT binary patch delta 1245 zcmV<31S0#^3ZDv)7#0Wv0001;w}I>c0004VQb$4nuFf3kkv=|u1f5AlK~z|UomY#N zqdE*DHc2S7JOBT;SCSo|vxV8Y+0*S5kRm^0rm2`s)8tl)xlg}eHqV4seK-3(1%Pue zrP@+J(cFG`zLesAmTGhFgj!kfZ9g!S@_0b$x*iCN612e2>4?$@#I5Ue3Li0ljbPpcc6C)Vxh$Z#~ z0X^t%cr!^rPHO))vfGHK1SDMq(m+54SO<9GQPPr-0-7k3AQ=ED5r;t#0o?H}37!Iu z0@eL+q>2K6abPl=1=@GK7+9C>4L{jnU@|axc`qqkRxIr#X~9tXVk6vBUf$ti zFkA*lU1QaTjZO@OuC`Hk;HLBaSa=i!JDiJFk|P-8=u_b`q2-5!`-TYn+73LE@|ioO zUgptTy~iDr+qQv)+wK#YcQZg#_F1K^u5qafzv-P43z^vT)m8n~wm5eiAVDBiS!kkr!UC zS4$rT{OKfsaAo@~-k78ycu7Lr@eI5&Pm`D47I@<#LMrIOm}Dq=v}F7E)AO& z_6LD~5pQ?a4}wZt|A-+72t+K<#(Mt;2_$g)vO(bfWg@WoL580Qpi~mRJP7O$$k>FT z0FwY1uE8!JvkQ25f&1GR@p0mGGF%ckoo>oRKJLQ;<_<&9Ab|{*_%*6AD$f0IVN?$} zt>a9%!dIm!N=U`>WFD9)h|$=XfQkRhk5M0gsy|wa{gFCwAFeBn_O@xn!%J^NgzmCy zj6U8hl2;AJGLO?dIk}xDp}^8@aW;~`?YXy~!6uO`l58mZ5so9RxDIC7DTomiMQ8DY z3~H%Xvn$qdVy?)J65GrC?3hnE#Wh&kz)wo2?7n$~SHRc3Ar#01P!&7JfYL00000NkvXX Hu0mjfgeXUa delta 1300 zcmV+v1?&2s3f2mc7$yV*00013M{Ml?0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuE-e010qNS#tmY4#NNd4#NS*Z>VGd00gf|L_t(Y$90u4Z`(!`$Im3t*_4<_$s`_S zTCLN@y#o)1!Pt zJM`YU0lOE^hmRL^;(h(jZE4*S4GHT}el zX`zyBiNS2-bn`1`u>t07o+!BmSb9Erl;h{|ArYR|T1cs6`UzlK4`z8DMc*8fkRlL& zegazNOB^9^9z~-)AYqCXN(0nI?EJQah){EFfYWS281+zKDMby~oIN_-B?7qC{V19u z(2wT+csx#c29yvk6`LZEr~v{aUoOag=S5g7moW&yA_NbU!7d3iIMV$K$9WLrO}5X9 zVyr+x+Ow0rI7H4)l2q?Id43raPhS>)#qwGJ3!n#am?#9S43zf1&ZEc+wxS+Z?q>Z@{9$fC$(QdRVLK~baOXHhSG^T(?-~4RuINmM7etUuOG_veAoc& z>sEEc8Ko$3>-%YfrZhQ!!uM`_EW^YM!V~Iqr;S4B?@$5`4CV-3=Q6_#IGsRymN%Mm z%4yHe5*UwTH1+pGZB|r}g4qwm9ZhMEnuBM!HJ13u?dlmWISw0xxuebD?XzMz9s@q} z^sMD)NeaORxa+`I1zr|40HxHM2^=$CTiCt3y))EQ0yhF~0%xLs+WJ4?fkpVklGECYC;Cg|6R|icXOSpFP z=pmT5mPm(s4vkl1t0mQZ_A-yA_3hehI1ieWZearY@@ljJh>cn9%^BC7N$Y$RsLc{X z*B&+jHapKpltOdGZ0G2_yt?q=vlsSOj{c|x>dUWuB+v&wA>@BlE<$)GQ2?$P#e^fphs( z>$1QGpX%p-4MJ810ny765jD0Y;PG$<+;1#IBLRkR4!m`UUavoYh(GE#rRNkmM-_Xv zF-dwFa+0M=N#GLXcv1fp{M%7x2bFAz9>foj{*EdOjsw z�j#+!)A@7W6Y}tOcrA7tbCdSK(9DPb2O7mf%NdWxyZh-co!7zvGTO?)Vk)sr!bD z=iokn@bXD|z(+X`f6SofyJHcD{D0TwmUrPx1gm@BUdO*ZEA0(QUMnj1?rwJ2{}-RT zzMi=e?fCx_3F+wGQ`f$C7+Uwf+V`Q?1?;%@G$vpw&A4;#7w}sBgL^+tcDnd*?%s!A zm(Jb$_{&-);M~2B5cJLWKOk`Yse2z{5Q4scdmkn^ckh=J9Nqf`g1&nnCOCKR;{<2! zeRv(QFtqM{kU*`v8P~?We~U*XjbKv{9fP=gue@)6J5?9S1Viku_JF!~wvbT#?>Pn9 zfJ3$G3`J9j#l2@ANpvX`KhHDhkY>Gfb?+2|F}RNX2m{%q0$(=II)`#4VRi4hXwxZw zO374)NY2Cg6D_P@Ml3^`g4V;N*ms+vm4 zFq(GJbMHErM1-0hPw-RUy&E;v<8eB}zX_uz8ayrUxZ^*FzbM@@PabE3pO_JEN->{UI$d3wwWN2YnmJ<@DA1Rsr}OYcdDSn{XBVV%NjqVVx=A zBYnBZ0XYER@};LvSe^uh4|jKb9|#;Syjv9_NDgeWO^;M0#|5yUz$KC0^*FZKCLLUC z?$3QCW-9|+1E3DQU9aDpx2`#{4SReF#o{^#W*R`q>EhwfdlFaXj05I>|KxuQEKLvv zK*$5{Vzc>MT|H>Ddbe?ydOoD`jZ=xjE;d}R#C8_8Fx{*>u-mEs5=pLwUZd*_Z; z!JLcqQ zw$Q`LXn8tiJY>#+Az4o(G97=*rSuNGm!(G}aFCOM=iB#P13W@CEL2{&K?8ush-a~c ze`@GV3rufhG8+3w05nFrlJf-B&=?_iarr};&^cejLG6%A z%QHl&99=i}6x9#;05}rg8hasrL40QY)n4sOn%CH|J8K>5$kObP>K>ZtlJ#qilkd+Of^RMh{7hpm75Hv@a>-w0IHzZux6f8$A^R!a460@|7azfk|0^16MEr|fh} z8tSi2RduU?c@)gQ^`PzPc&0pmpXd{wcyDCS7neB5F(!>YAFc|r+u+eW&DCEI0_o!? zVJS~so$2hmk3D#aa`m6$gD2nRVYQQ2juyXW8GA;SNsOAD58;0*98Uuub7|K}9# z(`6Js_ttkyGfyh&a5H@y_5Ue0>I;c~`;fgy`McUEwn@p%H_Uu??bd96a8W3BRsAtg zVqPp}cCr13u)9E6TuibXZoaws2CY@qpAqIo(}QmD_rN@@s6S|Jn^f1Ur=)fF$l9y@ a5B4vEDudj3#^-_n0000c>cDC*N5CWoahT(}n62_P>_2c*zg7o7T2+IE} zf~Z%-M}R!K`IMjl7IzbjuAV&*Y==6JSO7|Jjq671+5K$crD0!StyCjk2k>#_oTs?hgS0z2}5QoY1_ zYa0mGfTdx7aY52X+VcjudMKl}q`-iYs=%9I^l>Dd1q3gAo{d>&iEi`D^{L$El-ja z`_CN+`mGa6Qz}13R_(u21jPk_4Wcx{{Du90XRR*K86kbioQL;U_Fu>6Zca6ebsqlO z{wpDBH|;_``tZ*FGa~np4~VV1M$f=+>^~D^x8$mw^wQzFvj6J-o$8N$Y;$bRUD$s% z^|ZJ16pnptv+wO)*?+aZ6D5?jd%~_gcV++A_5q^J8DF%q<(c|y|F!#}?Sr*_YizA* zi>-hc`>&k?E`(UujZo<;<_5yv{_DYnyY9i-L$3DW*G5mV|7!lzv6m)@dSCNwEb8X} zx-VJ?*`xC5+GpN#Yw=I@eBAsJp9Fzzs~>w002ovPDHLk FV1gu;{`vp_ delta 1143 zcmV--1c>|32)YT77zqRe0000yDJS*qr3ALvX)l%6p}dF*x?(TWV34sRBe{yfq$0i-Q!k%Jws0D$snL%2L|9Rtwfs%SjKZ`|gDitw1&OXONf zl2$me@jhV0X5#;#b}(s4z$>t0hf?A9wDynO$@}R5Z}@b z{)_4^|M(CpO%`lpjC((lTjT<$HjjVfyfWJo5X~cqO%A-*?Cmb(F>wKSJjWQ;Pvk%x z9FZg4^!lCydE={v7)mkqBc1i5?lp{S?eqsLxh=Rq=>Ji7jzzJgJZ;^fr~R`TvbXJVgEmpRE|KWe-Y5&js zckH8IT$%=Qk6!elhG^?d4P2e3*4S=P$e(r4R&?2;^x}~vMnL6JFx=ij1v_$S#UzVB z`9c1}!8cbn${l+|bt(eT3-)yL(Sw5JDnO(Fxmbh^BDGVLP4dhn)*?VVb`(V&wQNYT zX`5tmpE8ke5AB~j#X|f;8Zdti>A-R^-Qn9aiEev~0F~}qZX?c#ZkhIC2TwQFWcQfo zv_*!*OV7ZgeSX!}Eze3nPScoPkx0Fq2IL7Kx9l@j@VMhzYquqtdSR3rVO;ldqrI;% z&l7#4cpbnWV9jTYEd$o>V|)|xaLEdMh_C(doIP(t?TZm5jI6K?uM>YhP^Zw|<>$=}tx`d@4BHStUj zgf*uJ%kIwvR%d!3E_td4OKPeI*}&p^ep;966Fm^e)!t8IJzyfD+QZI74tv1E=bIG1r3o(#P=Loawo>~fWa@J|nsIXkG7=788R;JB4rmLH9R Date: Wed, 19 Apr 2023 01:52:20 +0200 Subject: [PATCH 092/131] Reusable TMs (#2903) * Reusable TMs * Forgot about Gen9 making TMs expendable again * Change importance check based on Alex's suggestion * Prevent items with importance from being bought more than once * Change importance check to ghoul's suggestion * Update include/config/item.h Co-authored-by: Eduardo Quezada D'Ottone --------- Co-authored-by: Eduardo Quezada D'Ottone --- include/config/item.h | 3 ++ include/strings.h | 2 + src/data/items.h | 100 ++++++++++++++++++++++++++++++++++++++++++ src/party_menu.c | 2 +- src/shop.c | 22 ++++++++-- src/strings.c | 2 + 6 files changed, 126 insertions(+), 5 deletions(-) diff --git a/include/config/item.h b/include/config/item.h index 031af37241..f707b7a540 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -9,6 +9,9 @@ #define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. #define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8, the Vitamins no longer have a cap of 100 EV per stat. +// TM config +#define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. + // Repel/Lure config // These two settings are both independent and complementary. #define VAR_LAST_REPEL_LURE_USED 0 // If this var has been assigned, last Repel/Lure used will be saved and the player will get prompted with the vanilla repel YES/NO option, unless I_REPEL_LURE_MENU is set to TRUE. diff --git a/include/strings.h b/include/strings.h index 959bb8c22d..f17d509e85 100644 --- a/include/strings.h +++ b/include/strings.h @@ -1025,6 +1025,8 @@ extern const u8 gText_ThrowInPremierBall[]; extern const u8 gText_ShopBuy[]; extern const u8 gText_ShopSell[]; extern const u8 gText_ShopQuit[]; +extern const u8 gText_SoldOut[]; +extern const u8 gText_SoldOut2[]; extern const u8 gText_OhABite[]; extern const u8 gText_PokemonOnHook[]; diff --git a/src/data/items.h b/src/data/items.h index fc99e10373..84436be55b 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -7728,6 +7728,7 @@ const struct Item gItems[] = .itemId = ITEM_TM01_FOCUS_PUNCH, .price = 3000, .description = sTM01Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7739,6 +7740,7 @@ const struct Item gItems[] = .itemId = ITEM_TM02_DRAGON_CLAW, .price = 3000, .description = sTM02Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7750,6 +7752,7 @@ const struct Item gItems[] = .itemId = ITEM_TM03_WATER_PULSE, .price = 3000, .description = sTM03Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7761,6 +7764,7 @@ const struct Item gItems[] = .itemId = ITEM_TM04_CALM_MIND, .price = 3000, .description = sTM04Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7772,6 +7776,7 @@ const struct Item gItems[] = .itemId = ITEM_TM05_ROAR, .price = 1000, .description = sTM05Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7783,6 +7788,7 @@ const struct Item gItems[] = .itemId = ITEM_TM06_TOXIC, .price = 3000, .description = sTM06Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7794,6 +7800,7 @@ const struct Item gItems[] = .itemId = ITEM_TM07_HAIL, .price = 3000, .description = sTM07Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7805,6 +7812,7 @@ const struct Item gItems[] = .itemId = ITEM_TM08_BULK_UP, .price = 3000, .description = sTM08Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7816,6 +7824,7 @@ const struct Item gItems[] = .itemId = ITEM_TM09_BULLET_SEED, .price = 3000, .description = sTM09Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7827,6 +7836,7 @@ const struct Item gItems[] = .itemId = ITEM_TM10_HIDDEN_POWER, .price = 3000, .description = sTM10Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7838,6 +7848,7 @@ const struct Item gItems[] = .itemId = ITEM_TM11_SUNNY_DAY, .price = 2000, .description = sTM11Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7849,6 +7860,7 @@ const struct Item gItems[] = .itemId = ITEM_TM12_TAUNT, .price = 3000, .description = sTM12Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7860,6 +7872,7 @@ const struct Item gItems[] = .itemId = ITEM_TM13_ICE_BEAM, .price = 3000, .description = sTM13Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7871,6 +7884,7 @@ const struct Item gItems[] = .itemId = ITEM_TM14_BLIZZARD, .price = 5500, .description = sTM14Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7882,6 +7896,7 @@ const struct Item gItems[] = .itemId = ITEM_TM15_HYPER_BEAM, .price = 7500, .description = sTM15Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7893,6 +7908,7 @@ const struct Item gItems[] = .itemId = ITEM_TM16_LIGHT_SCREEN, .price = 3000, .description = sTM16Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7904,6 +7920,7 @@ const struct Item gItems[] = .itemId = ITEM_TM17_PROTECT, .price = 3000, .description = sTM17Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7915,6 +7932,7 @@ const struct Item gItems[] = .itemId = ITEM_TM18_RAIN_DANCE, .price = 2000, .description = sTM18Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7926,6 +7944,7 @@ const struct Item gItems[] = .itemId = ITEM_TM19_GIGA_DRAIN, .price = 3000, .description = sTM19Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7937,6 +7956,7 @@ const struct Item gItems[] = .itemId = ITEM_TM20_SAFEGUARD, .price = 3000, .description = sTM20Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7948,6 +7968,7 @@ const struct Item gItems[] = .itemId = ITEM_TM21_FRUSTRATION, .price = 1000, .description = sTM21Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7959,6 +7980,7 @@ const struct Item gItems[] = .itemId = ITEM_TM22_SOLAR_BEAM, .price = 3000, .description = sTM22Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7970,6 +7992,7 @@ const struct Item gItems[] = .itemId = ITEM_TM23_IRON_TAIL, .price = 3000, .description = sTM23Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7981,6 +8004,7 @@ const struct Item gItems[] = .itemId = ITEM_TM24_THUNDERBOLT, .price = 3000, .description = sTM24Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7992,6 +8016,7 @@ const struct Item gItems[] = .itemId = ITEM_TM25_THUNDER, .price = 5500, .description = sTM25Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8003,6 +8028,7 @@ const struct Item gItems[] = .itemId = ITEM_TM26_EARTHQUAKE, .price = 3000, .description = sTM26Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8014,6 +8040,7 @@ const struct Item gItems[] = .itemId = ITEM_TM27_RETURN, .price = 1000, .description = sTM27Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8025,6 +8052,7 @@ const struct Item gItems[] = .itemId = ITEM_TM28_DIG, .price = 2000, .description = sTM28Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8036,6 +8064,7 @@ const struct Item gItems[] = .itemId = ITEM_TM29_PSYCHIC, .price = 2000, .description = sTM29Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8047,6 +8076,7 @@ const struct Item gItems[] = .itemId = ITEM_TM30_SHADOW_BALL, .price = 3000, .description = sTM30Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8058,6 +8088,7 @@ const struct Item gItems[] = .itemId = ITEM_TM31_BRICK_BREAK, .price = 3000, .description = sTM31Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8069,6 +8100,7 @@ const struct Item gItems[] = .itemId = ITEM_TM32_DOUBLE_TEAM, .price = 2000, .description = sTM32Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8080,6 +8112,7 @@ const struct Item gItems[] = .itemId = ITEM_TM33_REFLECT, .price = 3000, .description = sTM33Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8091,6 +8124,7 @@ const struct Item gItems[] = .itemId = ITEM_TM34_SHOCK_WAVE, .price = 3000, .description = sTM34Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8102,6 +8136,7 @@ const struct Item gItems[] = .itemId = ITEM_TM35_FLAMETHROWER, .price = 3000, .description = sTM35Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8113,6 +8148,7 @@ const struct Item gItems[] = .itemId = ITEM_TM36_SLUDGE_BOMB, .price = 1000, .description = sTM36Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8124,6 +8160,7 @@ const struct Item gItems[] = .itemId = ITEM_TM37_SANDSTORM, .price = 2000, .description = sTM37Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8135,6 +8172,7 @@ const struct Item gItems[] = .itemId = ITEM_TM38_FIRE_BLAST, .price = 5500, .description = sTM38Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8146,6 +8184,7 @@ const struct Item gItems[] = .itemId = ITEM_TM39_ROCK_TOMB, .price = 3000, .description = sTM39Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8157,6 +8196,7 @@ const struct Item gItems[] = .itemId = ITEM_TM40_AERIAL_ACE, .price = 3000, .description = sTM40Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8168,6 +8208,7 @@ const struct Item gItems[] = .itemId = ITEM_TM41_TORMENT, .price = 3000, .description = sTM41Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8179,6 +8220,7 @@ const struct Item gItems[] = .itemId = ITEM_TM42_FACADE, .price = 3000, .description = sTM42Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8190,6 +8232,7 @@ const struct Item gItems[] = .itemId = ITEM_TM43_SECRET_POWER, .price = 3000, .description = sTM43Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8201,6 +8244,7 @@ const struct Item gItems[] = .itemId = ITEM_TM44_REST, .price = 3000, .description = sTM44Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8212,6 +8256,7 @@ const struct Item gItems[] = .itemId = ITEM_TM45_ATTRACT, .price = 3000, .description = sTM45Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8223,6 +8268,7 @@ const struct Item gItems[] = .itemId = ITEM_TM46_THIEF, .price = 3000, .description = sTM46Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8234,6 +8280,7 @@ const struct Item gItems[] = .itemId = ITEM_TM47_STEEL_WING, .price = 3000, .description = sTM47Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8245,6 +8292,7 @@ const struct Item gItems[] = .itemId = ITEM_TM48_SKILL_SWAP, .price = 3000, .description = sTM48Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8256,6 +8304,7 @@ const struct Item gItems[] = .itemId = ITEM_TM49_SNATCH, .price = 3000, .description = sTM49Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8267,6 +8316,7 @@ const struct Item gItems[] = .itemId = ITEM_TM50_OVERHEAT, .price = 3000, .description = sTM50Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8278,6 +8328,7 @@ const struct Item gItems[] = .itemId = ITEM_TM51, .price = 3000, .description = sTM51Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8289,6 +8340,7 @@ const struct Item gItems[] = .itemId = ITEM_TM52, .price = 3000, .description = sTM52Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8300,6 +8352,7 @@ const struct Item gItems[] = .itemId = ITEM_TM53, .price = 3000, .description = sTM53Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8311,6 +8364,7 @@ const struct Item gItems[] = .itemId = ITEM_TM54, .price = 3000, .description = sTM54Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8322,6 +8376,7 @@ const struct Item gItems[] = .itemId = ITEM_TM55, .price = 3000, .description = sTM55Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8333,6 +8388,7 @@ const struct Item gItems[] = .itemId = ITEM_TM56, .price = 3000, .description = sTM56Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8344,6 +8400,7 @@ const struct Item gItems[] = .itemId = ITEM_TM57, .price = 3000, .description = sTM57Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8355,6 +8412,7 @@ const struct Item gItems[] = .itemId = ITEM_TM58, .price = 3000, .description = sTM58Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8366,6 +8424,7 @@ const struct Item gItems[] = .itemId = ITEM_TM59, .price = 3000, .description = sTM59Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8377,6 +8436,7 @@ const struct Item gItems[] = .itemId = ITEM_TM60, .price = 3000, .description = sTM60Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8388,6 +8448,7 @@ const struct Item gItems[] = .itemId = ITEM_TM61, .price = 3000, .description = sTM61Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8399,6 +8460,7 @@ const struct Item gItems[] = .itemId = ITEM_TM62, .price = 3000, .description = sTM62Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8410,6 +8472,7 @@ const struct Item gItems[] = .itemId = ITEM_TM63, .price = 3000, .description = sTM63Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8421,6 +8484,7 @@ const struct Item gItems[] = .itemId = ITEM_TM64, .price = 3000, .description = sTM64Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8432,6 +8496,7 @@ const struct Item gItems[] = .itemId = ITEM_TM65, .price = 3000, .description = sTM65Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8443,6 +8508,7 @@ const struct Item gItems[] = .itemId = ITEM_TM66, .price = 3000, .description = sTM66Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8454,6 +8520,7 @@ const struct Item gItems[] = .itemId = ITEM_TM67, .price = 3000, .description = sTM67Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8465,6 +8532,7 @@ const struct Item gItems[] = .itemId = ITEM_TM68, .price = 3000, .description = sTM68Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8476,6 +8544,7 @@ const struct Item gItems[] = .itemId = ITEM_TM69, .price = 3000, .description = sTM69Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8487,6 +8556,7 @@ const struct Item gItems[] = .itemId = ITEM_TM70, .price = 3000, .description = sTM70Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8498,6 +8568,7 @@ const struct Item gItems[] = .itemId = ITEM_TM71, .price = 3000, .description = sTM71Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8509,6 +8580,7 @@ const struct Item gItems[] = .itemId = ITEM_TM72, .price = 3000, .description = sTM72Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8520,6 +8592,7 @@ const struct Item gItems[] = .itemId = ITEM_TM73, .price = 3000, .description = sTM73Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8531,6 +8604,7 @@ const struct Item gItems[] = .itemId = ITEM_TM74, .price = 3000, .description = sTM74Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8542,6 +8616,7 @@ const struct Item gItems[] = .itemId = ITEM_TM75, .price = 3000, .description = sTM75Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8553,6 +8628,7 @@ const struct Item gItems[] = .itemId = ITEM_TM76, .price = 3000, .description = sTM76Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8564,6 +8640,7 @@ const struct Item gItems[] = .itemId = ITEM_TM77, .price = 3000, .description = sTM77Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8575,6 +8652,7 @@ const struct Item gItems[] = .itemId = ITEM_TM78, .price = 3000, .description = sTM78Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8586,6 +8664,7 @@ const struct Item gItems[] = .itemId = ITEM_TM79, .price = 3000, .description = sTM79Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8597,6 +8676,7 @@ const struct Item gItems[] = .itemId = ITEM_TM80, .price = 3000, .description = sTM80Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8608,6 +8688,7 @@ const struct Item gItems[] = .itemId = ITEM_TM81, .price = 3000, .description = sTM81Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8619,6 +8700,7 @@ const struct Item gItems[] = .itemId = ITEM_TM82, .price = 3000, .description = sTM82Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8630,6 +8712,7 @@ const struct Item gItems[] = .itemId = ITEM_TM83, .price = 3000, .description = sTM83Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8641,6 +8724,7 @@ const struct Item gItems[] = .itemId = ITEM_TM84, .price = 3000, .description = sTM84Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8652,6 +8736,7 @@ const struct Item gItems[] = .itemId = ITEM_TM85, .price = 3000, .description = sTM85Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8663,6 +8748,7 @@ const struct Item gItems[] = .itemId = ITEM_TM86, .price = 3000, .description = sTM86Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8674,6 +8760,7 @@ const struct Item gItems[] = .itemId = ITEM_TM87, .price = 3000, .description = sTM87Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8685,6 +8772,7 @@ const struct Item gItems[] = .itemId = ITEM_TM88, .price = 3000, .description = sTM88Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8696,6 +8784,7 @@ const struct Item gItems[] = .itemId = ITEM_TM89, .price = 3000, .description = sTM89Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8707,6 +8796,7 @@ const struct Item gItems[] = .itemId = ITEM_TM90, .price = 3000, .description = sTM90Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8718,6 +8808,7 @@ const struct Item gItems[] = .itemId = ITEM_TM91, .price = 3000, .description = sTM91Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8729,6 +8820,7 @@ const struct Item gItems[] = .itemId = ITEM_TM92, .price = 3000, .description = sTM92Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8740,6 +8832,7 @@ const struct Item gItems[] = .itemId = ITEM_TM93, .price = 3000, .description = sTM93Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8751,6 +8844,7 @@ const struct Item gItems[] = .itemId = ITEM_TM94, .price = 3000, .description = sTM94Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8762,6 +8856,7 @@ const struct Item gItems[] = .itemId = ITEM_TM95, .price = 3000, .description = sTM95Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8773,6 +8868,7 @@ const struct Item gItems[] = .itemId = ITEM_TM96, .price = 3000, .description = sTM96Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8784,6 +8880,7 @@ const struct Item gItems[] = .itemId = ITEM_TM97, .price = 3000, .description = sTM97Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8795,6 +8892,7 @@ const struct Item gItems[] = .itemId = ITEM_TM98, .price = 3000, .description = sTM98Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8806,6 +8904,7 @@ const struct Item gItems[] = .itemId = ITEM_TM99, .price = 3000, .description = sTM99Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8817,6 +8916,7 @@ const struct Item gItems[] = .itemId = ITEM_TM100, .price = 3000, .description = sTM100Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, diff --git a/src/party_menu.c b/src/party_menu.c index a7ab305450..3cc3efdcdd 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5090,7 +5090,7 @@ static void Task_LearnedMove(u8 taskId) if (move[1] == 0) { AdjustFriendship(mon, FRIENDSHIP_EVENT_LEARN_TMHM); - if (item < ITEM_HM01_CUT) + if (!ItemId_GetImportance(item)) RemoveBagItem(item, 1); } GetMonNickname(mon, gStringVar1); diff --git a/src/shop.c b/src/shop.c index 8fea1e1178..6f4e093562 100644 --- a/src/shop.c +++ b/src/shop.c @@ -639,7 +639,10 @@ static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y) 5); } - StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1); + if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1))) + StringCopy(gStringVar4, gText_SoldOut2); + else + StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1); x = GetStringRightAlignXOffset(FONT_NARROW, gStringVar4, 120); AddTextPrinterParameterized4(windowId, FONT_NARROW, x, y, 0, 0, sShopBuyMenuTextColors[COLORID_ITEM_LIST], TEXT_SKIP_DRAW, gStringVar4); } @@ -989,7 +992,9 @@ static void Task_BuyMenu(u8 taskId) else sShopData->totalCost = gDecorations[itemId].price; - if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost)) + if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1))) + BuyMenuDisplayMessage(taskId, gText_SoldOut, BuyMenuReturnToItemList); + else if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost)) { BuyMenuDisplayMessage(taskId, gText_YouDontHaveMoney, BuyMenuReturnToItemList); } @@ -998,7 +1003,15 @@ static void Task_BuyMenu(u8 taskId) if (sMartInfo.martType == MART_TYPE_NORMAL) { CopyItemName(itemId, gStringVar1); - if (ItemId_GetPocket(itemId) == POCKET_TM_HM) + if (ItemId_GetImportance(itemId)) + { + ConvertIntToDecimalStringN(gStringVar2, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6); + StringExpandPlaceholders(gStringVar4, gText_YouWantedVar1ThatllBeVar2); + tItemCount = 1; + sShopData->totalCost = (ItemId_GetPrice(tItemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT)) * tItemCount; + BuyMenuDisplayMessage(taskId, gStringVar4, BuyMenuConfirmPurchase); + } + else if (ItemId_GetPocket(itemId) == POCKET_TM_HM) { StringCopy(gStringVar2, gMoveNames[ItemIdToBattleMoveId(itemId)]); BuyMenuDisplayMessage(taskId, gText_Var1CertainlyHowMany2, Task_BuyHowManyDialogueInit); @@ -1103,8 +1116,8 @@ static void BuyMenuTryMakePurchase(u8 taskId) { if (AddBagItem(tItemId, tItemCount) == TRUE) { - BuyMenuDisplayMessage(taskId, gText_HereYouGoThankYou, BuyMenuSubtractMoney); RecordItemPurchase(taskId); + BuyMenuDisplayMessage(taskId, gText_HereYouGoThankYou, BuyMenuSubtractMoney); } else { @@ -1170,6 +1183,7 @@ static void BuyMenuReturnToItemList(u8 taskId) s16 *data = gTasks[taskId].data; ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE); + RedrawListMenu(tListTaskId); BuyMenuPrintCursor(tListTaskId, COLORID_ITEM_LIST); PutWindowTilemap(WIN_ITEM_LIST); PutWindowTilemap(WIN_ITEM_DESCRIPTION); diff --git a/src/strings.c b/src/strings.c index 847b2849a6..dd632a32bd 100644 --- a/src/strings.c +++ b/src/strings.c @@ -341,6 +341,8 @@ const u8 gText_Var1DisdainfullyAteVar2[] = _("{STR_VAR_1} disdainfully ate the\n const u8 gText_ShopBuy[] = _("BUY"); const u8 gText_ShopSell[] = _("SELL"); const u8 gText_ShopQuit[] = _("QUIT"); +const u8 gText_SoldOut[] = _("I'm sorry, but that item is sold out.\p"); +const u8 gText_SoldOut2[] = _("SOLD OUT"); const u8 gText_InBagVar1[] = _("IN BAG: {STR_VAR_1}"); const u8 gText_QuitShopping[] = _("Quit shopping."); const u8 gText_Var1CertainlyHowMany[] = _("{STR_VAR_1}? Certainly.\nHow many would you like?"); From 52ce39924051c3a94f96eabb4ac9fb5b7edebf81 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Wed, 19 Apr 2023 17:01:00 +0200 Subject: [PATCH 093/131] Fix TM reusability shortcomings (#2930) --- include/strings.h | 2 +- src/shop.c | 4 ++-- src/strings.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/strings.h b/include/strings.h index f17d509e85..72109ed945 100644 --- a/include/strings.h +++ b/include/strings.h @@ -1025,8 +1025,8 @@ extern const u8 gText_ThrowInPremierBall[]; extern const u8 gText_ShopBuy[]; extern const u8 gText_ShopSell[]; extern const u8 gText_ShopQuit[]; +extern const u8 gText_ThatItemIsSoldOut[]; extern const u8 gText_SoldOut[]; -extern const u8 gText_SoldOut2[]; extern const u8 gText_OhABite[]; extern const u8 gText_PokemonOnHook[]; diff --git a/src/shop.c b/src/shop.c index 6f4e093562..b4978f063e 100644 --- a/src/shop.c +++ b/src/shop.c @@ -640,7 +640,7 @@ static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y) } if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1))) - StringCopy(gStringVar4, gText_SoldOut2); + StringCopy(gStringVar4, gText_SoldOut); else StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1); x = GetStringRightAlignXOffset(FONT_NARROW, gStringVar4, 120); @@ -993,7 +993,7 @@ static void Task_BuyMenu(u8 taskId) sShopData->totalCost = gDecorations[itemId].price; if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1))) - BuyMenuDisplayMessage(taskId, gText_SoldOut, BuyMenuReturnToItemList); + BuyMenuDisplayMessage(taskId, gText_ThatItemIsSoldOut, BuyMenuReturnToItemList); else if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost)) { BuyMenuDisplayMessage(taskId, gText_YouDontHaveMoney, BuyMenuReturnToItemList); diff --git a/src/strings.c b/src/strings.c index dd632a32bd..75ff2ef994 100644 --- a/src/strings.c +++ b/src/strings.c @@ -341,8 +341,8 @@ const u8 gText_Var1DisdainfullyAteVar2[] = _("{STR_VAR_1} disdainfully ate the\n const u8 gText_ShopBuy[] = _("BUY"); const u8 gText_ShopSell[] = _("SELL"); const u8 gText_ShopQuit[] = _("QUIT"); -const u8 gText_SoldOut[] = _("I'm sorry, but that item is sold out.\p"); -const u8 gText_SoldOut2[] = _("SOLD OUT"); +const u8 gText_ThatItemIsSoldOut[] = _("I'm sorry, but that item is sold out.{PAUSE_UNTIL_PRESS}"); +const u8 gText_SoldOut[] = _("SOLD OUT"); const u8 gText_InBagVar1[] = _("IN BAG: {STR_VAR_1}"); const u8 gText_QuitShopping[] = _("Quit shopping."); const u8 gText_Var1CertainlyHowMany[] = _("{STR_VAR_1}? Certainly.\nHow many would you like?"); From d3fed5639b4b56836221ccf6232387e2d63a3eed Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Wed, 19 Apr 2023 15:54:57 -0700 Subject: [PATCH 094/131] Added config to enable NEW_ROCKS_PARTICLE (#2929) Co-authored-by: LOuroboros --- include/config/battle.h | 1 + src/data/battle_anim.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index ad31621623..3e9ec9b9a5 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -195,6 +195,7 @@ #define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. #define B_NEW_LEECH_SEED_PARTICLE FALSE // If set to TRUE, it updates Leech Seed's animation particle. #define B_NEW_HORN_ATTACK_PARTICLE FALSE // If set to TRUE, it updates Horn Attack's horn particle. +#define B_NEW_ROCKS_PARTICLE TRUE // If set to TRUE, it updates rock particles. #define B_NEW_LEAF_PARTICLE FALSE // If set to TRUE, it updates leaf particle. #define B_NEW_EMBER_PARTICLES FALSE // If set to TRUE, it updates Ember's fire particle. #define B_NEW_MEAN_LOOK_PARTICLE FALSE // If set to TRUE, it updates Mean Look's eye particle. diff --git a/src/data/battle_anim.h b/src/data/battle_anim.h index b1f158310a..46293e3a0a 100644 --- a/src/data/battle_anim.h +++ b/src/data/battle_anim.h @@ -1079,7 +1079,7 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] = {gBattleAnimSpriteGfx_RedFist, 0x0200, ANIM_TAG_RED_FIST}, {gBattleAnimSpriteGfx_SlamHit, 0x1000, ANIM_TAG_SLAM_HIT}, {gBattleAnimSpriteGfx_Ring, 0x0180, ANIM_TAG_RING}, -#if NEW_ROCKS_PARTICLE +#if B_NEW_ROCKS_PARTICLE == TRUE {gBattleAnimSpriteGfx_NewRocks, 0x0C00, ANIM_TAG_ROCKS}, #else {gBattleAnimSpriteGfx_Rocks, 0x0C00, ANIM_TAG_ROCKS}, @@ -1529,7 +1529,7 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] = {gBattleAnimSpritePal_HumanoidFoot, ANIM_TAG_RED_FIST}, {gBattleAnimSpritePal_SlamHit, ANIM_TAG_SLAM_HIT}, {gBattleAnimSpritePal_Ring, ANIM_TAG_RING}, -#if NEW_ROCKS_PARTICLE +#if B_NEW_ROCKS_PARTICLE == TRUE {gBattleAnimSpritePal_NewRocks, ANIM_TAG_ROCKS}, #else {gBattleAnimSpritePal_Rocks, ANIM_TAG_ROCKS}, From 216b7a4dfd4521104ca4f1a2a07bf58fd56539a7 Mon Sep 17 00:00:00 2001 From: CallmeEchoo Date: Thu, 20 Apr 2023 09:44:18 +0200 Subject: [PATCH 095/131] fix dire hit and paralyze heal --- src/item.c | 2 ++ src/item_use.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/item.c b/src/item.c index da57c40766..b2b19480a3 100644 --- a/src/item.c +++ b/src/item.c @@ -973,6 +973,8 @@ u32 GetItemStatus1Mask(u16 itemId) const u8 *effect = GetItemEffect(itemId); switch (effect[3]) { + case ITEM3_PARALYSIS: + return STATUS1_PARALYSIS; case ITEM3_FREEZE: return STATUS1_FREEZE; case ITEM3_BURN: diff --git a/src/item_use.c b/src/item_use.c index 8bcadfb2eb..3a838288b1 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1154,7 +1154,7 @@ static bool32 CannotUseBagBattleItem(u16 itemId) } // Dire Hit if (battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY - && !(gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY)) + && (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY)) { cannotUse++; } From 3aec63b8cfb23b0983b92ba03e89c31db84b20a1 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 20 Apr 2023 15:08:42 +0200 Subject: [PATCH 096/131] new define to restore items after battle --- include/battle.h | 4 ++-- include/battle_util.h | 2 +- include/config/battle.h | 1 + src/battle_main.c | 6 +++--- src/battle_script_commands.c | 14 +++++++------- src/battle_util.c | 18 ++++++++++-------- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/include/battle.h b/include/battle.h index 46975bec3c..f86a5c975c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -517,7 +517,7 @@ struct ZMoveData u8 splits[MAX_BATTLERS_COUNT]; }; -struct StolenItem +struct LostItem { u16 originalItem:15; u16 stolen:1; @@ -640,7 +640,7 @@ struct BattleStruct u16 moveEffect2; // For Knock Off u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon. u8 quickClawBattlerId; - struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member) + struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member) u8 blunderPolicy:1; // should blunder policy activate u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky u8 forcedSwitch:4; // For each battler diff --git a/include/battle_util.h b/include/battle_util.h index 0661081e43..b83209a697 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -197,7 +197,7 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId); u8 GetSplitBasedOnStats(u8 battlerId); void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); bool32 TestSheerForceFlag(u8 battler, u16 move); -void TryRestoreStolenItems(void); +void TryRestoreHeldItems(void); bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item); void TrySaveExchangedItem(u8 battlerId, u16 stolenItem); bool32 IsPartnerMonFromSameTrainer(u8 battlerId); diff --git a/include/config/battle.h b/include/config/battle.h index 3e9ec9b9a5..4bead3ae83 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -126,6 +126,7 @@ #define B_X_ITEMS_BUFF GEN_LATEST // In Gen7+, the X Items raise a stat by 2 stages instead of 1. #define B_MENTAL_HERB GEN_LATEST // In Gen5+, the Mental Herb cures Taunt, Encore, Torment, Heal Block, and Disable in addition to Infatuation from before. #define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items. +#define B_RESTORE_HELD_BATTLE_ITEMS TRUE // In Gen9 all non berry items are restored after battle. #define B_SOUL_DEW_BOOST GEN_LATEST // In Gens3-6, Soul Dew boosts Lati@s' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead. #define B_NET_BALL_MODIFIER GEN_LATEST // In Gen7+, Net Ball's catch multiplier is x5 instead of x3. #define B_DIVE_BALL_MODIFIER GEN_LATEST // In Gen4+, Dive Ball's effectiveness increases by when Surfing or Fishing. diff --git a/src/battle_main.c b/src/battle_main.c index a5a9b5bbf6..01d79db3eb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3189,7 +3189,7 @@ static void BattleStartClearSetData(void) { gBattleStruct->usedHeldItems[i][B_SIDE_PLAYER] = 0; gBattleStruct->usedHeldItems[i][B_SIDE_OPPONENT] = 0; - gBattleStruct->itemStolen[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + gBattleStruct->itemLost[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); gPartyCriticalHits[i] = 0; gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_PLAYER] = FALSE; gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_OPPONENT] = FALSE; @@ -5387,9 +5387,9 @@ static void HandleEndTurn_FinishBattle(void) TestRunner_Battle_AfterLastTurn(); BeginFastPaletteFade(3); FadeOutMapMusic(5); - #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE + #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE || B_RESTORE_HELD_BATTLE_ITEMS == TRUE if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - TryRestoreStolenItems(); + TryRestoreHeldItems(); #endif for (i = 0; i < PARTY_SIZE; i++) { diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4e1494ce38..228cbb8120 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7892,7 +7892,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef) // Called by Cmd_removeitem. itemId represents the item that was removed, not being given. static bool32 TrySymbiosis(u32 battler, u32 itemId) { - if (!gBattleStruct->itemStolen[gBattlerPartyIndexes[battler]].stolen + if (!gBattleStruct->itemLost[gBattlerPartyIndexes[battler]].stolen && gBattleStruct->changedItems[battler] == ITEM_NONE && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_BUTTON && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_PACK @@ -11264,7 +11264,7 @@ static void Cmd_various(void) // Open party menu, wait to go to next instruction. else - { + { BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); MarkBattlerForControllerExec(gBattlerAttacker); } @@ -16469,7 +16469,7 @@ void BS_ItemRestoreHP(void) { } if (hp + healAmount > maxHP) healAmount = maxHP - hp; - + // Heal is applied as move damage if battler is active. if (battlerId != MAX_BATTLERS_COUNT && hp != 0) { @@ -16494,10 +16494,10 @@ void BS_ItemRestoreHP(void) { void BS_ItemCureStatus(void) { NATIVE_ARGS(); struct Pokemon *party = (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - + // Heal Status1 conditions. HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], gBattleStruct->itemPartyIndex[gBattlerAttacker], GetItemStatus1Mask(gLastUsedItem), gBattlerAttacker); - + // Heal Status2 conditions if battler is active. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) { @@ -16506,10 +16506,10 @@ void BS_ItemCureStatus(void) { else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) { - gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); + gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker); } - + if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; diff --git a/src/battle_util.c b/src/battle_util.c index ac274bf0f8..e057b78dc3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10536,18 +10536,20 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast) } } -void TryRestoreStolenItems(void) +void TryRestoreHeldItems(void) { u32 i; - u16 stolenItem = ITEM_NONE; + u16 lostItem = ITEM_NONE; for (i = 0; i < PARTY_SIZE; i++) { - if (gBattleStruct->itemStolen[i].stolen) + #if B_RESTORE_HELD_BATTLE_ITEMS == FALSE + if (gBattleStruct->itemLost[i].stolen) + #endif { - stolenItem = gBattleStruct->itemStolen[i].originalItem; - if (stolenItem != ITEM_NONE && ItemId_GetPocket(stolenItem) != POCKET_BERRIES) - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &stolenItem); // Restore stolen non-berry items + lostItem = gBattleStruct->itemLost[i].originalItem; + if (lostItem != ITEM_NONE && ItemId_GetPocket(lostItem) != POCKET_BERRIES) + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &lostItem); // Restore stolen non-berry items } } } @@ -10601,8 +10603,8 @@ void TrySaveExchangedItem(u8 battlerId, u16 stolenItem) if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && GetBattlerSide(battlerId) == B_SIDE_PLAYER - && stolenItem == gBattleStruct->itemStolen[gBattlerPartyIndexes[battlerId]].originalItem) - gBattleStruct->itemStolen[gBattlerPartyIndexes[battlerId]].stolen = TRUE; + && stolenItem == gBattleStruct->itemLost[gBattlerPartyIndexes[battlerId]].originalItem) + gBattleStruct->itemLost[gBattlerPartyIndexes[battlerId]].stolen = TRUE; #endif } From 6c7f5881e453631a1f336618b7e0120c33b7f140 Mon Sep 17 00:00:00 2001 From: citrusbolt <32605812+citrusbolt@users.noreply.github.com> Date: Thu, 20 Apr 2023 08:05:32 -0600 Subject: [PATCH 097/131] Add two EV-related configs (#2825) --- include/config/item.h | 13 +++++++------ include/config/pokemon.h | 1 + include/constants/pokemon.h | 4 ++++ src/pokemon.c | 12 ++++++++++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/config/item.h b/include/config/item.h index f707b7a540..09008d0f24 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -2,12 +2,13 @@ #define GUARD_CONFIG_ITEM_H // Item config -#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects. -#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items. -#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts. -#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to. -#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. -#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8, the Vitamins no longer have a cap of 100 EV per stat. +#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects. +#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items. +#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts. +#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to. +#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. +#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat. +#define I_BERRY_EV_JUMP GEN_LATEST // In Gen4 only, EV-lowering Berries lower a stat's EV to 100 if it is above 100. // TM config #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. diff --git a/include/config/pokemon.h b/include/config/pokemon.h index ce5faf2a6e..1cde573c96 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -21,6 +21,7 @@ // Other settings #define P_LEGENDARY_PERFECT_IVS GEN_LATEST // Since Gen 6, Legendaries, Mythicals and Ultra Beasts found in the wild or given through gifts have at least 3 perfect IVs. +#define P_EV_CAP GEN_LATEST // Since Gen 6, the max EVs per stat is 252 instead of 255. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index cf6cc8751b..ddf879854e 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -201,7 +201,11 @@ #define MAX_PER_STAT_IVS 31 #define MAX_IV_MASK 31 #define USE_RANDOM_IVS (MAX_PER_STAT_IVS + 1) +#if P_EV_CAP >= GEN_6 +#define MAX_PER_STAT_EVS 252 +#else #define MAX_PER_STAT_EVS 255 +#endif #define MAX_TOTAL_EVS 510 #if I_VITAMIN_EV_CAP >= GEN_8 #define EV_ITEM_RAISE_LIMIT MAX_PER_STAT_EVS diff --git a/src/pokemon.c b/src/pokemon.c index 46eca90b29..e82cb98c30 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5854,7 +5854,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (itemEffect[10] & ITEM10_IS_VITAMIN) evCap = EV_ITEM_RAISE_LIMIT; else - evCap = 252; + evCap = MAX_PER_STAT_EVS; if (dataSigned >= evCap) break; @@ -5880,6 +5880,10 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov break; } dataSigned += evChange; + #if I_EV_LOWERING_BERRY_JUMP == GEN_4 + if (dataSigned > 100) + dataSigned = 100; + #endif if (dataSigned < 0) dataSigned = 0; } @@ -6030,7 +6034,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (itemEffect[10] & ITEM10_IS_VITAMIN) evCap = EV_ITEM_RAISE_LIMIT; else - evCap = 252; + evCap = MAX_PER_STAT_EVS; if (dataSigned >= evCap) break; @@ -6056,6 +6060,10 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov break; } dataSigned += evChange; + #if I_BERRY_EV_JUMP == GEN_4 + if (dataSigned > 100) + dataSigned = 100; + #endif if (dataSigned < 0) dataSigned = 0; } From ae80d545c5b4f2f86baf702d4527d88c11b935b0 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 20 Apr 2023 16:12:11 +0200 Subject: [PATCH 098/131] Support for multi battles where Trainer has only one mon (#2670) --- src/battle_controller_opponent.c | 12 +++++++----- src/battle_interface.c | 5 +++++ src/battle_main.c | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index cb0499ac8f..4eda81b094 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -228,9 +228,11 @@ static void Intro_DelayAndEnd(void) } } -static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active. +static bool32 TwoIntroMons(u32 battlerId) // Double battle with both opponent pokemon active. { - return (IsDoubleBattle() && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]])); + return (IsDoubleBattle() + && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[battlerId]]) + && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]])); } static void Intro_WaitForShinyAnimAndHealthbox(void) @@ -1969,7 +1971,7 @@ static void SpriteCB_FreeOpponentSprite(struct Sprite *sprite) static void Task_StartSendOutAnim(u8 taskId) { - u8 savedActiveBank = gActiveBattler; + u8 savedActiveBattler = gActiveBattler; gActiveBattler = gTasks[taskId].data[0]; if ((!TwoIntroMons(gActiveBattler) || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) && !BATTLE_TWO_VS_ONE_OPPONENT) @@ -1977,7 +1979,7 @@ static void Task_StartSendOutAnim(u8 taskId) gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); } - else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) || (BATTLE_TWO_VS_ONE_OPPONENT && !TwoIntroMons(gActiveBattler))) { gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); @@ -1992,7 +1994,7 @@ static void Task_StartSendOutAnim(u8 taskId) gActiveBattler ^= BIT_FLANK; } gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; - gActiveBattler = savedActiveBank; + gActiveBattler = savedActiveBattler; DestroyTask(taskId); } diff --git a/src/battle_interface.c b/src/battle_interface.c index 7f7e1d20f0..bbe61a3727 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -690,12 +690,17 @@ static void InitLastUsedBallAssets(void) } // This function is here to cover a specific case - one player's mon in a 2 vs 1 double battle. In this scenario - display singles layout. +// The same goes for a 2 vs 1 where opponent has only one pokemon. u32 WhichBattleCoords(u32 battlerId) // 0 - singles, 1 - doubles { if (GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT && gPlayerPartyCount == 1 && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) return 0; + else if (GetBattlerPosition(battlerId) == B_POSITION_OPPONENT_LEFT + && gEnemyPartyCount == 1 + && !(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + return 0; else return IsDoubleBattle(); } diff --git a/src/battle_main.c b/src/battle_main.c index a5a9b5bbf6..2eecda65b2 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -594,6 +594,7 @@ static void CB2_InitBattleInternal(void) if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], gTrainerBattleOpponent_B, FALSE); SetWildMonHeldItem(); + CalculateEnemyPartyCount(); } gMain.inBattle = TRUE; From 4a08ede2c49ba55ac9d358d95ee240b238325192 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 21 Apr 2023 20:13:30 +0200 Subject: [PATCH 099/131] Add GetMovesArray in GetMovesArray --- src/battle_ai_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 05e7aec58f..53b5ebed6c 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -477,7 +477,7 @@ bool32 IsAiBattlerAware(u32 battlerId) { if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT) return TRUE; - + return BattlerHasAi(battlerId); } @@ -1129,7 +1129,7 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) { s32 i, dmg; u32 unusable = AI_DATA->moveLimitations[battlerDef]; - u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef]; + u16 *moves = GetMovesArray(battlerDef); for (i = 0; i < MAX_MON_MOVES; i++) { From 30204e99533bf826486c3cd535a04a2c97dc5e09 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 21 Apr 2023 20:59:54 +0200 Subject: [PATCH 100/131] fix wrong z-move ususage --- src/battle_z_move.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/battle_z_move.c b/src/battle_z_move.c index 104a44daa5..f435253c7b 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -215,11 +215,7 @@ bool32 IsViableZMove(u8 battlerId, u16 move) if (move != MOVE_NONE && zMove != MOVE_Z_STATUS && gBattleMoves[move].type == ItemId_GetSecondaryId(item)) { - if (IS_MOVE_STATUS(move)) - gBattleStruct->zmove.chosenZMove = move; - else - gBattleStruct->zmove.chosenZMove = GetTypeBasedZMove(move, battlerId); - + gBattleStruct->zmove.chosenZMove = GetTypeBasedZMove(move, battlerId); return TRUE; } } From 623e7c5f25f79599ff1de98704258f79e8c28ab2 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 22 Apr 2023 18:23:08 +0200 Subject: [PATCH 101/131] Add Frostbite status --- graphics/battle_interface/status.png | Bin 531 -> 559 bytes graphics/battle_interface/status2.png | Bin 531 -> 559 bytes graphics/battle_interface/status3.png | Bin 530 -> 559 bytes graphics/battle_interface/status4.png | Bin 530 -> 559 bytes graphics/interface/status_icons.png | Bin 455 -> 458 bytes include/constants/battle.h | 3 ++- include/constants/party_menu.h | 1 + src/battle_debug.c | 3 +++ src/battle_interface.c | 27 ++++++++++++++++++++++++++ src/data/party_menu.h | 4 ++-- src/party_menu.c | 2 ++ src/pokemon_summary_screen.c | 7 ++++++- 12 files changed, 43 insertions(+), 4 deletions(-) diff --git a/graphics/battle_interface/status.png b/graphics/battle_interface/status.png index 9fae45b71fff0c44e11746fb80c8f84dd1fba71a..0b212907e5574725f3c8f3d4f95a713b44fc02e2 100644 GIT binary patch delta 282 zcmV+#0piOO9{9gpz?RJ4K~n(wnoPh+X_5m2y1{`i ze@>w7Qtc=;!MvPzLzHzd7qBPucl6GYoz0XK+5%mj$9@7jcVH@>&nH~W0IpK&<=1in zM>2oM7!=&eP^n={brQz}bF-iY=;kSvz(@dhskr=F?q@%G{K-Q<;Ls1xy!zp-I(Kjd g7;W1xzm@v~WH5Z2Ai(eI00000NkvXX1g=70g10z=BLDyZ delta 253 zcmVdlu^|irf6+-qK~yM_g^$@01R)4St>)Jd48af# z!TjS{P7iiwmr_6;wpc(l89}UYokJDRTbGhj{b){Oy?|9JE}*BA?;EF{19I^7`0Kc! zmMs3!8iyu6GLw>$tnHNl0j>gY=m6Hdq!O43&@Htee;fA$d!=Esamg_Z00000NkvXXu0mjf DVL5SM diff --git a/graphics/battle_interface/status2.png b/graphics/battle_interface/status2.png index af7ce05d3bad0de62d22a478535e5939fde21c01..0b212907e5574725f3c8f3d4f95a713b44fc02e2 100644 GIT binary patch delta 282 zcmV+#0piOO9{9gpz?RJ4K~n(wnoPh+X_5m2y1{`i ze@>w7Qtc=;!MvPzLzHzd7qBPucl6GYoz0XK+5%mj$9@7jcVH@>&nH~W0IpK&<=1in zM>2oM7!=&eP^n={brQz}bF-iY=;kSvz(@dhskr=F?q@%G{K-Q<;Ls1xy!zp-I(Kjd g7;W1xzm@v~WH5Z2Ai(eI00000NkvXX1g=70g10z=BLDyZ delta 253 zcmVdlu^|irf6+-qK~yM_g^$@01R)4St>)Vh48af# z!Ti%%P7iiwmr_6;wpc(l89}UYokJDRTbGhj{b){Oy?|9JE}*BA?;EF{19I^7`0Kc! zmMs3!8iyu6GLw>$tnHNl0j>gY=m6Hdq!O43&@Htee;fA$zBOaqp_a-h00000NkvXXu0mjf DVMlTU diff --git a/graphics/battle_interface/status3.png b/graphics/battle_interface/status3.png index d0febfb17c501b1f65d1e835c79d7dfede349004..0b212907e5574725f3c8f3d4f95a713b44fc02e2 100644 GIT binary patch delta 282 zcmV+#0piOO9{9gpz?RJ4K~n(wnoPh+X_5m2y1{`i ze@>w7Qtc=;!MvPzLzHzd7qBPucl6GYoz0XK+5%mj$9@7jcVH@>&nH~W0IpK&<=1in zM>2oM7!=&eP^n={brQz}bF-iY=;kSvz(@dhskr=F?q@%G{K-Q<;Ls1xy!zp-I(Kjd g7;W1xzm@v~WH5Z2Ai(eI00000NkvXX1g=70g0>!lA^-pY delta 252 zcmVdlu^|irf6z%pK~yM_g^$@010V=Qo#o#WEWr{i z!T!q$r&ly#6p)82CQv?%AeOk!A&cj&OG(OpG^a6dz$zIV(9_E2jaAP9Irw_~IWDLi z7XK)PLlGaDNl8i8bjtq#SAk2dH^#LIXa}XSp0)ifOpjdK~mKk99TmDJKR9s zW~J&?YJl;$bYqV79v9ROi+{8xQJiN+61Sk4i`Z_!@&K+9_47uEIiOW)ef&8ts2>*p z=$%72T_)B2Xij4vU^FXQfHe=Pevw)L?Namc*SH@6AZ7&y4`C<(0000iOO9{9gpz?RJ4K~n(wnoPh+X_5m2y1{`i ze@>w7Qtc=;!MvPzLzHzd7qBPucl6GYoz0XK+5%mj$9@7jcVH@>&nH~W0IpK&<=1in zM>2oM7!=&eP^n={brQz}bF-iY=;kSvz(@dhskr=F?q@%G{K-Q<;Ls1xy!zp-I(Kjd g7;W1xzm@v~WH5Z2Ai(eI00000NkvXX1g=70g0>!lA^-pY delta 252 zcmVdlu^|irf6z%pK~yM_g^!6510V^lJa`5%|b6ik4 zEdEgnhax^Qlai9G>6HHgt^$`@Z;Wdb&<Bb!EJuavn7XN5XqBzftByK@77qQ)dgSCRb3m)q`uKBPP(LjG z(L0B5x=gD3(VWIUz-U&q0Basn{UWsh+NI{>uW>&^v1l#_UZ~0d0000${ZUD;vcm>pd`DI!0Cy|}jT zBY@5ZsM%XQ%Fv1^;NT^^CSS))*Qx9>@tn6gT9P>Hb#b(x2I!9oae(r;mk59}04`a= zHu*ZH(GR5{T_(9)a-yr7kTC_2d;*g}4HN}sa_IpqzbsK-hhQbNP|h8Qgz~wSJtmGn zv>WnHCs4$V0d&NavkxE=0YLd*GX%h60XxQU%%AmP|Nesq`TzrcDCz*QJ~Rm#D~tym ey+qJtJmw$h<04&U&$ZzI0000 delta 381 zcmV-@0fPR@1IGi97zqRe0001qplF?uEf$}&4cPmsZ^Og%s*voSJvbQfmE%tqn>opOM{2`ZkO=hUgi&Xe-w{PaGSR}@9D z(j1S)6dMJtgwo=HLDO3(C4^2uX_7NQ2TCjGKY9Ah5OM+y7J#wIDpEK`h(oir b{~>+>lF0pSLPH5(00000NkvXXu0mjf?VP2v diff --git a/include/constants/battle.h b/include/constants/battle.h index 61c3776c6c..7682b851ec 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -115,8 +115,9 @@ #define STATUS1_TOXIC_POISON (1 << 7) #define STATUS1_TOXIC_COUNTER (1 << 8 | 1 << 9 | 1 << 10 | 1 << 11) #define STATUS1_TOXIC_TURN(num) ((num) << 8) +#define STATUS1_FROSTBITE (1 << 12) #define STATUS1_PSN_ANY (STATUS1_POISON | STATUS1_TOXIC_POISON) -#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON) +#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) // Volatile status ailments // These are removed after exiting the battle or switching out diff --git a/include/constants/party_menu.h b/include/constants/party_menu.h index f28b75122f..fd94afe544 100644 --- a/include/constants/party_menu.h +++ b/include/constants/party_menu.h @@ -11,6 +11,7 @@ #define AILMENT_BRN 5 #define AILMENT_PKRS 6 #define AILMENT_FNT 7 +#define AILMENT_FSB 8 #define PARTY_LAYOUT_SINGLE 0 #define PARTY_LAYOUT_DOUBLE 1 diff --git a/src/battle_debug.c b/src/battle_debug.c index 1d690caaa0..0549cf91ed 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -181,6 +181,7 @@ static const u8 sText_SideStatus[] = _("Side Status"); static const u8 sText_MaxHp[] = _("HP Max"); static const u8 sText_CurrHp[] = _("HP Current"); static const u8 sText_Freeze[] = _("Freeze"); +static const u8 sText_Frostbite[] = _("Frostbite"); static const u8 sText_ToxicPoison[] = _("Toxic Poison"); static const u8 sText_ToxicCounter[] = _("Toxic Counter"); static const u8 sText_Flinch[] = _("Flinch"); @@ -258,6 +259,7 @@ static const struct BitfieldInfo sStatus1Bitfield[] = {/*Paralysis*/1, 6}, {/*Toxic Poison*/ 1, 7}, {/*Toxic Counter*/ 4, 8}, + {/*Frostbite*/ 1, 12}, }; static const struct BitfieldInfo sStatus2Bitfield[] = @@ -397,6 +399,7 @@ static const struct ListMenuItem sStatus1ListItems[] = {gText_Paralysis, 4}, {sText_ToxicPoison, 5}, {sText_ToxicCounter, 6}, + {sText_Frostbite, 7}, }; static const struct ListMenuItem sStatus2ListItems[] = diff --git a/src/battle_interface.c b/src/battle_interface.c index bbe61a3727..eec4e50f0d 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -73,6 +73,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER0, //status brn HEALTHBOX_GFX_34, HEALTHBOX_GFX_35, + HEALTHBOX_GFX_STATUS_FSB_BATTLER0, //status fsb + HEALTHBOX_GFX_116, + HEALTHBOX_GFX_117, HEALTHBOX_GFX_36, //misc [Black section] HEALTHBOX_GFX_37, //misc [Black section] HEALTHBOX_GFX_38, //misc [Black section] @@ -123,6 +126,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER1, //status2 "BRN" HEALTHBOX_GFX_84, HEALTHBOX_GFX_85, + HEALTHBOX_GFX_STATUS_FSB_BATTLER1, //status2 "FSB" + HEALTHBOX_GFX_118, + HEALTHBOX_GFX_119, HEALTHBOX_GFX_STATUS_PSN_BATTLER2, //status3 "PSN" HEALTHBOX_GFX_87, HEALTHBOX_GFX_88, @@ -138,6 +144,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER2, //status3 "BRN" HEALTHBOX_GFX_99, HEALTHBOX_GFX_100, + HEALTHBOX_GFX_STATUS_FSB_BATTLER2, //status3 "FSB" + HEALTHBOX_GFX_120, + HEALTHBOX_GFX_121, HEALTHBOX_GFX_STATUS_PSN_BATTLER3, //status4 "PSN" HEALTHBOX_GFX_102, HEALTHBOX_GFX_103, @@ -153,6 +162,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER3, //status4 "BRN" HEALTHBOX_GFX_114, HEALTHBOX_GFX_115, + HEALTHBOX_GFX_STATUS_FSB_BATTLER3, //status4 "FSB" + HEALTHBOX_GFX_122, + HEALTHBOX_GFX_123, HEALTHBOX_GFX_FRAME_END, HEALTHBOX_GFX_FRAME_END_BAR, }; @@ -2208,6 +2220,11 @@ static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FRZ_BATTLER0, battlerId)); statusPalId = PAL_STATUS_FRZ; } + else if (status & STATUS1_FROSTBITE) + { + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FSB_BATTLER0, battlerId)); + statusPalId = PAL_STATUS_FRZ; + } else if (status & STATUS1_PARALYSIS) { statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_PRZ_BATTLER0, battlerId)); @@ -2290,6 +2307,16 @@ static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId) else ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER3; break; + case HEALTHBOX_GFX_STATUS_FSB_BATTLER0: + if (battlerId == 0) + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER0; + else if (battlerId == 1) + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER1; + else if (battlerId == 2) + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER2; + else + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER3; + break; case HEALTHBOX_GFX_STATUS_BRN_BATTLER0: if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER0; diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 4a06fa135e..e7ebf98939 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -1054,7 +1054,7 @@ static const union AnimCmd sSpriteAnim_StatusFaint[] = ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_Blank[] = +static const union AnimCmd sSpriteAnim_StatusFrostbite[] = { ANIMCMD_FRAME(28, 0), ANIMCMD_END @@ -1069,7 +1069,7 @@ static const union AnimCmd *const sSpriteTemplate_StatusCondition[] = sSpriteAnim_StatusBurn, sSpriteAnim_StatusPokerus, sSpriteAnim_StatusFaint, - sSpriteAnim_Blank + sSpriteAnim_StatusFrostbite }; static const struct CompressedSpriteSheet sSpriteSheet_StatusIcons = diff --git a/src/party_menu.c b/src/party_menu.c index 3cc3efdcdd..43ed5818ad 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -1941,6 +1941,8 @@ u8 GetAilmentFromStatus(u32 status) return AILMENT_FRZ; if (status & STATUS1_BURN) return AILMENT_BRN; + if (status & STATUS1_FROSTBITE) + return AILMENT_FSB; return AILMENT_NONE; } diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 3313076262..f7106b8752 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -1112,6 +1112,10 @@ static const union AnimCmd sSpriteAnim_StatusFaint[] = { ANIMCMD_FRAME(24, 0, FALSE, FALSE), ANIMCMD_END }; +static const union AnimCmd sSpriteAnim_StatusFrostbite[] = { + ANIMCMD_FRAME(28, 0, FALSE, FALSE), + ANIMCMD_END +}; static const union AnimCmd *const sSpriteAnimTable_StatusCondition[] = { sSpriteAnim_StatusPoison, sSpriteAnim_StatusParalyzed, @@ -1120,11 +1124,12 @@ static const union AnimCmd *const sSpriteAnimTable_StatusCondition[] = { sSpriteAnim_StatusBurn, sSpriteAnim_StatusPokerus, sSpriteAnim_StatusFaint, + sSpriteAnim_StatusFrostbite, }; static const struct CompressedSpriteSheet sStatusIconsSpriteSheet = { .data = gStatusGfx_Icons, - .size = 0x380, + .size = 0x400, .tag = TAG_MON_STATUS }; static const struct CompressedSpritePalette sStatusIconsSpritePalette = From f50bfb37708396af5f2ab2841041927af6c18352 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 22 Apr 2023 18:47:36 +0200 Subject: [PATCH 102/131] Frostbite hurts at the end of the turn and halves SpA --- data/battle_scripts_1.s | 5 +++++ include/battle_scripts.h | 1 + include/constants/battle_string_ids.h | 3 ++- src/battle_gfx_sfx_util.c | 2 +- src/battle_message.c | 2 ++ src/battle_util.c | 26 ++++++++++++++++++++++++++ 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 0be8934127..316a179ab7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8121,6 +8121,11 @@ BattleScript_BurnTurnDmg:: waitmessage B_WAIT_TIME_LONG goto BattleScript_DoStatusTurnDmg +BattleScript_FrostbiteTurnDmg:: + printstring STRINGID_PKMNHURTBYFROSTBITE + waitmessage B_WAIT_TIME_LONG + goto BattleScript_DoStatusTurnDmg + BattleScript_MoveUsedIsFrozen:: printstring STRINGID_PKMNISFROZEN waitmessage B_WAIT_TIME_LONG diff --git a/include/battle_scripts.h b/include/battle_scripts.h index c78fcafe48..1fb7d8cc6a 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -108,6 +108,7 @@ extern const u8 BattleScript_MoveUsedWokeUp[]; extern const u8 BattleScript_MonWokeUpInUproar[]; extern const u8 BattleScript_PoisonTurnDmg[]; extern const u8 BattleScript_BurnTurnDmg[]; +extern const u8 BattleScript_FrostbiteTurnDmg[]; extern const u8 BattleScript_MoveUsedIsFrozen[]; extern const u8 BattleScript_MoveUsedUnfroze[]; extern const u8 BattleScript_DefrostedViaFireMove[]; diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index e552077534..10e2a6fe56 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -651,8 +651,9 @@ #define STRINGID_ITEMRESTOREDSPECIESHEALTH 649 #define STRINGID_ITEMCUREDSPECIESSTATUS 650 #define STRINGID_ITEMRESTOREDSPECIESPP 651 +#define STRINGID_PKMNHURTBYFROSTBITE 652 -#define BATTLESTRINGS_COUNT 652 +#define BATTLESTRINGS_COUNT 653 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index bc541f0a01..6404bb7dea 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -398,7 +398,7 @@ void InitAndLaunchChosenStatusAnimation(bool8 isStatus2, u32 status) gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive = 1; if (!isStatus2) { - if (status == STATUS1_FREEZE) + if (status == STATUS1_FREEZE || status == STATUS1_FROSTBITE) LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_FRZ); else if (status == STATUS1_POISON || status & STATUS1_TOXIC_POISON) LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_PSN); diff --git a/src/battle_message.c b/src/battle_message.c index 7df30cb296..b3be9afd1c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -103,6 +103,7 @@ static const u8 sText_PkmnEnergyDrained[] = _("{B_DEF_NAME_WITH_PREFIX} had its\ static const u8 sText_PkmnWasBurned[] = _("{B_EFF_NAME_WITH_PREFIX} was burned!"); static const u8 sText_PkmnBurnedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nburned {B_EFF_NAME_WITH_PREFIX}!"); static const u8 sText_PkmnHurtByBurn[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its burn!"); +static const u8 sText_PkmnHurtByFrostbite[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its frostbite!"); static const u8 sText_PkmnAlreadyHasBurn[] = _("{B_DEF_NAME_WITH_PREFIX} already\nhas a burn."); static const u8 sText_PkmnWasFrozen[] = _("{B_EFF_NAME_WITH_PREFIX} was\nfrozen solid!"); static const u8 sText_PkmnFrozenBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nfroze {B_EFF_NAME_WITH_PREFIX} solid!"); @@ -1428,6 +1429,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_TARGETTOOHEAVY - BATTLESTRINGS_TABLE_START] = sText_TargetTooHeavy, [STRINGID_ATTACKERLOSTELECTRICTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostElectricType, [STRINGID_PKMNSABILITYPREVENTSABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilityPreventsAbility, + [STRINGID_PKMNHURTBYFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnHurtByFrostbite, }; const u16 gTrainerUsedItemStringIds[] = diff --git a/src/battle_util.c b/src/battle_util.c index ac274bf0f8..993a0d5ab3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2523,6 +2523,7 @@ enum ENDTURN_POISON, ENDTURN_BAD_POISON, ENDTURN_BURN, + ENDTURN_FROSTBITE, ENDTURN_NIGHTMARES, ENDTURN_CURSE, ENDTURN_WRAP, @@ -2736,6 +2737,23 @@ u8 DoBattlerEndTurnEffects(void) } gBattleStruct->turnEffectsTracker++; break; + case ENDTURN_FROSTBITE: // burn + if ((gBattleMons[gActiveBattler].status1 & STATUS1_FROSTBITE) + && gBattleMons[gActiveBattler].hp != 0) + { + MAGIC_GUARD_CHECK; + #if B_BURN_DAMAGE >= GEN_7 + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + #else + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; + #endif + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_FrostbiteTurnDmg); + effect++; + } + gBattleStruct->turnEffectsTracker++; + break; case ENDTURN_NIGHTMARES: // spooky nightmares if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBattler].hp != 0) @@ -9508,6 +9526,14 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move && abilityAtk != ABILITY_GUTS) dmg = ApplyModifier(UQ_4_12(0.5), dmg); + // check frostbite + if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !IS_MOVE_PHYSICAL(move) + #if B_BURN_FACADE_DMG >= GEN_6 + && gBattleMoves[move].effect != EFFECT_FACADE + #endif + && abilityAtk != ABILITY_GUTS) + dmg = ApplyModifier(UQ_4_12(0.5), dmg); + // check sunny/rain weather if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_RAIN)) { From 9c9a1fb831eb33e9164f176052c3d5caed9eb362 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 22 Apr 2023 19:18:10 +0200 Subject: [PATCH 103/131] Allow for healing with items --- include/strings.h | 1 + src/battle_ai_switch_items.c | 2 +- src/item.c | 2 +- src/party_menu.c | 2 ++ src/pokemon.c | 2 +- src/strings.c | 1 + 6 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/strings.h b/include/strings.h index 72109ed945..4019dee0b1 100644 --- a/include/strings.h +++ b/include/strings.h @@ -475,6 +475,7 @@ extern const u8 gText_EscapeFromHere[]; extern const u8 gText_PkmnCuredOfPoison[]; extern const u8 gText_PkmnWokeUp2[]; extern const u8 gText_PkmnBurnHealed[]; +extern const u8 gText_PkmnFrostbiteHealed[]; extern const u8 gText_PkmnThawedOut[]; extern const u8 gText_PkmnCuredOfParalysis[]; extern const u8 gText_PkmnGotOverInfatuation[]; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 29911d798f..d7fd062ba2 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1079,7 +1079,7 @@ static bool8 ShouldUseItem(void) shouldUse = TRUE; if (itemEffects[3] & ITEM3_BURN && gBattleMons[gActiveBattler].status1 & STATUS1_BURN) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE) + if (itemEffects[3] & ITEM3_FREEZE && (gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE || gBattleMons[gActiveBattler].status1 & STATUS1_FROSTBITE)) shouldUse = TRUE; if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[gActiveBattler].status1 & STATUS1_PARALYSIS) shouldUse = TRUE; diff --git a/src/item.c b/src/item.c index b2b19480a3..d07e93782f 100644 --- a/src/item.c +++ b/src/item.c @@ -976,7 +976,7 @@ u32 GetItemStatus1Mask(u16 itemId) case ITEM3_PARALYSIS: return STATUS1_PARALYSIS; case ITEM3_FREEZE: - return STATUS1_FREEZE; + return STATUS1_FREEZE | STATUS1_FROSTBITE; case ITEM3_BURN: return STATUS1_BURN; case ITEM3_POISON: diff --git a/src/party_menu.c b/src/party_menu.c index 43ed5818ad..1623201b10 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4332,6 +4332,8 @@ static void GetMedicineItemEffectMessage(u16 item) break; case ITEM_EFFECT_CURE_FREEZE: StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); + // TO DO: if it heals frostbite, use the following instead: + // StringExpandPlaceholders(gStringVar4, gText_PkmnFrostbiteHealed); break; case ITEM_EFFECT_CURE_PARALYSIS: StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfParalysis); diff --git a/src/pokemon.c b/src/pokemon.c index e82cb98c30..7fc3399050 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5802,7 +5802,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov retVal = FALSE; if ((itemEffect[i] & ITEM3_BURN) && HealStatusConditions(mon, partyIndex, STATUS1_BURN, battlerId) == 0) retVal = FALSE; - if ((itemEffect[i] & ITEM3_FREEZE) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE, battlerId) == 0) + if ((itemEffect[i] & ITEM3_FREEZE) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE | STATUS1_FROSTBITE, battlerId) == 0) retVal = FALSE; if ((itemEffect[i] & ITEM3_PARALYSIS) && HealStatusConditions(mon, partyIndex, STATUS1_PARALYSIS, battlerId) == 0) retVal = FALSE; diff --git a/src/strings.c b/src/strings.c index 75ff2ef994..eb7bb8ba1f 100644 --- a/src/strings.c +++ b/src/strings.c @@ -414,6 +414,7 @@ const u8 gText_PkmnCuredOfPoison[] = _("{STR_VAR_1} was cured of its\npoisoning. const u8 gText_PkmnCuredOfParalysis[] = _("{STR_VAR_1} was cured of\nparalysis.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnWokeUp2[] = _("{STR_VAR_1} woke up.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnBurnHealed[] = _("{STR_VAR_1}'s burn was healed.{PAUSE_UNTIL_PRESS}"); +const u8 gText_PkmnFrostbiteHealed[] = _("{STR_VAR_1}'s frostbite was healed.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnThawedOut[] = _("{STR_VAR_1} was thawed out.{PAUSE_UNTIL_PRESS}"); const u8 gText_PPWasRestored[] = _("PP was restored.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnRegainhedHealth[] = _("{STR_VAR_1} regained health.{PAUSE_UNTIL_PRESS}"); // Unused From a561c6da6a1aced96f9b992ac00a83cc42420e9e Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 22 Apr 2023 23:14:49 +0200 Subject: [PATCH 104/131] Add config to Frostbite & allow it to be inflicted --- data/battle_scripts_1.s | 15 +++ include/battle_scripts.h | 1 + include/config/battle.h | 17 +-- include/constants/battle.h | 145 ++++++++++++------------ include/constants/battle_move_effects.h | 3 +- include/constants/battle_string_ids.h | 3 +- include/pokemon.h | 2 +- src/battle_message.c | 7 ++ src/battle_script_commands.c | 20 ++++ src/battle_tv.c | 1 + src/data/battle_moves.h | 36 +++++- 11 files changed, 161 insertions(+), 89 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 316a179ab7..3bfc3ac089 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -286,7 +286,11 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHealPulse @ EFFECT_HEAL_PULSE .4byte BattleScript_EffectQuash @ EFFECT_QUASH .4byte BattleScript_EffectIonDeluge @ EFFECT_ION_DELUGE +#if B_USE_FROSTBITE == TRUE + .4byte BattleScript_EffectFrostbiteHit @ EFFECT_FREEZE_DRY +#else .4byte BattleScript_EffectFreezeHit @ EFFECT_FREEZE_DRY +#endif .4byte BattleScript_EffectTopsyTurvy @ EFFECT_TOPSY_TURVY .4byte BattleScript_EffectMistyTerrain @ EFFECT_MISTY_TERRAIN .4byte BattleScript_EffectGrassyTerrain @ EFFECT_GRASSY_TERRAIN @@ -424,6 +428,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectDireClaw @ EFFECT_DIRE_CLAW .4byte BattleScript_EffectBarbBarrage @ EFFECT_BARB_BARRAGE .4byte BattleScript_EffectRevivalBlessing @ EFFECT_REVIVAL_BLESSING + .4byte BattleScript_EffectFrostbiteHit @ EFFECT_FROSTBITE_HIT BattleScript_EffectRevivalBlessing:: attackcanceler @@ -3464,6 +3469,10 @@ BattleScript_EffectBurnHit:: setmoveeffect MOVE_EFFECT_BURN goto BattleScript_EffectHit +BattleScript_EffectFrostbiteHit:: + setmoveeffect MOVE_EFFECT_FROSTBITE + goto BattleScript_EffectHit + BattleScript_EffectSleepHit:: setmoveeffect MOVE_EFFECT_SLEEP goto BattleScript_EffectHit @@ -8365,6 +8374,12 @@ BattleScript_MoveEffectBurn:: waitmessage B_WAIT_TIME_LONG goto BattleScript_UpdateEffectStatusIconRet +BattleScript_MoveEffectFrostbite:: + statusanimation BS_EFFECT_BATTLER + printfromtable gGotFrostbiteStringIds + waitmessage B_WAIT_TIME_LONG + goto BattleScript_UpdateEffectStatusIconRet + BattleScript_MoveEffectFreeze:: statusanimation BS_EFFECT_BATTLER printfromtable gGotFrozenStringIds diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 1fb7d8cc6a..9b9156eb6f 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -132,6 +132,7 @@ extern const u8 BattleScript_MoveEffectSleep[]; extern const u8 BattleScript_YawnMakesAsleep[]; extern const u8 BattleScript_MoveEffectPoison[]; extern const u8 BattleScript_MoveEffectBurn[]; +extern const u8 BattleScript_MoveEffectFrostbite[]; extern const u8 BattleScript_MoveEffectFreeze[]; extern const u8 BattleScript_MoveEffectParalysis[]; extern const u8 BattleScript_MoveEffectUproar[]; diff --git a/include/config/battle.h b/include/config/battle.h index 3e9ec9b9a5..951952416f 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -182,14 +182,15 @@ #define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. // Other settings -#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. -#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD. -#define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. -#define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. -#define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) -#define B_AFFECTION_MECHANICS FALSE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead. -#define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class. -#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level +#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. +#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD. +#define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. +#define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. +#define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) +#define B_AFFECTION_MECHANICS FALSE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead. +#define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class. +#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level +#define B_USE_FROSTBITE FALSE // In PLA, Frostbite replaces Freeze. Enabling this flag does the same here. Moves can still be cherry-picked to either Freeze or Frostbite. Freeze-Dry, Secret Power & Tri Attack depend on this config. // Animation Settings #define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. diff --git a/include/constants/battle.h b/include/constants/battle.h index 7682b851ec..0e6c66e8d6 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -306,79 +306,80 @@ #define MOVE_EFFECT_FREEZE 4 #define MOVE_EFFECT_PARALYSIS 5 #define MOVE_EFFECT_TOXIC 6 -#define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_TOXIC // All above move effects apply primary status -#define MOVE_EFFECT_CONFUSION 7 -#define MOVE_EFFECT_FLINCH 8 -#define MOVE_EFFECT_TRI_ATTACK 9 -#define MOVE_EFFECT_UPROAR 10 -#define MOVE_EFFECT_PAYDAY 11 -#define MOVE_EFFECT_CHARGING 12 -#define MOVE_EFFECT_WRAP 13 -#define MOVE_EFFECT_BURN_UP 14 // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break -#define MOVE_EFFECT_ATK_PLUS_1 15 -#define MOVE_EFFECT_DEF_PLUS_1 16 -#define MOVE_EFFECT_SPD_PLUS_1 17 -#define MOVE_EFFECT_SP_ATK_PLUS_1 18 -#define MOVE_EFFECT_SP_DEF_PLUS_1 19 -#define MOVE_EFFECT_ACC_PLUS_1 20 -#define MOVE_EFFECT_EVS_PLUS_1 21 -#define MOVE_EFFECT_ATK_MINUS_1 22 -#define MOVE_EFFECT_DEF_MINUS_1 23 -#define MOVE_EFFECT_SPD_MINUS_1 24 -#define MOVE_EFFECT_SP_ATK_MINUS_1 25 -#define MOVE_EFFECT_SP_DEF_MINUS_1 26 -#define MOVE_EFFECT_ACC_MINUS_1 27 -#define MOVE_EFFECT_EVS_MINUS_1 28 -#define MOVE_EFFECT_RECHARGE 29 -#define MOVE_EFFECT_RAGE 30 -#define MOVE_EFFECT_STEAL_ITEM 31 -#define MOVE_EFFECT_PREVENT_ESCAPE 32 -#define MOVE_EFFECT_NIGHTMARE 33 -#define MOVE_EFFECT_ALL_STATS_UP 34 -#define MOVE_EFFECT_RAPIDSPIN 35 -#define MOVE_EFFECT_REMOVE_STATUS 36 -#define MOVE_EFFECT_ATK_DEF_DOWN 37 -#define MOVE_EFFECT_SCALE_SHOT 38 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break -#define MOVE_EFFECT_ATK_PLUS_2 39 -#define MOVE_EFFECT_DEF_PLUS_2 40 -#define MOVE_EFFECT_SPD_PLUS_2 41 -#define MOVE_EFFECT_SP_ATK_PLUS_2 42 -#define MOVE_EFFECT_SP_DEF_PLUS_2 43 -#define MOVE_EFFECT_ACC_PLUS_2 44 -#define MOVE_EFFECT_EVS_PLUS_2 45 -#define MOVE_EFFECT_ATK_MINUS_2 46 -#define MOVE_EFFECT_DEF_MINUS_2 47 -#define MOVE_EFFECT_SPD_MINUS_2 48 -#define MOVE_EFFECT_SP_ATK_MINUS_2 49 -#define MOVE_EFFECT_SP_DEF_MINUS_2 50 -#define MOVE_EFFECT_ACC_MINUS_2 51 -#define MOVE_EFFECT_EVS_MINUS_2 52 -#define MOVE_EFFECT_THRASH 53 -#define MOVE_EFFECT_KNOCK_OFF 54 -#define MOVE_EFFECT_DEF_SPDEF_DOWN 55 -#define MOVE_EFFECT_CLEAR_SMOG 56 -#define MOVE_EFFECT_SP_ATK_TWO_DOWN 57 -#define MOVE_EFFECT_SMACK_DOWN 58 -#define MOVE_EFFECT_FLAME_BURST 59 -#define MOVE_EFFECT_FEINT 60 -#define MOVE_EFFECT_SPECTRAL_THIEF 61 -#define MOVE_EFFECT_V_CREATE 62 -#define MOVE_EFFECT_HAPPY_HOUR 63 -#define MOVE_EFFECT_CORE_ENFORCER 64 -#define MOVE_EFFECT_THROAT_CHOP 65 -#define MOVE_EFFECT_INCINERATE 66 -#define MOVE_EFFECT_BUG_BITE 67 -#define MOVE_EFFECT_RECOIL_HP_25 68 -#define MOVE_EFFECT_RELIC_SONG 69 -#define MOVE_EFFECT_TRAP_BOTH 70 -#define MOVE_EFFECT_DOUBLE_SHOCK 71 -#define MOVE_EFFECT_ROUND 72 -#define MOVE_EFFECT_STOCKPILE_WORE_OFF 73 -#define MOVE_EFFECT_DIRE_CLAW 74 -#define MOVE_EFFECT_STEALTH_ROCK 75 -#define MOVE_EFFECT_SPIKES 76 +#define MOVE_EFFECT_FROSTBITE 7 +#define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_FROSTBITE // All above move effects apply primary status +#define MOVE_EFFECT_CONFUSION 8 +#define MOVE_EFFECT_FLINCH 9 +#define MOVE_EFFECT_TRI_ATTACK 10 +#define MOVE_EFFECT_UPROAR 11 +#define MOVE_EFFECT_PAYDAY 12 +#define MOVE_EFFECT_CHARGING 13 +#define MOVE_EFFECT_WRAP 14 +#define MOVE_EFFECT_BURN_UP 15 // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break +#define MOVE_EFFECT_ATK_PLUS_1 16 +#define MOVE_EFFECT_DEF_PLUS_1 17 +#define MOVE_EFFECT_SPD_PLUS_1 18 +#define MOVE_EFFECT_SP_ATK_PLUS_1 19 +#define MOVE_EFFECT_SP_DEF_PLUS_1 20 +#define MOVE_EFFECT_ACC_PLUS_1 21 +#define MOVE_EFFECT_EVS_PLUS_1 22 +#define MOVE_EFFECT_ATK_MINUS_1 23 +#define MOVE_EFFECT_DEF_MINUS_1 24 +#define MOVE_EFFECT_SPD_MINUS_1 25 +#define MOVE_EFFECT_SP_ATK_MINUS_1 26 +#define MOVE_EFFECT_SP_DEF_MINUS_1 27 +#define MOVE_EFFECT_ACC_MINUS_1 28 +#define MOVE_EFFECT_EVS_MINUS_1 29 +#define MOVE_EFFECT_RECHARGE 30 +#define MOVE_EFFECT_RAGE 31 +#define MOVE_EFFECT_STEAL_ITEM 32 +#define MOVE_EFFECT_PREVENT_ESCAPE 33 +#define MOVE_EFFECT_NIGHTMARE 34 +#define MOVE_EFFECT_ALL_STATS_UP 35 +#define MOVE_EFFECT_RAPIDSPIN 36 +#define MOVE_EFFECT_REMOVE_STATUS 37 +#define MOVE_EFFECT_ATK_DEF_DOWN 38 +#define MOVE_EFFECT_SCALE_SHOT 39 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break +#define MOVE_EFFECT_ATK_PLUS_2 40 +#define MOVE_EFFECT_DEF_PLUS_2 41 +#define MOVE_EFFECT_SPD_PLUS_2 42 +#define MOVE_EFFECT_SP_ATK_PLUS_2 43 +#define MOVE_EFFECT_SP_DEF_PLUS_2 44 +#define MOVE_EFFECT_ACC_PLUS_2 45 +#define MOVE_EFFECT_EVS_PLUS_2 46 +#define MOVE_EFFECT_ATK_MINUS_2 47 +#define MOVE_EFFECT_DEF_MINUS_2 48 +#define MOVE_EFFECT_SPD_MINUS_2 49 +#define MOVE_EFFECT_SP_ATK_MINUS_2 50 +#define MOVE_EFFECT_SP_DEF_MINUS_2 51 +#define MOVE_EFFECT_ACC_MINUS_2 52 +#define MOVE_EFFECT_EVS_MINUS_2 53 +#define MOVE_EFFECT_THRASH 54 +#define MOVE_EFFECT_KNOCK_OFF 55 +#define MOVE_EFFECT_DEF_SPDEF_DOWN 56 +#define MOVE_EFFECT_CLEAR_SMOG 57 +#define MOVE_EFFECT_SP_ATK_TWO_DOWN 58 +#define MOVE_EFFECT_SMACK_DOWN 59 +#define MOVE_EFFECT_FLAME_BURST 60 +#define MOVE_EFFECT_FEINT 61 +#define MOVE_EFFECT_SPECTRAL_THIEF 62 +#define MOVE_EFFECT_V_CREATE 63 +#define MOVE_EFFECT_HAPPY_HOUR 64 +#define MOVE_EFFECT_CORE_ENFORCER 65 +#define MOVE_EFFECT_THROAT_CHOP 66 +#define MOVE_EFFECT_INCINERATE 67 +#define MOVE_EFFECT_BUG_BITE 68 +#define MOVE_EFFECT_RECOIL_HP_25 69 +#define MOVE_EFFECT_RELIC_SONG 70 +#define MOVE_EFFECT_TRAP_BOTH 71 +#define MOVE_EFFECT_DOUBLE_SHOCK 72 +#define MOVE_EFFECT_ROUND 73 +#define MOVE_EFFECT_STOCKPILE_WORE_OFF 74 +#define MOVE_EFFECT_DIRE_CLAW 75 +#define MOVE_EFFECT_STEALTH_ROCK 76 +#define MOVE_EFFECT_SPIKES 77 -#define NUM_MOVE_EFFECTS 77 +#define NUM_MOVE_EFFECTS 78 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index d1562dec93..5df12b4496 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -405,7 +405,8 @@ #define EFFECT_DIRE_CLAW 399 #define EFFECT_BARB_BARRAGE 400 #define EFFECT_REVIVAL_BLESSING 401 +#define EFFECT_FROSTBITE_HIT 402 -#define NUM_BATTLE_MOVE_EFFECTS 402 +#define NUM_BATTLE_MOVE_EFFECTS 403 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 10e2a6fe56..b482a35947 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -652,8 +652,9 @@ #define STRINGID_ITEMCUREDSPECIESSTATUS 650 #define STRINGID_ITEMRESTOREDSPECIESPP 651 #define STRINGID_PKMNHURTBYFROSTBITE 652 +#define STRINGID_PKMNGOTFROSTBITE 653 -#define BATTLESTRINGS_COUNT 653 +#define BATTLESTRINGS_COUNT 654 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/pokemon.h b/include/pokemon.h index 581677cae7..a889e70aa5 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -346,7 +346,7 @@ struct BattleMove s8 priority; u32 flags; u8 split; - u8 argument; + u16 argument; u8 zMoveEffect; }; diff --git a/src/battle_message.c b/src/battle_message.c index b3be9afd1c..e77182f1b2 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -101,6 +101,7 @@ static const u8 sText_PkmnAlreadyPoisoned[] = _("{B_DEF_NAME_WITH_PREFIX} is alr static const u8 sText_PkmnBadlyPoisoned[] = _("{B_EFF_NAME_WITH_PREFIX} is badly\npoisoned!"); static const u8 sText_PkmnEnergyDrained[] = _("{B_DEF_NAME_WITH_PREFIX} had its\nenergy drained!"); static const u8 sText_PkmnWasBurned[] = _("{B_EFF_NAME_WITH_PREFIX} was burned!"); +static const u8 sText_PkmnGotFrostbite[] = _("{B_EFF_NAME_WITH_PREFIX} got frostbite!"); static const u8 sText_PkmnBurnedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nburned {B_EFF_NAME_WITH_PREFIX}!"); static const u8 sText_PkmnHurtByBurn[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its burn!"); static const u8 sText_PkmnHurtByFrostbite[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its frostbite!"); @@ -1430,6 +1431,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_ATTACKERLOSTELECTRICTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostElectricType, [STRINGID_PKMNSABILITYPREVENTSABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilityPreventsAbility, [STRINGID_PKMNHURTBYFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnHurtByFrostbite, + [STRINGID_PKMNGOTFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnGotFrostbite, }; const u16 gTrainerUsedItemStringIds[] = @@ -1731,6 +1733,11 @@ const u16 gGotBurnedStringIds[] = [B_MSG_STATUSED_BY_ABILITY] = STRINGID_PKMNBURNEDBY }; +const u16 gGotFrostbiteStringIds[] = +{ + [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE +}; + const u16 gGotFrozenStringIds[] = { [B_MSG_STATUSED] = STRINGID_PKMNWASFROZEN, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4e1494ce38..7273b03ae2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -61,6 +61,7 @@ #include "constants/trainers.h" #include "battle_util.h" #include "constants/pokemon.h" +#include "config/battle.h" // Helper for accessing command arguments and advancing gBattlescriptCurrInstr. // @@ -896,6 +897,7 @@ static const u32 sStatusFlagsForMoveEffects[NUM_MOVE_EFFECTS] = [MOVE_EFFECT_FREEZE] = STATUS1_FREEZE, [MOVE_EFFECT_PARALYSIS] = STATUS1_PARALYSIS, [MOVE_EFFECT_TOXIC] = STATUS1_TOXIC_POISON, + [MOVE_EFFECT_FROSTBITE] = STATUS1_FROSTBITE, [MOVE_EFFECT_CONFUSION] = STATUS2_CONFUSION, [MOVE_EFFECT_FLINCH] = STATUS2_FLINCHED, [MOVE_EFFECT_UPROAR] = STATUS2_UPROAR, @@ -919,6 +921,7 @@ static const u8 *const sMoveEffectBS_Ptrs[] = [MOVE_EFFECT_UPROAR] = BattleScript_MoveEffectUproar, [MOVE_EFFECT_PAYDAY] = BattleScript_MoveEffectPayDay, [MOVE_EFFECT_WRAP] = BattleScript_MoveEffectWrap, + [MOVE_EFFECT_FROSTBITE] = BattleScript_MoveEffectFrostbite, }; static const struct WindowTemplate sUnusedWinTemplate = @@ -3161,6 +3164,12 @@ void SetMoveEffect(bool32 primary, u32 certain) gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE; } break; + case STATUS1_FROSTBITE: + if (!CanBeFrozen(gEffectBattler)) + break; + + statusChanged = TRUE; + break; } if (statusChanged == TRUE) { @@ -3319,7 +3328,11 @@ void SetMoveEffect(bool32 primary, u32 certain) } else { + #if B_USE_FROSTBITE == TRUE + static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FROSTBITE, MOVE_EFFECT_PARALYSIS }; + #else static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FREEZE, MOVE_EFFECT_PARALYSIS }; + #endif gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects); SetMoveEffect(FALSE, 0); } @@ -9960,6 +9973,9 @@ static void Cmd_various(void) case STATUS1_TOXIC_POISON: gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC; break; + case STATUS1_FROSTBITE: + gBattleScripting.moveEffect = MOVE_EFFECT_FROSTBITE; + break; default: gBattleScripting.moveEffect = 0; break; @@ -15079,7 +15095,11 @@ u16 GetSecretPowerMoveEffect(void) break; case BATTLE_TERRAIN_SNOW: case BATTLE_TERRAIN_ICE: + #if B_USE_FROSTBITE == TRUE + moveEffect = MOVE_EFFECT_FROSTBITE; + #else moveEffect = MOVE_EFFECT_FREEZE; + #endif break; case BATTLE_TERRAIN_VOLCANO: moveEffect = MOVE_EFFECT_BURN; diff --git a/src/battle_tv.c b/src/battle_tv.c index 10c2144ccd..f5c9f43c4e 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -481,6 +481,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_DOUBLE_SHOCK] = 0, // TODO: Assign points [EFFECT_SPECIAL_ATTACK_UP_HIT] = 1, [EFFECT_VICTORY_DANCE] = 0, // TODO: Assign points + [EFFECT_FROSTBITE_HIT] = 1, }; static const u16 sPoints_Effectiveness[] = diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 4a89222a96..a1cc695059 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -121,7 +121,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_ICE_PUNCH] = { - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .power = 75, .type = TYPE_ICE, .accuracy = 100, @@ -982,7 +986,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .power = 95, #endif - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .type = TYPE_ICE, .accuracy = 100, .pp = 10, @@ -1001,7 +1009,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .power = 120, #endif - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .type = TYPE_ICE, .accuracy = 70, .pp = 5, @@ -3062,7 +3074,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_POWDER_SNOW] = { - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .power = 40, .type = TYPE_ICE, .accuracy = 100, @@ -7177,6 +7193,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_STRONG_JAW_BOOST, #endif + #if B_USE_FROSTBITE == TRUE + .argument = STATUS1_FROSTBITE, + #else + .argument = STATUS1_FREEZE, + #endif .effect = EFFECT_FLINCH_STATUS, .power = 65, .type = TYPE_ICE, @@ -7186,7 +7207,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, - .argument = STATUS1_FREEZE, .zMoveEffect = Z_EFFECT_NONE, }, @@ -12354,7 +12374,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_FREEZING_GLARE] = { .power = 90, - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 10, From 13f6acf9a1e0731afcf0d144c2b12409dde00a3a Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 23 Apr 2023 19:20:48 +0200 Subject: [PATCH 105/131] General mechanics --- data/battle_scripts_1.s | 16 ++++++++++++++ include/battle_scripts.h | 2 ++ include/constants/battle_string_ids.h | 4 +++- src/battle_message.c | 6 +++++- src/battle_script_commands.c | 6 ++++-- src/battle_util.c | 31 +++++++++++++++++++++------ 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3bfc3ac089..a169b12752 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -581,6 +581,7 @@ BattleScript_AffectionBasedStatusHeal:: jumpifstatus BS_ATTACKER, STATUS1_PARALYSIS, BattleScript_AffectionBasedStatus_HealParalysisString jumpifstatus BS_ATTACKER, STATUS1_BURN, BattleScript_AffectionBasedStatus_HealBurnString jumpifstatus BS_ATTACKER, STATUS1_FREEZE, BattleScript_AffectionBasedStatus_HealFreezeString + jumpifstatus BS_ATTACKER, STATUS1_FROSTBITE, BattleScript_AffectionBasedStatus_HealFrostbiteString end2 BattleScript_AffectionBasedStatus_HealPoisonString: printstring STRINGID_ATTACKEREXPELLEDTHEPOISON @@ -596,6 +597,9 @@ BattleScript_AffectionBasedStatus_HealBurnString: goto BattleScript_AffectionBasedStatusHeal_Continue BattleScript_AffectionBasedStatus_HealFreezeString: printstring STRINGID_ATTACKERMELTEDTHEICE + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatus_HealFrostbiteString: + printstring STRINGID_ATTACKERHEALEDITSFROSTBITE BattleScript_AffectionBasedStatusHeal_Continue: waitmessage B_WAIT_TIME_LONG clearstatus BS_ATTACKER @@ -9580,6 +9584,18 @@ BattleScript_BerryCureFrzRet:: removeitem BS_SCRIPTING return +BattleScript_BerryCureFsbEnd2:: + call BattleScript_BerryCureFrzRet + end2 + +BattleScript_BerryCureFsbRet:: + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT + printstring STRINGID_PKMNSITEMHEALEDFROSTBITE + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_SCRIPTING + removeitem BS_SCRIPTING + return + BattleScript_BerryCureSlpEnd2:: call BattleScript_BerryCureSlpRet end2 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 9b9156eb6f..6fcdcac258 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -197,6 +197,8 @@ extern const u8 BattleScript_BerryCureBrnEnd2[]; extern const u8 BattleScript_BerryCureBrnRet[]; extern const u8 BattleScript_BerryCureFrzEnd2[]; extern const u8 BattleScript_BerryCureFrzRet[]; +extern const u8 BattleScript_BerryCureFsbEnd2[]; +extern const u8 BattleScript_BerryCureFsbRet[]; extern const u8 BattleScript_BerryCureSlpEnd2[]; extern const u8 BattleScript_BerryCureSlpRet[]; extern const u8 BattleScript_BerryCureConfusionEnd2[]; diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index b482a35947..4e8cd9ab83 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -653,8 +653,10 @@ #define STRINGID_ITEMRESTOREDSPECIESPP 651 #define STRINGID_PKMNHURTBYFROSTBITE 652 #define STRINGID_PKMNGOTFROSTBITE 653 +#define STRINGID_PKMNSITEMHEALEDFROSTBITE 654 +#define STRINGID_ATTACKERHEALEDITSFROSTBITE 655 -#define BATTLESTRINGS_COUNT 654 +#define BATTLESTRINGS_COUNT 656 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/src/battle_message.c b/src/battle_message.c index e77182f1b2..39d862057c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -493,6 +493,7 @@ static const u8 sText_BerrySuffix[] = _(" BERRY"); static const u8 sText_PkmnsItemCuredParalysis[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\ncured paralysis!"); static const u8 sText_PkmnsItemCuredPoison[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\ncured poison!"); static const u8 sText_PkmnsItemHealedBurn[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nhealed its burn!"); +static const u8 sText_PkmnsItemHealedFrostbite[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nhealed its frostbite!"); static const u8 sText_PkmnsItemDefrostedIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\ndefrosted it!"); static const u8 sText_PkmnsItemWokeIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nwoke it from its sleep!"); static const u8 sText_PkmnsItemSnappedOut[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nsnapped it out of confusion!"); @@ -770,6 +771,7 @@ static const u8 sText_AttackerExpelledThePoison[] = _("{B_ATK_NAME_WITH_PREFIX} static const u8 sText_AttackerShookItselfAwake[] = _("{B_ATK_NAME_WITH_PREFIX} shook itself awake!"); static const u8 sText_AttackerBrokeThroughParalysis[] = _("{B_ATK_NAME_WITH_PREFIX} gathered all its energy\nto overcome its paralysis!"); static const u8 sText_AttackerHealedItsBurn[] = _("{B_ATK_NAME_WITH_PREFIX} healed its burn with\nits sheer determination!"); +static const u8 sText_AttackerHealedItsFrostbite[] = _("{B_ATK_NAME_WITH_PREFIX} healed its frostbite with\nits sheer determination!"); static const u8 sText_AttackerMeltedTheIce[] = _("{B_ATK_NAME_WITH_PREFIX} melted the ice with\nits fiery determination!"); static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!"); static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!"); @@ -1432,6 +1434,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_PKMNSABILITYPREVENTSABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilityPreventsAbility, [STRINGID_PKMNHURTBYFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnHurtByFrostbite, [STRINGID_PKMNGOTFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnGotFrostbite, + [STRINGID_PKMNSITEMHEALEDFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnsItemHealedFrostbite, + [STRINGID_ATTACKERHEALEDITSFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_AttackerHealedItsFrostbite, }; const u16 gTrainerUsedItemStringIds[] = @@ -1898,7 +1902,7 @@ const u16 gRoomsStringIds[] = const u16 gStatusConditionsStringIds[] = { - STRINGID_PKMNWASPOISONED, STRINGID_PKMNBADLYPOISONED, STRINGID_PKMNWASBURNED, STRINGID_PKMNWASPARALYZED, STRINGID_PKMNFELLASLEEP + STRINGID_PKMNWASPOISONED, STRINGID_PKMNBADLYPOISONED, STRINGID_PKMNWASBURNED, STRINGID_PKMNWASPARALYZED, STRINGID_PKMNFELLASLEEP, STRINGID_PKMNGOTFROSTBITE }; const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7273b03ae2..ecf9023936 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10144,6 +10144,8 @@ static void Cmd_various(void) gBattleCommunication[MULTISTRING_CHOOSER] = 3; else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanSleep(gBattlerTarget)) gBattleCommunication[MULTISTRING_CHOOSER] = 4; + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerTarget)) + gBattleCommunication[MULTISTRING_CHOOSER] = 5; else { gBattlescriptCurrInstr = cmd->failInstr; @@ -14370,7 +14372,7 @@ static void Cmd_cureifburnedparalysedorpoisoned(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerAttacker].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)) + if (gBattleMons[gBattlerAttacker].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) { gBattleMons[gBattlerAttacker].status1 = 0; gBattlescriptCurrInstr = cmd->nextInstr; @@ -15696,7 +15698,7 @@ static void Cmd_handleballthrow(void) if (gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) odds *= 2; - if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)) + if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) odds = (odds * 15) / 10; if (gBattleResults.catchAttempts[gLastUsedItem - FIRST_BALL] < 255) diff --git a/src/battle_util.c b/src/battle_util.c index 993a0d5ab3..456936fadb 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4916,7 +4916,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); if (gBattleMons[battler].status1 & STATUS1_BURN) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); - if (gBattleMons[battler].status1 & STATUS1_FREEZE) + if (gBattleMons[battler].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); gBattleMons[battler].status1 = 0; @@ -5957,7 +5957,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_MAGMA_ARMOR: - if (gBattleMons[battler].status1 & STATUS1_FREEZE) + if (gBattleMons[battler].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) { StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); effect = 1; @@ -6904,6 +6904,13 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) gBattlescriptCurrInstr = BattleScript_BerryCureFrzRet; effect = ITEM_STATUS_CHANGE; } + if (gBattleMons[battlerId].status1 & STATUS1_FROSTBITE && !UnnerveOn(battlerId, gLastUsedItem)) + { + gBattleMons[battlerId].status1 &= ~STATUS1_FROSTBITE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureFsbRet; + effect = ITEM_STATUS_CHANGE; + } break; case HOLD_EFFECT_CURE_SLP: if (gBattleMons[battlerId].status1 & STATUS1_SLEEP && !UnnerveOn(battlerId, gLastUsedItem)) @@ -6952,7 +6959,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) if (gBattleMons[battlerId].status1 & STATUS1_BURN) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); - if (gBattleMons[battlerId].status1 & STATUS1_FREEZE) + if (gBattleMons[battlerId].status1 & STATUS1_FREEZE || gBattleMons[battlerId].status1 & STATUS1_FROSTBITE) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION) @@ -7125,6 +7132,12 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptExecute(BattleScript_BerryCureFrzEnd2); effect = ITEM_STATUS_CHANGE; } + if (gBattleMons[battlerId].status1 & STATUS1_FROSTBITE && !UnnerveOn(battlerId, gLastUsedItem)) + { + gBattleMons[battlerId].status1 &= ~STATUS1_FROSTBITE; + BattleScriptExecute(BattleScript_BerryCureFsbEnd2); + effect = ITEM_STATUS_CHANGE; + } break; case HOLD_EFFECT_CURE_SLP: if (gBattleMons[battlerId].status1 & STATUS1_SLEEP && !UnnerveOn(battlerId, gLastUsedItem)) @@ -7160,7 +7173,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); i++; } - if (gBattleMons[battlerId].status1 & STATUS1_FREEZE) + if (gBattleMons[battlerId].status1 & STATUS1_FREEZE || gBattleMons[battlerId].status1 & STATUS1_FROSTBITE) { StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); i++; @@ -7443,6 +7456,12 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptExecute(BattleScript_BerryCureFrzEnd2); effect = ITEM_STATUS_CHANGE; } + if (gBattleMons[battlerId].status1 & STATUS1_FROSTBITE && !UnnerveOn(battlerId, gLastUsedItem)) + { + gBattleMons[battlerId].status1 &= ~STATUS1_FROSTBITE; + BattleScriptExecute(BattleScript_BerryCureFsbEnd2); + effect = ITEM_STATUS_CHANGE; + } break; case HOLD_EFFECT_CURE_SLP: if (gBattleMons[battlerId].status1 & STATUS1_SLEEP && !UnnerveOn(battlerId, gLastUsedItem)) @@ -7486,7 +7505,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); i++; } - if (gBattleMons[battlerId].status1 & STATUS1_FREEZE) + if (gBattleMons[battlerId].status1 & STATUS1_FREEZE || gBattleMons[battlerId].status1 & STATUS1_FROSTBITE) { StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); i++; @@ -9054,7 +9073,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe switch (gBattleMoves[move].effect) { case EFFECT_FACADE: - if (gBattleMons[battlerAtk].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS)) + if (gBattleMons[battlerAtk].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS | STATUS1_FROSTBITE)) MulModifier(&modifier, UQ_4_12(2.0)); break; case EFFECT_BRINE: From a020001a78e7cd08537d6c6ca85d5cd273792a89 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 23 Apr 2023 20:33:28 +0200 Subject: [PATCH 106/131] Battle Pike functionality --- src/battle_pike.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/battle_pike.c b/src/battle_pike.c index 9751d565de..37dfd9997d 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -729,6 +729,7 @@ static void GetRoomInflictedStatus(void) switch (sStatusFlags) { case STATUS1_FREEZE: + case STATUS1_FROSTBITE: gSpecialVar_Result = PIKE_STATUS_FREEZE; break; case STATUS1_BURN: @@ -818,6 +819,7 @@ static bool8 DoesAbilityPreventStatus(struct Pokemon *mon, u32 status) switch (status) { case STATUS1_FREEZE: + case STATUS1_FROSTBITE: if (ability == ABILITY_MAGMA_ARMOR) ret = TRUE; break; @@ -853,6 +855,7 @@ static bool8 DoesTypePreventStatus(u16 species, u32 status) ret = TRUE; break; case STATUS1_FREEZE: + case STATUS1_FROSTBITE: if (gSpeciesInfo[species].types[0] == TYPE_ICE || gSpeciesInfo[species].types[1] == TYPE_ICE) ret = TRUE; break; @@ -913,7 +916,11 @@ static bool8 TryInflictRandomStatus(void) if (rand < 35) sStatusFlags = STATUS1_TOXIC_POISON; else if (rand < 60) + #if B_USE_FROSTBITE == TRUE + sStatusFlags = STATUS1_FROSTBITE; + #else sStatusFlags = STATUS1_FREEZE; + #endif else if (rand < 80) sStatusFlags = STATUS1_PARALYSIS; else if (rand < 90) @@ -950,6 +957,7 @@ static bool8 TryInflictRandomStatus(void) switch (sStatusFlags) { case STATUS1_FREEZE: + case STATUS1_FROSTBITE: sStatusMon = PIKE_STATUSMON_DUSCLOPS; break; case STATUS1_BURN: From 6b2a873071ae9526d25b784e2d667c48c7d296c1 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 23 Apr 2023 20:41:19 +0200 Subject: [PATCH 107/131] Add comment in Ice Beam --- src/data/battle_moves.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index a1cc695059..9473bae71c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -986,6 +986,8 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .power = 95, #endif + // The following effect is also relevant in battle_pike.c + // If you cherry-pick this to use something other than the config, make sure to update it there too #if B_USE_FROSTBITE == TRUE .effect = EFFECT_FROSTBITE_HIT, #else From 0b8d148c2643fdd85735663f602252d590c53582 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 23 Apr 2023 20:53:51 +0200 Subject: [PATCH 108/131] Let AI take Frostbite into account --- include/battle_ai_util.h | 3 +++ src/battle_ai_main.c | 32 +++++++++++++++++++++++++---- src/battle_ai_util.c | 44 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index d1319f0ca7..f2dd8f03ed 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -130,6 +130,7 @@ bool32 IsSemiInvulnerable(u8 battlerDef, u16 move); // status checks bool32 AI_CanBeBurned(u8 battler, u16 ability); +bool32 AI_CanGetFrostbite(u8 battler, u16 ability); bool32 AI_CanBeConfused(u8 battler, u16 ability); bool32 AI_CanSleep(u8 battler, u16 ability); bool32 IsBattlerIncapacitated(u8 battler, u16 ability); @@ -140,6 +141,7 @@ bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u1 bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 ShouldBurnSelf(u8 battler, u16 ability); bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); +bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGender, u8 defGender); bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof); u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move); @@ -175,5 +177,6 @@ void IncreaseBurnScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); +void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); #endif //GUARD_BATTLE_AI_UTIL_H \ No newline at end of file diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6c60705d5a..77220f79ef 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1725,7 +1725,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score -= 10; break; case EFFECT_REFRESH: - if (!(gBattleMons[battlerDef].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS))) + if (!(gBattleMons[battlerDef].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_FROSTBITE))) score -= 10; break; case EFFECT_PSYCHO_SHIFT: @@ -1734,6 +1734,9 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (gBattleMons[battlerAtk].status1 & STATUS1_BURN && !AI_CanBurn(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) score -= 10; + else if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !AI_CanGiveFrostbite(battlerAtk, battlerDef, + AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) + score -= 10; else if (gBattleMons[battlerAtk].status1 & STATUS1_PARALYSIS && !AI_CanParalyze(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove)) score -= 10; else if (gBattleMons[battlerAtk].status1 & STATUS1_SLEEP && !AI_CanPutToSleep(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove)) @@ -3143,7 +3146,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score++; // check thawing moves - if ((gBattleMons[battlerAtk].status1 & STATUS1_FREEZE) && TestMoveFlags(move, FLAG_THAW_USER)) + if ((gBattleMons[battlerAtk].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) && TestMoveFlags(move, FLAG_THAW_USER)) score += (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? 20 : 10; // check burn @@ -3165,6 +3168,25 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } } + // check frostbite + if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE) + { + switch (AI_DATA->abilities[battlerAtk]) + { + case ABILITY_GUTS: + break; + case ABILITY_NATURAL_CURE: + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING + && HasOnlyMovesWithSplit(battlerAtk, SPLIT_SPECIAL, TRUE)) + score = 90; // Force switch if all your attacking moves are special and you have Natural Cure. + break; + default: + if (IS_MOVE_SPECIAL(move) && gBattleMoves[move].effect != EFFECT_FACADE) + score -= 2; + break; + } + } + // attacker ability checks switch (AI_DATA->abilities[battlerAtk]) { @@ -3602,7 +3624,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_SUBSTITUTE: if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG) score += 3; - if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY)) + if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE)) score++; if (HasMoveEffect(battlerDef, EFFECT_SLEEP) || HasMoveEffect(battlerDef, EFFECT_TOXIC) @@ -4391,6 +4413,8 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) IncreaseParalyzeScore(battlerAtk, battlerDef, move, &score); else if (gBattleMons[battlerAtk].status1 & STATUS1_SLEEP) IncreaseSleepScore(battlerAtk, battlerDef, move, &score); + else if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE) + IncreaseFrostbiteScore(battlerAtk, battlerDef, move, &score); break; case EFFECT_GRUDGE: break; @@ -4781,7 +4805,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 2; break; case EFFECT_FACADE: - if (gBattleMons[battlerAtk].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)) + if (gBattleMons[battlerAtk].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) score++; break; case EFFECT_FOCUS_PUNCH: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 05e7aec58f..dabeb33c78 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1678,7 +1678,7 @@ void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s1 (*score) -= min(uses, 3); } - if (gBattleMons[battlerAtk].status1 & (STATUS1_PSN_ANY | STATUS1_BURN) + if (gBattleMons[battlerAtk].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_FROSTBITE) || gBattleMons[battlerAtk].status2 & (STATUS2_CURSED | STATUS2_INFATUATION) || gStatuses3[battlerAtk] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN)) { @@ -2892,6 +2892,17 @@ bool32 AI_CanBeBurned(u8 battler, u16 ability) return TRUE; } +bool32 AI_CanGetFrostbite(u8 battler, u16 ability) +{ + if (ability == ABILITY_MAGMA_ARMOR + || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || gBattleMons[battler].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battler) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) + return FALSE; + return TRUE; +} + bool32 ShouldBurnSelf(u8 battler, u16 ability) { if (AI_CanBeBurned(battler, ability) && ( @@ -2918,6 +2929,18 @@ bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPar return TRUE; } +bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove) +{ + if (!AI_CanGetFrostbite(battlerDef, defAbility) + || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 + || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) + || PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove)) + { + return FALSE; + } + return TRUE; +} + bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGender, u8 defGender) { if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION) @@ -3717,6 +3740,25 @@ void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) } } +void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) +{ + if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) + return; + + if (AI_CanGiveFrostbite(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) + { + (*score)++; // frostbite is good + if (HasMoveWithSplit(battlerDef, SPLIT_SPECIAL)) + { + if (CanTargetFaintAi(battlerDef, battlerAtk)) + *score += 2; // frostbiting the target to stay alive is cool + } + + if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX)) + (*score)++; + } +} + bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move) { if (TestMoveFlags(move, FLAG_MAKES_CONTACT) From f13c39d784d15186374b7e81cf29e296bb41ede3 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 23 Apr 2023 21:20:23 +0200 Subject: [PATCH 109/131] Thawing out for frostbite --- data/battle_scripts_1.s | 12 ++++++++++++ include/battle_scripts.h | 2 ++ include/constants/battle_string_ids.h | 9 ++++++++- src/battle_message.c | 12 ++++++++++++ src/battle_script_commands.c | 19 +++++++++++++++++++ src/battle_util.c | 11 +++++++++++ 6 files changed, 64 insertions(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a169b12752..f65d6e18a6 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8151,12 +8151,24 @@ BattleScript_MoveUsedUnfroze:: updatestatusicon BS_ATTACKER return +BattleScript_MoveUsedUnfrostbite:: + printfromtable gFrostbiteHealedStringIds + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_ATTACKER + return + BattleScript_DefrostedViaFireMove:: printstring STRINGID_PKMNWASDEFROSTED waitmessage B_WAIT_TIME_LONG updatestatusicon BS_TARGET return +BattleScript_FrostbiteHealedViaFireMove:: + printstring STRINGID_PKMNFROSTBITEHEALED + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_TARGET + return + BattleScript_MoveUsedIsParalyzed:: printstring STRINGID_PKMNISPARALYZED waitmessage B_WAIT_TIME_LONG diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 6fcdcac258..d10d5ba07f 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -111,7 +111,9 @@ extern const u8 BattleScript_BurnTurnDmg[]; extern const u8 BattleScript_FrostbiteTurnDmg[]; extern const u8 BattleScript_MoveUsedIsFrozen[]; extern const u8 BattleScript_MoveUsedUnfroze[]; +extern const u8 BattleScript_MoveUsedUnfrostbite[]; extern const u8 BattleScript_DefrostedViaFireMove[]; +extern const u8 BattleScript_FrostbiteHealedViaFireMove[]; extern const u8 BattleScript_MoveUsedIsParalyzed[]; extern const u8 BattleScript_MoveUsedFlinched[]; extern const u8 BattleScript_PrintUproarOverTurns[]; diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 4e8cd9ab83..294bd1f7cb 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -655,8 +655,11 @@ #define STRINGID_PKMNGOTFROSTBITE 653 #define STRINGID_PKMNSITEMHEALEDFROSTBITE 654 #define STRINGID_ATTACKERHEALEDITSFROSTBITE 655 +#define STRINGID_PKMNFROSTBITEHEALED 656 +#define STRINGID_PKMNFROSTBITEHEALED2 657 +#define STRINGID_PKMNFROSTBITEHEALEDBY 658 -#define BATTLESTRINGS_COUNT 656 +#define BATTLESTRINGS_COUNT 659 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, @@ -864,6 +867,10 @@ #define B_MSG_DEFROSTED 0 #define B_MSG_DEFROSTED_BY_MOVE 1 +// gFrostbiteHealedStringIds +#define B_MSG_FROSTBITE_HEALED 0 +#define B_MSG_FROSTBITE_HEALED_BY_MOVE 1 + // gBattlePalaceFlavorTextTable #define B_MSG_GLINT_IN_EYE 0 #define B_MSG_GETTING_IN_POS 1 diff --git a/src/battle_message.c b/src/battle_message.c index 39d862057c..48c4f222ab 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -112,6 +112,9 @@ static const u8 sText_PkmnIsFrozen[] = _("{B_ATK_NAME_WITH_PREFIX} is\nfrozen so static const u8 sText_PkmnWasDefrosted[] = _("{B_DEF_NAME_WITH_PREFIX} was\ndefrosted!"); static const u8 sText_PkmnWasDefrosted2[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted!"); static const u8 sText_PkmnWasDefrostedBy[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted by {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnFrostbiteHealed[] = _("{B_DEF_NAME_WITH_PREFIX}'s\nfrostbite was healed!"); +static const u8 sText_PkmnFrostbiteHealed2[] = _("{B_ATK_NAME_WITH_PREFIX}'s\nfrostbite was healed!"); +static const u8 sText_PkmnFrostbiteHealedBy[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE}\nhealed its frostbite!"); static const u8 sText_PkmnWasParalyzed[] = _("{B_EFF_NAME_WITH_PREFIX} is paralyzed!\nIt may be unable to move!"); static const u8 sText_PkmnWasParalyzedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nparalyzed {B_EFF_NAME_WITH_PREFIX}!\lIt may be unable to move!"); static const u8 sText_PkmnIsParalyzed[] = _("{B_ATK_NAME_WITH_PREFIX} is paralyzed!\nIt can't move!"); @@ -1436,6 +1439,9 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_PKMNGOTFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnGotFrostbite, [STRINGID_PKMNSITEMHEALEDFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnsItemHealedFrostbite, [STRINGID_ATTACKERHEALEDITSFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_AttackerHealedItsFrostbite, + [STRINGID_PKMNFROSTBITEHEALED - BATTLESTRINGS_TABLE_START] = sText_PkmnFrostbiteHealed, + [STRINGID_PKMNFROSTBITEHEALED2 - BATTLESTRINGS_TABLE_START] = sText_PkmnFrostbiteHealed2, + [STRINGID_PKMNFROSTBITEHEALEDBY - BATTLESTRINGS_TABLE_START] = sText_PkmnFrostbiteHealedBy, }; const u16 gTrainerUsedItemStringIds[] = @@ -1742,6 +1748,12 @@ const u16 gGotFrostbiteStringIds[] = [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE }; +const u16 gFrostbiteHealedStringIds[] = +{ + [B_MSG_FROSTBITE_HEALED] = STRINGID_PKMNFROSTBITEHEALED2, + [B_MSG_FROSTBITE_HEALED_BY_MOVE] = STRINGID_PKMNFROSTBITEHEALEDBY +}; + const u16 gGotFrozenStringIds[] = { [B_MSG_STATUSED] = STRINGID_PKMNWASFROZEN, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ecf9023936..81d1a94e81 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5565,6 +5565,25 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; effect = TRUE; } + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE + && gBattleMons[gBattlerTarget].hp != 0 + && gBattlerAttacker != gBattlerTarget + && gSpecialStatuses[gBattlerTarget].specialDmg + && (moveType == TYPE_FIRE + #if B_BURN_HIT_THAW >= GEN_6 + || gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT + #endif + ) + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; + gActiveBattler = gBattlerTarget; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gActiveBattler); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; + effect = TRUE; + } gBattleScripting.moveendState++; break; case MOVEEND_RECOIL: diff --git a/src/battle_util.c b/src/battle_util.c index 456936fadb..97043f7dfd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3644,6 +3644,17 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 2; } + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) + { + if (!(gBattleMoves[gCurrentMove].effect == EFFECT_BURN_UP && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + { + gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FROSTBITE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedUnfrostbite; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE; + } + effect = 2; + } gBattleStruct->atkCancellerTracker++; break; case CANCELLER_POWDER_MOVE: From a2bc21d902a373e6ca759bcb81f1d785bb1bfdd2 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Mon, 24 Apr 2023 14:05:35 +0200 Subject: [PATCH 110/131] Update battle_ai_util.h Co-Authored-By: Salem <65783283+callmeechoo@users.noreply.github.com> --- include/battle_ai_util.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index f2dd8f03ed..1a0fbc2645 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -172,11 +172,11 @@ bool32 SideHasMoveSplit(u8 battlerId, u8 split); // score increases void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score); -void IncreasePoisonScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); -void IncreaseBurnScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); +void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); +void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); -void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); +void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); -#endif //GUARD_BATTLE_AI_UTIL_H \ No newline at end of file +#endif //GUARD_BATTLE_AI_UTIL_H From 330e85ba64b1b23d602a83ad3bef16f93a05b73c Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 24 Apr 2023 09:34:11 -0300 Subject: [PATCH 111/131] Updates -Undeclared size for certain trainer slide-in variables at struct BattleStruct for reasons. -Added a BattlerHPPercentage function to make HP threshold checks in ShouldDoTrainerSlide a bit more readable. --- include/battle.h | 10 +++++----- src/battle_message.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/battle.h b/include/battle.h index 44aa063c9c..2b72d48365 100644 --- a/include/battle.h +++ b/include/battle.h @@ -622,7 +622,7 @@ struct BattleStruct struct MegaEvolutionData mega; struct ZMoveData zmove; const u8 *trainerSlideMsg; - bool8 trainerSlideLowHpMsgDone:1; + bool8 trainerSlideLowHpMsgDone; u8 introState; u8 ateBerry[2]; // array id determined by side, each party pokemon as bit u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages @@ -663,14 +663,14 @@ struct BattleStruct u8 storedHealingWish:4; // Each battler as a bit. u8 storedLunarDance:4; // Each battler as a bit. u16 supremeOverlordModifier[MAX_BATTLERS_COUNT]; - bool8 trainerSlideHalfHpMsgDone:1; + bool8 trainerSlideHalfHpMsgDone; u8 trainerSlideFirstCriticalHitMsgState:2; u8 trainerSlideFirstSuperEffectiveHitMsgState:2; u8 trainerSlideFirstSTABMoveMsgState:2; u8 trainerSlidePlayerMonUnaffectedMsgState:2; - bool8 trainerSlideMegaEvolutionMsgDone:1; - bool8 trainerSlideZMoveMsgDone:1; - bool8 trainerSlideBeforeFirstTurnMsgDone:1; + bool8 trainerSlideMegaEvolutionMsgDone; + bool8 trainerSlideZMoveMsgDone; + bool8 trainerSlideBeforeFirstTurnMsgDone; }; #define F_DYNAMIC_TYPE_1 (1 << 6) diff --git a/src/battle_message.c b/src/battle_message.c index fab65a46b4..dd6390d282 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3934,6 +3934,37 @@ static u32 GetEnemyMonCount(u32 firstId, u32 lastId, bool32 onlyAlive) return count; } +enum +{ + LESS_THAN, + EQUAL, + GREATER_THAN, + LESS_THAN_OR_EQUAL, + GREATER_THAN_OR_EQUAL, + NOT_EQUAL, +}; + +u32 BattlerHPPercentage(u32 battlerId, u32 operation, u32 threshold) +{ + switch (operation) + { + case LESS_THAN: + return gBattleMons[battlerId].hp < (gBattleMons[battlerId].maxHP / threshold); + case EQUAL: + return gBattleMons[battlerId].hp == (gBattleMons[battlerId].maxHP / threshold); + case GREATER_THAN: + return gBattleMons[battlerId].hp > (gBattleMons[battlerId].maxHP / threshold); + case LESS_THAN_OR_EQUAL: + return gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / threshold); + case GREATER_THAN_OR_EQUAL: + return gBattleMons[battlerId].hp >= (gBattleMons[battlerId].maxHP / threshold); + case NOT_EQUAL: + return gBattleMons[battlerId].hp != (gBattleMons[battlerId].maxHP / threshold); + default: + break; + } +} + u32 ShouldDoTrainerSlide(u32 battlerId, u32 which) { u32 i, firstId, lastId, trainerId, retValue = 1; @@ -3979,7 +4010,7 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which) case TRAINER_SLIDE_LAST_LOW_HP: if (sTrainerSlides[i].msgLastLowHp != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == 1 - && gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4) + && BattlerHPPercentage(battlerId, GREATER_THAN_OR_EQUAL, 4) && !gBattleStruct->trainerSlideLowHpMsgDone) { gBattleStruct->trainerSlideLowHpMsgDone = TRUE; @@ -3997,7 +4028,7 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which) case TRAINER_SLIDE_LAST_HALF_HP: if (sTrainerSlides[i].msgLastHalfHp != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1 - && (gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 2) && gBattleMons[battlerId].hp > (gBattleMons[battlerId].maxHP / 4)) + && BattlerHPPercentage(battlerId, LESS_THAN_OR_EQUAL, 2) && BattlerHPPercentage(battlerId, GREATER_THAN, 4) && !gBattleStruct->trainerSlideHalfHpMsgDone) { gBattleStruct->trainerSlideHalfHpMsgDone = TRUE; From 868838a87d8af109ee90835d6c33bd7d8928328c Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 24 Apr 2023 14:35:42 -0400 Subject: [PATCH 112/131] Add thunder cage case to trap anim IDs (#2941) --- data/battle_anim_scripts.s | 5 +++++ include/constants/battle_anim.h | 1 + include/constants/battle_string_ids.h | 24 +++++++++++--------- src/battle_anim_throw.c | 32 +++++++++++++++++++-------- src/battle_message.c | 3 +++ 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index cca8706cbc..adcb88c881 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24463,6 +24463,7 @@ General_TurnTrap: jumpargeq 0, TRAP_ANIM_MAGMA_STORM, Status_MagmaStorm jumpargeq 0, TRAP_ANIM_INFESTATION, Status_Infestation jumpargeq 0, TRAP_ANIM_SNAP_TRAP, Status_Snap_Trap + jumpargeq 0, TRAP_ANIM_THUNDER_CAGE, Status_Thunder_Cage goto Status_BindWrap Status_BindWrap: loadspritegfx ANIM_TAG_TENDRILS @@ -24549,6 +24550,10 @@ Status_Clamp: waitforvisualfinish end +Status_Thunder_Cage: + @ TODO + goto Move_THUNDER_CAGE + Status_Snap_Trap: @ placeholder goto Move_BITE diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 4316191a2e..46e229a319 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -583,6 +583,7 @@ #define TRAP_ANIM_MAGMA_STORM 5 #define TRAP_ANIM_INFESTATION 6 #define TRAP_ANIM_SNAP_TRAP 7 +#define TRAP_ANIM_THUNDER_CAGE 8 // Weather defines for battle animation scripts. #define ANIM_WEATHER_NONE 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index e552077534..f4fd589db1 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -651,8 +651,9 @@ #define STRINGID_ITEMRESTOREDSPECIESHEALTH 649 #define STRINGID_ITEMCUREDSPECIESSTATUS 650 #define STRINGID_ITEMRESTOREDSPECIESPP 651 +#define STRINGID_THUNDERCAGETRAPPED 652 -#define BATTLESTRINGS_COUNT 652 +#define BATTLESTRINGS_COUNT 653 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, @@ -917,16 +918,17 @@ #define B_MSG_TERRAINENDS_COUNT 4 // gWrappedStringIds -#define B_MSG_WRAPPED_BIND 0 -#define B_MSG_WRAPPED_WRAP 1 -#define B_MSG_WRAPPED_FIRE_SPIN 2 -#define B_MSG_WRAPPED_CLAMP 3 -#define B_MSG_WRAPPED_WHIRLPOOL 4 -#define B_MSG_WRAPPED_SAND_TOMB 5 -#define B_MSG_WRAPPED_MAGMA_STORM 6 -#define B_MSG_WRAPPED_INFESTATION 7 -#define B_MSG_WRAPPED_SNAP_TRAP 8 -#define NUM_TRAPPING_MOVES 9 +#define B_MSG_WRAPPED_BIND 0 +#define B_MSG_WRAPPED_WRAP 1 +#define B_MSG_WRAPPED_FIRE_SPIN 2 +#define B_MSG_WRAPPED_CLAMP 3 +#define B_MSG_WRAPPED_WHIRLPOOL 4 +#define B_MSG_WRAPPED_SAND_TOMB 5 +#define B_MSG_WRAPPED_MAGMA_STORM 6 +#define B_MSG_WRAPPED_INFESTATION 7 +#define B_MSG_WRAPPED_SNAP_TRAP 8 +#define B_MSG_WRAPPED_THUNDER_CAGE 9 +#define NUM_TRAPPING_MOVES 10 // z effects #define B_MSG_Z_RESET_STATS 0 diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index a3197d4477..3fc2000e4a 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -2736,23 +2736,37 @@ void AnimTask_SetAttackerTargetLeftPos(u8 taskId) void AnimTask_GetTrappedMoveAnimId(u8 taskId) { - if (gBattleSpritesDataPtr->animationData->animArg == MOVE_FIRE_SPIN) + switch (gBattleSpritesDataPtr->animationData->animArg) + { + case MOVE_FIRE_SPIN: gBattleAnimArgs[0] = TRAP_ANIM_FIRE_SPIN; - else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_WHIRLPOOL) + break; + case MOVE_WHIRLPOOL: gBattleAnimArgs[0] = TRAP_ANIM_WHIRLPOOL; - else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_CLAMP) + break; + case MOVE_CLAMP: gBattleAnimArgs[0] = TRAP_ANIM_CLAMP; - else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SAND_TOMB) + break; + case MOVE_SAND_TOMB: gBattleAnimArgs[0] = TRAP_ANIM_SAND_TOMB; - else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_MAGMA_STORM) + break; + case MOVE_MAGMA_STORM: gBattleAnimArgs[0] = TRAP_ANIM_MAGMA_STORM; - else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_INFESTATION) + break; + case MOVE_INFESTATION: gBattleAnimArgs[0] = TRAP_ANIM_INFESTATION; - else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SNAP_TRAP) + break; + case MOVE_SNAP_TRAP: gBattleAnimArgs[0] = TRAP_ANIM_SNAP_TRAP; - else + break; + case MOVE_THUNDER_CAGE: + gBattleAnimArgs[0] = TRAP_ANIM_THUNDER_CAGE; + break; + default: gBattleAnimArgs[0] = TRAP_ANIM_BIND; - + break; + } + DestroyAnimVisualTask(taskId); } diff --git a/src/battle_message.c b/src/battle_message.c index e1122c7aac..21f7098f81 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -786,9 +786,11 @@ static const u8 sText_PkmnRevivedReadyToFight[] = _("{B_BUFF1} was revived and\n static const u8 sText_ItemRestoredSpeciesHealth[] = _("{B_BUFF1} had its\nHP restored!"); static const u8 sText_ItemCuredSpeciesStatus[] = _("{B_BUFF1} had\nits status healed!"); static const u8 sText_ItemRestoredSpeciesPP[] = _("{B_BUFF1} had its\nPP restored!"); +static const u8 sText_AtkTrappedDef[] = _("{B_ATK_NAME_WITH_PREFIX} trapped\nthe {B_DEF_NAME_WITH_PREFIX}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_THUNDERCAGETRAPPED - BATTLESTRINGS_TABLE_START] = sText_AtkTrappedDef, [STRINGID_ITEMRESTOREDSPECIESHEALTH - BATTLESTRINGS_TABLE_START] = sText_ItemRestoredSpeciesHealth, [STRINGID_ITEMCUREDSPECIESSTATUS - BATTLESTRINGS_TABLE_START] = sText_ItemCuredSpeciesStatus, [STRINGID_ITEMRESTOREDSPECIESPP - BATTLESTRINGS_TABLE_START] = sText_ItemRestoredSpeciesPP, @@ -1679,6 +1681,7 @@ const u16 gWrappedStringIds[NUM_TRAPPING_MOVES] = [B_MSG_WRAPPED_MAGMA_STORM] = STRINGID_TRAPPEDBYSWIRLINGMAGMA, // MOVE_MAGMA_STORM [B_MSG_WRAPPED_INFESTATION] = STRINGID_INFESTATION, // MOVE_INFESTATION [B_MSG_WRAPPED_SNAP_TRAP] = STRINGID_PKMNINSNAPTRAP, // MOVE_SNAP_TRAP + [B_MSG_WRAPPED_THUNDER_CAGE]= STRINGID_THUNDERCAGETRAPPED, // MOVE_THUNDER_CAGE }; const u16 gMistUsedStringIds[] = From 9562c7a37a000b4cfa34650ad717e300f7234c9e Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Mon, 24 Apr 2023 18:49:53 -0400 Subject: [PATCH 113/131] Added forbidden Metronome moves from PLA and SV (#2949) --- src/battle_script_commands.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 07669635e3..3632095963 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -979,6 +979,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_STRUGGLE] = 0xFF, // Neither Struggle [MOVE_AFTER_YOU] = FORBIDDEN_METRONOME, [MOVE_APPLE_ACID] = FORBIDDEN_METRONOME, + [MOVE_ARMOR_CANNON] = FORBIDDEN_METRONOME, [MOVE_ARM_THRUST] = FORBIDDEN_PARENTAL_BOND, [MOVE_ASSIST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_ASTRAL_BARRAGE] = FORBIDDEN_METRONOME, @@ -994,6 +995,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_BESTOW] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_BIDE] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, // Note: Bide should work with Parental Bond. This will be addressed in future. [MOVE_BLAST_BURN] = FORBIDDEN_INSTRUCT, + [MOVE_BLAZING_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_BODY_PRESS] = FORBIDDEN_METRONOME, [MOVE_BONE_RUSH] = FORBIDDEN_PARENTAL_BOND, [MOVE_BONEMERANG] = FORBIDDEN_PARENTAL_BOND, @@ -1005,9 +1007,14 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_BUZZY_BUZZ] = FORBIDDEN_METRONOME, [MOVE_CELEBRATE] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_CHATTER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, + [MOVE_CHILLING_WATER] = FORBIDDEN_METRONOME, + [MOVE_CHILLY_RECEPTION] = FORBIDDEN_METRONOME, [MOVE_CIRCLE_THROW] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_CLANGOROUS_SOUL] = FORBIDDEN_METRONOME, + [MOVE_COLLISION_COURSE] = FORBIDDEN_METRONOME, + [MOVE_COMBAT_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_COMET_PUNCH] = FORBIDDEN_PARENTAL_BOND, + [MOVE_COMEUPPANCE] = FORBIDDEN_METRONOME, [MOVE_COPYCAT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_COUNTER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_COVET] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, @@ -1018,9 +1025,11 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_DIAMOND_STORM] = FORBIDDEN_METRONOME, [MOVE_DIG] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_DIVE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, + [MOVE_DOODLE] = FORBIDDEN_METRONOME, [MOVE_DOUBLE_IRON_BASH] = FORBIDDEN_METRONOME | FORBIDDEN_PARENTAL_BOND, [MOVE_DOUBLE_HIT] = FORBIDDEN_PARENTAL_BOND, [MOVE_DOUBLE_KICK] = FORBIDDEN_PARENTAL_BOND, + [MOVE_DOUBLE_SHOCK] = FORBIDDEN_METRONOME, [MOVE_DOUBLE_SLAP] = FORBIDDEN_PARENTAL_BOND, [MOVE_DRAGON_ASCENT] = FORBIDDEN_METRONOME, [MOVE_DRAGON_ENERGY] = FORBIDDEN_METRONOME, @@ -1030,6 +1039,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_DUAL_CHOP] = FORBIDDEN_PARENTAL_BOND, [MOVE_DUAL_WINGBEAT] = FORBIDDEN_PARENTAL_BOND, [MOVE_DYNAMAX_CANNON] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, + [MOVE_ELECTRO_DRIFT] = FORBIDDEN_METRONOME, [MOVE_ENDEAVOR] = FORBIDDEN_PARENTAL_BOND, [MOVE_ENDURE] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_ETERNABEAM] = FORBIDDEN_METRONOME | FORBIDDEN_INSTRUCT, @@ -1037,6 +1047,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_FALSE_SURRENDER] = FORBIDDEN_METRONOME, [MOVE_FEINT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_FIERY_WRATH] = FORBIDDEN_METRONOME, + [MOVE_FILLET_AWAY] = FORBIDDEN_METRONOME, [MOVE_FINAL_GAMBIT] = FORBIDDEN_PARENTAL_BOND, [MOVE_FISSURE] = FORBIDDEN_PARENTAL_BOND, [MOVE_FLEUR_CANNON] = FORBIDDEN_METRONOME, @@ -1062,16 +1073,20 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_HORN_DRILL] = FORBIDDEN_PARENTAL_BOND, [MOVE_HYDRO_CANNON] = FORBIDDEN_INSTRUCT, [MOVE_HYPER_BEAM] = FORBIDDEN_INSTRUCT, + [MOVE_HYPER_DRILL] = FORBIDDEN_METRONOME, [MOVE_HYPERSPACE_FURY] = FORBIDDEN_METRONOME, [MOVE_HYPERSPACE_HOLE] = FORBIDDEN_METRONOME, [MOVE_ICE_BALL] = FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_ICE_BURN] = FORBIDDEN_METRONOME | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_ICICLE_SPEAR] = FORBIDDEN_PARENTAL_BOND, [MOVE_INSTRUCT] = FORBIDDEN_METRONOME | FORBIDDEN_INSTRUCT, + [MOVE_JET_PUNCH] = FORBIDDEN_METRONOME, [MOVE_JUNGLE_HEALING] = FORBIDDEN_METRONOME, [MOVE_KINGS_SHIELD] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_INSTRUCT, [MOVE_LIFE_DEW] = FORBIDDEN_METRONOME, [MOVE_LIGHT_OF_RUIN] = FORBIDDEN_METRONOME, + [MOVE_MAKE_IT_RAIN] = FORBIDDEN_METRONOME, + [MOVE_MAGICAL_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_MAT_BLOCK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_ME_FIRST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_METEOR_ASSAULT] = FORBIDDEN_METRONOME | FORBIDDEN_INSTRUCT, @@ -1085,32 +1100,47 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_MOONGEIST_BEAM] = FORBIDDEN_METRONOME, [MOVE_NATURE_POWER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_NATURES_MADNESS] = FORBIDDEN_METRONOME, + [MOVE_NOXIOUS_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_OBSTRUCT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_INSTRUCT, + [MOVE_ORDER_UP] = FORBIDDEN_METRONOME, [MOVE_ORIGIN_PULSE] = FORBIDDEN_METRONOME, [MOVE_OUTRAGE] = FORBIDDEN_INSTRUCT, [MOVE_OVERDRIVE] = FORBIDDEN_METRONOME, [MOVE_PHANTOM_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_PHOTON_GEYSER] = FORBIDDEN_METRONOME, + [MOVE_PLASMA_FISTS] = FORBIDDEN_METRONOME, + [MOVE_POPULATION_BOMB] = FORBIDDEN_METRONOME, + [MOVE_POUNCE] = FORBIDDEN_METRONOME, + [MOVE_POWER_SHIFT] = FORBIDDEN_METRONOME, + [MOVE_PRECIPICE_BLADES] = FORBIDDEN_METRONOME, [MOVE_PRISMATIC_LASER] = FORBIDDEN_INSTRUCT, [MOVE_PROTECT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_PYRO_BALL] = FORBIDDEN_METRONOME, [MOVE_QUASH] = FORBIDDEN_METRONOME, [MOVE_QUICK_GUARD] = FORBIDDEN_METRONOME, + [MOVE_RAGE_FIST] = FORBIDDEN_METRONOME, [MOVE_RAGE_POWDER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, + [MOVE_RAGING_BULL] = FORBIDDEN_METRONOME, + [MOVE_RAGING_FURY] = FORBIDDEN_METRONOME, [MOVE_RAZOR_WIND] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_RELIC_SONG] = FORBIDDEN_METRONOME, + [MOVE_REVIVAL_BLESSING] = FORBIDDEN_METRONOME, [MOVE_ROAR] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_ROAR_OF_TIME] = FORBIDDEN_INSTRUCT, [MOVE_ROCK_BLAST] = FORBIDDEN_PARENTAL_BOND, [MOVE_ROCK_WRECKER] = FORBIDDEN_INSTRUCT, [MOVE_ROLLOUT] = FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, + [MOVE_RUINATION] = FORBIDDEN_METRONOME, [MOVE_SAPPY_SEED] = FORBIDDEN_METRONOME, + [MOVE_SALT_CURE] = FORBIDDEN_METRONOME, [MOVE_SCALE_SHOT] = FORBIDDEN_PARENTAL_BOND, [MOVE_SECRET_SWORD] = FORBIDDEN_METRONOME, [MOVE_SELF_DESTRUCT] = FORBIDDEN_PARENTAL_BOND, [MOVE_SHADOW_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, + [MOVE_SHED_TAIL] = FORBIDDEN_METRONOME, [MOVE_SHEER_COLD] = FORBIDDEN_PARENTAL_BOND, [MOVE_SHELL_TRAP] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, + [MOVE_SILK_TRAP] = FORBIDDEN_METRONOME, [MOVE_SIZZLY_SLIDE] = FORBIDDEN_METRONOME, [MOVE_SKETCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_SKULL_BASH] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, @@ -1121,10 +1151,12 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_SNARL] = FORBIDDEN_METRONOME, [MOVE_SNATCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_INSTRUCT, [MOVE_SNORE] = FORBIDDEN_METRONOME, + [MOVE_SNOWSCAPE] = FORBIDDEN_METRONOME, [MOVE_SOLAR_BEAM] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_SOLAR_BLADE] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_SPARKLY_SWIRL] = FORBIDDEN_METRONOME, [MOVE_SPECTRAL_THIEF] = FORBIDDEN_METRONOME, + [MOVE_SPICY_EXTRACT] = FORBIDDEN_METRONOME, [MOVE_SPIKE_CANNON] = FORBIDDEN_PARENTAL_BOND, [MOVE_SPIKY_SHIELD] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_SPIRIT_BREAK] = FORBIDDEN_METRONOME, @@ -1144,17 +1176,21 @@ static const u8 sForbiddenMoves[MOVES_COUNT] = [MOVE_THRASH] = FORBIDDEN_INSTRUCT, [MOVE_THUNDER_CAGE] = FORBIDDEN_METRONOME, [MOVE_THUNDEROUS_KICK] = FORBIDDEN_METRONOME, + [MOVE_TIDY_UP] = FORBIDDEN_METRONOME, + [MOVE_TRAILBLAZE] = FORBIDDEN_METRONOME, [MOVE_TRANSFORM] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_INSTRUCT, [MOVE_TRICK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_TRIPLE_AXEL] = FORBIDDEN_PARENTAL_BOND, [MOVE_TRIPLE_KICK] = FORBIDDEN_PARENTAL_BOND, [MOVE_TWINEEDLE] = FORBIDDEN_PARENTAL_BOND, + [MOVE_TWIN_BEAM] = FORBIDDEN_METRONOME, [MOVE_UPROAR] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, [MOVE_V_CREATE] = FORBIDDEN_METRONOME, [MOVE_VEEVEE_VOLLEY] = FORBIDDEN_METRONOME, [MOVE_WATER_SHURIKEN] = FORBIDDEN_PARENTAL_BOND, [MOVE_WHIRLWIND] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT, [MOVE_WICKED_BLOW] = FORBIDDEN_METRONOME, + [MOVE_WICKED_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT, [MOVE_WIDE_GUARD] = FORBIDDEN_METRONOME, [MOVE_ZIPPY_ZAP] = FORBIDDEN_METRONOME, }; From 2aa4d2da3836cad4e422c2f722970ae795105c39 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Tue, 25 Apr 2023 19:38:47 +0200 Subject: [PATCH 114/131] Fix Ice Heal message --- include/constants/item_effects.h | 2 +- src/item.c | 2 +- src/item_use.c | 2 +- src/party_menu.c | 18 ++++++++++-------- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/include/constants/item_effects.h b/include/constants/item_effects.h index 7cd4a58f48..fca7924514 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -74,7 +74,7 @@ #define ITEM_EFFECT_CURE_POISON 3 #define ITEM_EFFECT_CURE_SLEEP 4 #define ITEM_EFFECT_CURE_BURN 5 -#define ITEM_EFFECT_CURE_FREEZE 6 +#define ITEM_EFFECT_CURE_FREEZE_FROSTBITE 6 #define ITEM_EFFECT_CURE_PARALYSIS 7 #define ITEM_EFFECT_CURE_CONFUSION 8 #define ITEM_EFFECT_CURE_INFATUATION 9 diff --git a/src/item.c b/src/item.c index d07e93782f..2c69372446 100644 --- a/src/item.c +++ b/src/item.c @@ -941,7 +941,7 @@ u8 ItemId_GetBattleUsage(u16 itemId) case ITEM_EFFECT_CURE_POISON: case ITEM_EFFECT_CURE_SLEEP: case ITEM_EFFECT_CURE_BURN: - case ITEM_EFFECT_CURE_FREEZE: + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: case ITEM_EFFECT_CURE_PARALYSIS: case ITEM_EFFECT_CURE_ALL_STATUS: case ITEM_EFFECT_CURE_CONFUSION: diff --git a/src/item_use.c b/src/item_use.c index 3a838288b1..86764be3b6 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1244,7 +1244,7 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) case ITEM_EFFECT_CURE_POISON: case ITEM_EFFECT_CURE_SLEEP: case ITEM_EFFECT_CURE_BURN: - case ITEM_EFFECT_CURE_FREEZE: + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: case ITEM_EFFECT_CURE_PARALYSIS: case ITEM_EFFECT_CURE_ALL_STATUS: case ITEM_EFFECT_ATK_EV: diff --git a/src/party_menu.c b/src/party_menu.c index 1623201b10..4eb09c1385 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4317,7 +4317,7 @@ static bool8 IsHPRecoveryItem(u16 item) return FALSE; } -static void GetMedicineItemEffectMessage(u16 item) +static void GetMedicineItemEffectMessage(u16 item, u32 statusCured) { switch (GetItemEffectType(item)) { @@ -4330,10 +4330,11 @@ static void GetMedicineItemEffectMessage(u16 item) case ITEM_EFFECT_CURE_BURN: StringExpandPlaceholders(gStringVar4, gText_PkmnBurnHealed); break; - case ITEM_EFFECT_CURE_FREEZE: - StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); - // TO DO: if it heals frostbite, use the following instead: - // StringExpandPlaceholders(gStringVar4, gText_PkmnFrostbiteHealed); + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: + if (statusCured & STATUS1_FREEZE) + StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); + if (statusCured & STATUS1_FROSTBITE) + StringExpandPlaceholders(gStringVar4, gText_PkmnFrostbiteHealed); break; case ITEM_EFFECT_CURE_PARALYSIS: StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfParalysis); @@ -4497,6 +4498,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; u16 item = gSpecialVar_ItemId; bool8 canHeal, cannotUse; + u32 oldStatus = GetMonData(mon, MON_DATA_STATUS); if (NotUsingHPEVItemOnShedinja(mon, item) == FALSE) { @@ -4549,7 +4551,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) else { GetMonNickname(mon, gStringVar1); - GetMedicineItemEffectMessage(item); + GetMedicineItemEffectMessage(item, oldStatus); DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = task; @@ -4976,7 +4978,7 @@ static void TryUseItemOnMove(u8 taskId) RemoveBagItem(item, 1); move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot); StringCopy(gStringVar1, gMoveNames[move]); - GetMedicineItemEffectMessage(item); + GetMedicineItemEffectMessage(item, 0); DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = Task_ClosePartyMenuAfterText; @@ -5826,7 +5828,7 @@ u8 GetItemEffectType(u16 item) else if (statusCure == ITEM3_BURN) return ITEM_EFFECT_CURE_BURN; else if (statusCure == ITEM3_FREEZE) - return ITEM_EFFECT_CURE_FREEZE; + return ITEM_EFFECT_CURE_FREEZE_FROSTBITE; else if (statusCure == ITEM3_PARALYSIS) return ITEM_EFFECT_CURE_PARALYSIS; else if (statusCure == ITEM3_CONFUSION) From 2885ec24117f47628b2795483594d8793499589b Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Tue, 25 Apr 2023 19:48:45 +0200 Subject: [PATCH 115/131] Fix move descriptions --- src/data/text/move_descriptions.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/data/text/move_descriptions.h b/src/data/text/move_descriptions.h index c2b7e0b234..f950c2a1aa 100644 --- a/src/data/text/move_descriptions.h +++ b/src/data/text/move_descriptions.h @@ -38,7 +38,11 @@ static const u8 sFirePunchDescription[] = _( static const u8 sIcePunchDescription[] = _( "An icy punch that may\n" +#if B_USE_FROSTBITE == TRUE + "leave the foe with frostbite."); +#else "freeze the foe."); +#endif static const u8 sThunderPunchDescription[] = _( "An electrified punch that\n" @@ -238,11 +242,19 @@ static const u8 sSurfDescription[] = _( static const u8 sIceBeamDescription[] = _( "Blasts the foe with an icy\n" +#if B_USE_FROSTBITE == TRUE + "beam. May cause frostbite."); +#else "beam that may freeze it."); +#endif static const u8 sBlizzardDescription[] = _( "Hits the foe with an icy\n" +#if B_USE_FROSTBITE == TRUE + "storm. May cause frostbite."); +#else "storm that may freeze it."); +#endif static const u8 sPsybeamDescription[] = _( "Fires a peculiar ray that\n" @@ -2931,7 +2943,11 @@ static const u8 sDragonEnergyDescription[] = _( static const u8 sFreezingGlareDescription[] = _( "Shoots psychic power from\n" +#if B_USE_FROSTBITE == TRUE + "the eyes. May frostbite."); +#else "the eyes. May freeze the foe."); +#endif static const u8 sFieryWrathDescription[] = _( "An attack fueled by your\n" From 78c4d07b234c026304898bdc2b2fe8edc77a8402 Mon Sep 17 00:00:00 2001 From: Salem <65783283+CallmeEchoo@users.noreply.github.com> Date: Tue, 25 Apr 2023 21:03:57 +0200 Subject: [PATCH 116/131] Add Berserk Gene Item (#2893) Co-authored-by: Eduardo Quezada D'Ottone --- data/battle_scripts_1.s | 27 +++ graphics/items/icon_palettes/berserk_gene.pal | 19 ++ graphics/items/icons/berserk_gene.png | Bin 0 -> 356 bytes include/battle_scripts.h | 1 + include/battle_util.h | 1 + include/constants/battle.h | 1 + include/constants/hold_effects.h | 3 + include/constants/items.h | 3 +- include/graphics.h | 2 + src/battle_main.c | 2 +- src/battle_script_commands.c | 2 + src/battle_util.c | 79 +++++++- src/data/graphics/items.h | 3 + src/data/item_icon_table.h | 1 + src/data/items.h | 13 ++ src/data/text/item_descriptions.h | 5 + test/hold_effect_berserk_gene.c | 187 ++++++++++++++++++ 17 files changed, 340 insertions(+), 9 deletions(-) create mode 100644 graphics/items/icon_palettes/berserk_gene.pal create mode 100644 graphics/items/icons/berserk_gene.png create mode 100644 test/hold_effect_berserk_gene.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4a5af83a2d..dcb076c278 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -10395,3 +10395,30 @@ BattleScript_CouldntFullyProtect:: printstring STRINGID_COULDNTFULLYPROTECT waitmessage B_WAIT_TIME_LONG return + +BattleScript_BerserkGeneRet:: +BattleScript_BerserkGeneRet_Anim: + statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse + setgraphicalstatchangevalues + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM + call BattleScript_StatUp +BattleScript_BerserkGeneRet_TryConfuse: + jumpifability BS_SCRIPTING, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents + jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected + setmoveeffect MOVE_EFFECT_CONFUSION + seteffectprimary + goto BattleScript_BerserkGeneRet_End +BattleScript_BerserkGeneRet_SafeguardProtected:: + pause B_WAIT_TIME_SHORT + printstring STRINGID_PKMNUSEDSAFEGUARD + waitmessage B_WAIT_TIME_LONG + goto BattleScript_BerserkGeneRet_End +BattleScript_BerserkGeneRet_OwnTempoPrevents: + pause B_WAIT_TIME_SHORT + call BattleScript_AbilityPopUp + printstring STRINGID_PKMNPREVENTSCONFUSIONWITH + waitmessage B_WAIT_TIME_LONG +BattleScript_BerserkGeneRet_End: + removeitem BS_SCRIPTING + end3 diff --git a/graphics/items/icon_palettes/berserk_gene.pal b/graphics/items/icon_palettes/berserk_gene.pal new file mode 100644 index 0000000000..3ac8981aa0 --- /dev/null +++ b/graphics/items/icon_palettes/berserk_gene.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +212 146 75 +49 49 49 +131 123 131 +98 90 98 +74 65 74 +164 90 222 +230 180 255 +255 230 238 +255 230 106 +255 189 74 +255 171 32 +238 148 0 +255 246 189 +123 82 32 +0 0 0 +0 0 0 diff --git a/graphics/items/icons/berserk_gene.png b/graphics/items/icons/berserk_gene.png new file mode 100644 index 0000000000000000000000000000000000000000..faac0f67690b8861aa2794e781924c47b26ada27 GIT binary patch literal 356 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w_7YEDSN7*DZ2W5c{>}^efI{LW zt`Q}{`DrEPiAAXl?mjL+V-(6#ixiCYObT0QTLv0`TzgfyZ_I!{_pkrzgpql z6o&ub_ErZe0CfOCK(E1XAjO#E?e6k_Df_3RKu(9Ji(^Q|oaBUr1OXOCMm7V15GF=f zgZ_&gX9A5_ienDsh`MvIGbzjoNM6vgDO15kZS9^tdvuNpCP_sc6G+;|azl<&BmLUE zyVYfH8;Z)_S{A2W=Sh*YNdNxwvd0|T-4EwTY8Y|Y_BimJFmW_+7tk>lJX9#Sr~3Ol nS3#zAX(f!OXC!=NQd+^_oM!J?|9kIKkV8FP{an^LB{Ts5%RhFk literal 0 HcmV?d00001 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index c78fcafe48..876e2d343a 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -461,6 +461,7 @@ extern const u8 BattleScript_CouldntFullyProtect[]; extern const u8 BattleScript_MoveEffectStockpileWoreOff[]; extern const u8 BattleScript_StealthRockActivates[]; extern const u8 BattleScript_SpikesActivates[]; +extern const u8 BattleScript_BerserkGeneRet[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/battle_util.h b/include/battle_util.h index b83209a697..3a28f9b3d8 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -234,5 +234,6 @@ u32 GetBattlerFriendshipScore(u8 battlerId); u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc); bool32 IsMyceliumMightOnField(void); bool8 ChangeTypeBasedOnTerrain(u8 battlerId); +void RemoveConfusionStatus(u8 battlerId); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 61c3776c6c..f0130e58f2 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -185,6 +185,7 @@ #define STATUS4_PLASMA_FISTS (1 << 1) #define STATUS4_MUD_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6 #define STATUS4_WATER_SPORT (1 << 3) // Only used if B_SPORT_TURNS < GEN_6 +#define STATUS4_INFINITE_CONFUSION (1 << 4) // Used for Berserk Gene #define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked. #define HITMARKER_SKIP_DMG_TRACK (1 << 5) diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 5fc268cb05..9f877cffa8 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -161,6 +161,9 @@ #define HOLD_EFFECT_LOADED_DICE 180 #define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented. +// Gen2 hold effect +#define HOLD_EFFECT_BERSERK_GENE 182 + #define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) // Terrain seed params diff --git a/include/constants/items.h b/include/constants/items.h index 4421181668..57ed63feb4 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -972,8 +972,9 @@ #define ITEM_BLACK_AUGURITE 795 #define ITEM_LINKING_CORD 796 #define ITEM_PEAT_BLOCK 797 +#define ITEM_BERSERK_GENE 798 -#define ITEMS_COUNT 798 +#define ITEMS_COUNT 799 #define ITEM_FIELD_ARROW ITEMS_COUNT // A special item id associated with "Cancel"/"Exit" etc. in a list of items or decorations diff --git a/include/graphics.h b/include/graphics.h index 76f6e5d7cf..ad23dc67c8 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -8878,6 +8878,8 @@ extern const u32 gItemIcon_GriseousCore[]; extern const u32 gItemIconPalette_GriseousCore[]; extern const u32 gItemIcon_LustrousGlobe[]; extern const u32 gItemIconPalette_LustrousGlobe[]; +extern const u32 gItemIcon_BerserkGene[]; +extern const u32 gItemIconPalette_BerserkGene[]; extern const u32 gItemIcon_ReturnToFieldArrow[]; extern const u32 gItemIconPalette_ReturnToFieldArrow[]; diff --git a/src/battle_main.c b/src/battle_main.c index c43a2dc3b9..dec2100961 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3227,7 +3227,7 @@ void SwitchInClearSetData(void) gStatuses3[gActiveBattler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED | STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK | STATUS3_AQUA_RING | STATUS3_POWER_TRICK); - gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT); + gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT | STATUS4_INFINITE_CONFUSION); for (i = 0; i < gBattlersCount; i++) { if (GetBattlerSide(gActiveBattler) != GetBattlerSide(i) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3632095963..7195892ffc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16583,6 +16583,8 @@ void BS_ItemCureStatus(void) { if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION) + gStatuses4[gBattlerAttacker] &= ~STATUS4_INFINITE_CONFUSION; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); gBattlescriptCurrInstr = cmd->nextInstr; diff --git a/src/battle_util.c b/src/battle_util.c index cbe7629ee2..f6a9c642bf 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -64,6 +64,7 @@ static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item); static u16 GetInverseTypeMultiplier(u16 multiplier); static u16 GetSupremeOverlordModifier(u8 battlerId); +static bool8 CanBeInfinitelyConfused(u8 battlerId); extern const u8 *const gBattleScriptsForMoveEffects[]; extern const u8 *const gBattlescriptsForRunningByItem[]; @@ -3526,7 +3527,8 @@ u8 AtkCanceller_UnableToUseMove(void) case CANCELLER_CONFUSED: // confusion if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) { - gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); + if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION)) + gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) { // confusion dmg @@ -5968,7 +5970,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus; break; case 2: // get rid of confusion - gBattleMons[battler].status2 &= ~STATUS2_CONFUSION; + RemoveConfusionStatus(battler); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus; break; @@ -6906,7 +6908,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) case HOLD_EFFECT_CURE_CONFUSION: if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION && !UnnerveOn(battlerId, gLastUsedItem)) { - gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + RemoveConfusionStatus(battlerId); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet; effect = ITEM_EFFECT_OTHER; @@ -6947,7 +6949,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); gBattleMons[battlerId].status1 = 0; - gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + RemoveConfusionStatus(battlerId); BattleScriptPushCursor(); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM; gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet; @@ -6985,6 +6987,21 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) effect = ITEM_EFFECT_OTHER; } break; + case HOLD_EFFECT_BERSERK_GENE: + BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE); + gEffectBattler = battlerId; + if (CanBeInfinitelyConfused(gEffectBattler)) + { + gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION; + } + SET_STATCHANGER(STAT_ATK, 2, FALSE); + + gBattleScripting.animArg1 = 14 + STAT_ATK; + gBattleScripting.animArg2 = 0; + + BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet); + effect = ITEM_STATS_CHANGE; + break; } return effect; @@ -7163,7 +7180,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) else gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS; gBattleMons[battlerId].status1 = 0; - gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + RemoveConfusionStatus(battlerId); BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2); effect = ITEM_STATUS_CHANGE; } @@ -7224,6 +7241,21 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } } break; + case HOLD_EFFECT_BERSERK_GENE: + BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE); + gEffectBattler = battlerId; + if (CanBeInfinitelyConfused(gEffectBattler)) + { + gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION; + } + SET_STATCHANGER(STAT_ATK, 2, FALSE); + + gBattleScripting.animArg1 = 14 + STAT_ATK; + gBattleScripting.animArg2 = 0; + + BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet); + effect = ITEM_STATS_CHANGE; + break; } if (effect != 0) { @@ -7444,7 +7476,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) case HOLD_EFFECT_CURE_CONFUSION: if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION && !UnnerveOn(battlerId, gLastUsedItem)) { - gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + RemoveConfusionStatus(battlerId); BattleScriptExecute(BattleScript_BerryCureConfusionEnd2); effect = ITEM_EFFECT_OTHER; } @@ -7489,7 +7521,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) else gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS; gBattleMons[battlerId].status1 = 0; - gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + RemoveConfusionStatus(battlerId); BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2); effect = ITEM_STATUS_CHANGE; } @@ -7507,6 +7539,21 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) if (!moveTurn) effect = TrySetMicleBerry(battlerId, gLastUsedItem, TRUE); break; + case HOLD_EFFECT_BERSERK_GENE: + BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE); + gEffectBattler = battlerId; + if (CanBeInfinitelyConfused(gEffectBattler)) + { + gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION; + } + SET_STATCHANGER(STAT_ATK, 2, FALSE); + + gBattleScripting.animArg1 = 14 + STAT_ATK; + gBattleScripting.animArg2 = 0; + + BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet); + effect = ITEM_STATS_CHANGE; + break; } if (effect != 0) @@ -10870,3 +10917,21 @@ static void SetRandomMultiHitCounter() gMultiHitCounter = 5 - (Random() & 1); } } + +void RemoveConfusionStatus(u8 battlerId) +{ + gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + gStatuses4[battlerId] &= ~STATUS4_INFINITE_CONFUSION; +} + +static bool8 CanBeInfinitelyConfused(u8 battlerId) +{ + if (gBattleMons[battlerId].ability == ABILITY_OWN_TEMPO + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD) + { + return FALSE; + } + return TRUE; +} + diff --git a/src/data/graphics/items.h b/src/data/graphics/items.h index 1e60357b3e..9ef79b2c92 100644 --- a/src/data/graphics/items.h +++ b/src/data/graphics/items.h @@ -1998,3 +1998,6 @@ const u32 gItemIconPalette_GriseousCore[] = INCBIN_U32("graphics/items/icon_pale const u32 gItemIcon_LustrousGlobe[] = INCBIN_U32("graphics/items/icons/lustrous_globe.4bpp.lz"); const u32 gItemIconPalette_LustrousGlobe[] = INCBIN_U32("graphics/items/icon_palettes/lustrous_globe.gbapal.lz"); + +const u32 gItemIcon_BerserkGene[] = INCBIN_U32("graphics/items/icons/berserk_gene.4bpp.lz"); +const u32 gItemIconPalette_BerserkGene[] = INCBIN_U32("graphics/items/icon_palettes/berserk_gene.gbapal.lz"); diff --git a/src/data/item_icon_table.h b/src/data/item_icon_table.h index f220bd819c..05a8782812 100644 --- a/src/data/item_icon_table.h +++ b/src/data/item_icon_table.h @@ -843,6 +843,7 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] = [ITEM_BLACK_AUGURITE] = {gItemIcon_BlackAugurite, gItemIconPalette_BlackAugurite}, [ITEM_LINKING_CORD] = {gItemIcon_LinkingCord, gItemIconPalette_LinkingCord}, [ITEM_PEAT_BLOCK] = {gItemIcon_PeatBlock, gItemIconPalette_PeatBlock}, + [ITEM_BERSERK_GENE] = {gItemIcon_BerserkGene, gItemIconPalette_BerserkGene}, // Return to field arrow [ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow}, }; diff --git a/src/data/items.h b/src/data/items.h index 84436be55b..67c5b477f5 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -10340,4 +10340,17 @@ const struct Item gItems[] = .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .flingPower = 30, }, + + [ITEM_BERSERK_GENE] = + { + .name = _("Berserk Gene"), + .itemId = ITEM_BERSERK_GENE, + .price = 20, + .holdEffect = HOLD_EFFECT_BERSERK_GENE, + .description = sBerserkGene, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 10, + }, }; diff --git a/src/data/text/item_descriptions.h b/src/data/text/item_descriptions.h index 5dc870038a..dddf8552f5 100644 --- a/src/data/text/item_descriptions.h +++ b/src/data/text/item_descriptions.h @@ -3907,3 +3907,8 @@ static const u8 sLustrousGlobeDesc[] = _( "A large, glowing gem\n" "that lets Palkia\n" "change form."); + +static const u8 sBerserkGene[] = _( + "Sharply boosts\n" + "Attack, but causes\n" + "lasting confusion."); diff --git a/test/hold_effect_berserk_gene.c b/test/hold_effect_berserk_gene.c new file mode 100644 index 0000000000..361d148611 --- /dev/null +++ b/test/hold_effect_berserk_gene.c @@ -0,0 +1,187 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_BERSERK_GENE].holdEffect == HOLD_EFFECT_BERSERK_GENE); +} + +SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of battle", s16 damage) +{ + u16 useItem; + PARAMETRIZE { useItem = FALSE; } + PARAMETRIZE { useItem = TRUE; } + if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_TACKLE); + } + } SCENE { + if (useItem) + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player); + MESSAGE("Wobbuffet became confused!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Berserk Gene activates on switch in", s16 damage) +{ + u16 useItem; + PARAMETRIZE { useItem = FALSE; } + PARAMETRIZE { useItem = TRUE; } + if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION); + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + SWITCH(player, 1); + } TURN { + MOVE(player, MOVE_TACKLE); + } + } SCENE { + if (useItem) + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player); + MESSAGE("Wobbuffet became confused!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but still raises attack sharply", s16 damage) +{ + u16 useItem; + PARAMETRIZE { useItem = FALSE; } + PARAMETRIZE { useItem = TRUE; } + GIVEN { + PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); if (useItem) Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_TACKLE); + } + } SCENE { + if (useItem) + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Berserk Gene, the Attack of Slowbro sharply rose!"); + ABILITY_POPUP(player, ABILITY_OWN_TEMPO); + MESSAGE("Slowbro's Own Tempo prevents confusion!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + NONE_OF + { + MESSAGE("Slowbro became confused!"); + } + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Berserk Gene does not confuse on Misty Terrain but still raises attack sharply") +{ + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + PLAYER(SPECIES_TAPU_FINI) { Ability(ABILITY_MISTY_SURGE); Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_TACKLE); + } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Berserk Gene, the Attack of Tapu Fini sharply rose!"); + NONE_OF + { + MESSAGE("Tapu Fini became confused!"); + } + } +} + +SINGLE_BATTLE_TEST("Berserk Gene does not confuse when Safeguard is active") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SAFEGUARD); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!"); + MESSAGE("Wobbuffet's party is protected by SAFEGUARD!"); + NONE_OF + { + MESSAGE("Wobbuffet became confused!"); + } + } +} + +SINGLE_BATTLE_TEST("Berserk Gene causes confusion for more than 5 turns") // how else would be check for infinite? +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + NONE_OF + { + MESSAGE("Wobbuffet snapped out of confusion!"); + } + } +} + +SINGLE_BATTLE_TEST("Berserk Gene causes infinite confusion") // check if bit is set +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN {} + } SCENE { + } THEN { + EXPECT(gStatuses4[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] & STATUS4_INFINITE_CONFUSION); + } +} + +SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 status2) +{ + u32 turns; + PARAMETRIZE { turns = 1; } + PARAMETRIZE { turns = 2; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + u32 count; + for (count = 0; count < turns; count++) { + TURN {} + } + } THEN { + results[i].status2 = player->status2; + } FINALLY { + EXPECT_EQ(results[0].status2, results[1].status2); + } +} From 0315f704c1639cc1c37a4fa816797a15bef63d2c Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Tue, 25 Apr 2023 23:01:58 +0200 Subject: [PATCH 117/131] Fix thawing being triggered by every move --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 903edc1ac6..98b0b6744f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3650,7 +3650,7 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 2; } - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && (gBattleMoves[gCurrentMove].flags & FLAG_THAW_USER)) { if (!(gBattleMoves[gCurrentMove].effect == EFFECT_BURN_UP && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) { From 32dcea0cdb52a747b552bf3ccac5e598f864444a Mon Sep 17 00:00:00 2001 From: grunt-lucas Date: Wed, 26 Apr 2023 13:08:15 -0600 Subject: [PATCH 118/131] Fix issue with Enamorus Therian cry define order (#2956) --- sound/direct_sound_data.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/direct_sound_data.inc b/sound/direct_sound_data.inc index 05a1b7145e..3020a8f1a5 100644 --- a/sound/direct_sound_data.inc +++ b/sound/direct_sound_data.inc @@ -4246,6 +4246,10 @@ Cry_ThundurusTherian:: Cry_LandorusTherian:: .incbin "sound/direct_sound_samples/cries/landorus_therian.bin" + .align 2 +Cry_EnamorusTherian:: + .incbin "sound/direct_sound_samples/cries/enamorus_therian.bin" + .align 2 Cry_KyuremWhite:: .incbin "sound/direct_sound_samples/cries/kyurem_white.bin" @@ -4360,10 +4364,6 @@ Cry_CalyrexIceRider:: Cry_CalyrexShadowRider:: .incbin "sound/direct_sound_samples/cries/calyrex_shadow_rider.bin" - .align 2 -Cry_EnamorusTherian:: - .incbin "sound/direct_sound_samples/cries/enamorus_therian.bin" - .endif .align 2 From d5fb13ca17d0b59eb029e9ebbbdadbed61ac1b73 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Wed, 26 Apr 2023 23:33:22 +0200 Subject: [PATCH 119/131] Fix status icons --- graphics/battle_interface/status2.png | Bin 559 -> 559 bytes graphics/battle_interface/status3.png | Bin 559 -> 559 bytes graphics/battle_interface/status4.png | Bin 559 -> 559 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/battle_interface/status2.png b/graphics/battle_interface/status2.png index 0b212907e5574725f3c8f3d4f95a713b44fc02e2..5d7f6459be316f5e0b6d75db60329c71761e3c98 100644 GIT binary patch delta 42 xcmZ3_vYusw9V6$qmMICG(-Qu_o$StdMWpF|y~*_l6&egc;OXk;vd$@?2>^5#5SRb} delta 42 xcmZ3_vYusw9V6$~mMICG(-QuFo$StdMI^5>kRCSc3g`vz($tH;e)0=@&x*tjQ4A3gszO z_VmdRQmQT0Nvs>tOoa`|YUOca)iZzwUYB3X1$>hEJD!Ka!`^2q#VH=)gns~20h3x! z%wqv?2R!h9xqvO1zk{X#^fj4)lhPyy26Tf1U7SGMrP@(yf_Zv5?}jMrUM^ry=I`j8 zBRiWZDYON;I*lc7?>mg*#q3Fc-&3((C| zDuIyz?ox62wcO8s^!Ss9e!!t0o_Y1dTXpW>3NYHXUw$k12f#gqW~~#ZPXGV_07*qo IM6N<$f~|6R+5i9m delta 258 zcmV+d0sa231g`|JHUWRz5yT(}MIHFHgp^KQ--ugkCH0zS$79nVAIVed1Q;uMc?!asnifJv<< z=CJ^{10MLlT)>vh-$7FV`kG9@NokS;1G>S1E>58BQtc=;!Mu8$cSDqQFBh;U^LO;l zk)6$y6xsq^oyUFxI(J|yp3f&-%mA)Z>*d#S0Y@@_#~2jc$xx|bOLY>*1aq^X1?c7} zmB2^lKj6?0&%FBKtvYvb1sHAHFTa)h17t9Kn;^jN>i_@%07*qo IM6N<$g3XM3`v3p{ From 854e9be3257c227242cff643e887bd68123d12c5 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Fri, 28 Apr 2023 11:26:31 +0200 Subject: [PATCH 120/131] Fix move defrosting for both Freeze and Frostbite --- src/battle_script_commands.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4792504a6d..fecea28927 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5596,7 +5596,6 @@ static void Cmd_moveend(void) if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE && gBattleMons[gBattlerTarget].hp != 0 && gBattlerAttacker != gBattlerTarget - && gSpecialStatuses[gBattlerTarget].specialDmg && (moveType == TYPE_FIRE #if B_BURN_HIT_THAW >= GEN_6 || gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT @@ -5615,12 +5614,7 @@ static void Cmd_moveend(void) if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE && gBattleMons[gBattlerTarget].hp != 0 && gBattlerAttacker != gBattlerTarget - && gSpecialStatuses[gBattlerTarget].specialDmg - && (moveType == TYPE_FIRE - #if B_BURN_HIT_THAW >= GEN_6 - || gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT - #endif - ) + && gBattleMoves[originallyUsedMove].flags & FLAG_THAW_USER && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; From a98da30ec7bb8b11127367c397cbcdef2a7137c6 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 28 Apr 2023 12:38:34 +0200 Subject: [PATCH 121/131] frostbite tests --- test/status_frostbite.c | 98 +++++++++++++++++++++++++++++++++++++++ test/test_battle.h | 6 +-- test/test_runner_battle.c | 2 + 3 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 test/status_frostbite.c diff --git a/test/status_frostbite.c b/test/status_frostbite.c new file mode 100644 index 0000000000..6abd34a312 --- /dev/null +++ b/test/status_frostbite.c @@ -0,0 +1,98 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Frostbite reduces the special attack by 50 percent") +{ + s16 reducedDamage; + s16 normaleDamage; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SWIFT); MOVE(player, MOVE_FIRE_PUNCH); } + TURN { MOVE(opponent, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, opponent); + HP_BAR(player, captureDamage: &reducedDamage); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PUNCH, player); + HP_BAR(opponent); + MESSAGE("Foe Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, opponent); + HP_BAR(player, captureDamage: &normaleDamage); + } THEN { EXPECT_EQ(reducedDamage, normaleDamage); } +} + +SINGLE_BATTLE_TEST("Frostbite deals 1/16 damage to effected pokemon") +{ + s16 frostbiteDamage; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + } WHEN { + TURN { } + } SCENE { + MESSAGE("Foe Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + HP_BAR(opponent, captureDamage: &frostbiteDamage); + } THEN { EXPECT_EQ(frostbiteDamage, opponent->maxHP / 16); } +} + +SINGLE_BATTLE_TEST("Frostbite is healed if hit with a thawing move") +{ + u32 move; + + PARAMETRIZE { move = MOVE_FLAME_WHEEL; } + PARAMETRIZE { move = MOVE_SACRED_FIRE; } + PARAMETRIZE { move = MOVE_FLARE_BLITZ; } + PARAMETRIZE { move = MOVE_FUSION_FLARE; } + PARAMETRIZE { move = MOVE_EMBER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + if (move == MOVE_EMBER) { + NONE_OF { + MESSAGE("Foe Wobbuffet's frostbite was healed!"); + } + } else { + MESSAGE("Foe Wobbuffet's frostbite was healed!"); + } + } +} + +SINGLE_BATTLE_TEST("Frostbite is healed when the user uses a thawing move") +{ + u32 move; + + PARAMETRIZE { move = MOVE_FLAME_WHEEL; } + PARAMETRIZE { move = MOVE_SACRED_FIRE; } + PARAMETRIZE { move = MOVE_FLARE_BLITZ; } + PARAMETRIZE { move = MOVE_FUSION_FLARE; } + PARAMETRIZE { move = MOVE_EMBER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + if (move == MOVE_EMBER) { + MESSAGE("Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, player); + } else { + NONE_OF { + MESSAGE("Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, player); + } + } + } +} diff --git a/test/test_battle.h b/test/test_battle.h index 967bb661dd..432e33fa80 100644 --- a/test/test_battle.h +++ b/test/test_battle.h @@ -333,7 +333,7 @@ * Used when the battler chooses to switch to another Pokémon but not * via Switch, e.g. after fainting or due to a U-turn. * SEND_OUT(player, 1); - * + * * USE_ITEM(battler, itemId, [partyIndex:], [move:]) * Used when the battler chooses to use an item from the Bag. The item * ID must be specified, and party index and move slot if applicable, e.g: @@ -526,8 +526,7 @@ struct QueuedMessageEvent struct QueuedStatusEvent { u32 battlerId:3; - u32 mask:8; - u32 unused_01:21; + u32 mask:29; }; struct QueuedEvent @@ -872,6 +871,7 @@ struct StatusEventContext bool8 freeze:1; bool8 paralysis:1; bool8 badPoison:1; + bool8 frostbite:1; }; void OpenQueueGroup(u32 sourceLine, enum QueueGroupType); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 365120f137..a6fc00c276 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1717,6 +1717,8 @@ void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEve mask = STATUS1_PARALYSIS; else if (ctx.badPoison) mask = STATUS1_TOXIC_POISON; + else if (ctx.frostbite) + mask = STATUS1_FROSTBITE; else mask = ctx.status1; From bfcddff3ca37bdcfbde2f2b08a2942e5477090a0 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 28 Apr 2023 12:47:30 +0200 Subject: [PATCH 122/131] correct first test --- test/status_frostbite.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/status_frostbite.c b/test/status_frostbite.c index 6abd34a312..f034478217 100644 --- a/test/status_frostbite.c +++ b/test/status_frostbite.c @@ -10,18 +10,16 @@ SINGLE_BATTLE_TEST("Frostbite reduces the special attack by 50 percent") PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } } WHEN { - TURN { MOVE(opponent, MOVE_SWIFT); MOVE(player, MOVE_FIRE_PUNCH); } + TURN { MOVE(opponent, MOVE_SWIFT); MOVE(player, MOVE_FLAME_WHEEL); } TURN { MOVE(opponent, MOVE_SWIFT); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, opponent); HP_BAR(player, captureDamage: &reducedDamage); - ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PUNCH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLAME_WHEEL, player); HP_BAR(opponent); - MESSAGE("Foe Wobbuffet is hurt by its frostbite!"); - ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, opponent); HP_BAR(player, captureDamage: &normaleDamage); - } THEN { EXPECT_EQ(reducedDamage, normaleDamage); } + } THEN { EXPECT_EQ(reducedDamage * 2, normaleDamage); } } SINGLE_BATTLE_TEST("Frostbite deals 1/16 damage to effected pokemon") From 0cbb80dda76175a0ec5cb94aded25ed505ae74a8 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:58:43 +0200 Subject: [PATCH 123/131] Fix grassy terrain freezing the game (#2959) --- data/battle_scripts_1.s | 4 ++-- test/terrain_electric.c | 29 +++++++++++++++++++++++++++++ test/terrain_grassy.c | 29 +++++++++++++++++++++++++++++ test/terrain_misty.c | 29 +++++++++++++++++++++++++++++ test/terrain_psychic.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index dcb076c278..ec73fd6b25 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6944,14 +6944,14 @@ BattleScript_MagicRoomEnds:: waitmessage B_WAIT_TIME_LONG end2 -BattleScript_GrassyTerrainEnds: - setbyte cMULTISTRING_CHOOSER, B_MSG_TERRAINENDS_GRASS BattleScript_TerrainEnds_Ret:: printfromtable gTerrainEndingStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG return +BattleScript_GrassyTerrainEnds: + setbyte cMULTISTRING_CHOOSER, B_MSG_TERRAINENDS_GRASS BattleScript_TerrainEnds:: call BattleScript_TerrainEnds_Ret end2 diff --git a/test/terrain_electric.c b/test/terrain_electric.c index bb397fdf9b..e9c34ef923 100644 --- a/test/terrain_electric.c +++ b/test/terrain_electric.c @@ -61,3 +61,32 @@ SINGLE_BATTLE_TEST("Electric Terrain increases power of Electric-type moves by 3 EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); } } + +SINGLE_BATTLE_TEST("Electric Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_ELECTRIC_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + MESSAGE("An electric current runs across the battlefield!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The electricity disappeared from the battlefield."); + } +} diff --git a/test/terrain_grassy.c b/test/terrain_grassy.c index ae6e6d9e92..7668c49bde 100644 --- a/test/terrain_grassy.c +++ b/test/terrain_grassy.c @@ -84,3 +84,32 @@ SINGLE_BATTLE_TEST("Grassy Terrain decreases power of Earthquake and Bulldoze by EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage); } } + +SINGLE_BATTLE_TEST("Grassy Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GRASSY_TERRAIN, player); + MESSAGE("Grass grew to cover the battlefield!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The grass disappeared from the battlefield."); + } +} diff --git a/test/terrain_misty.c b/test/terrain_misty.c index 668b036992..4f8793d9d0 100644 --- a/test/terrain_misty.c +++ b/test/terrain_misty.c @@ -78,3 +78,32 @@ SINGLE_BATTLE_TEST("Misty Terrain decreases power of Dragon-type moves by 50 per EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); } } + +SINGLE_BATTLE_TEST("Misty Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_MISTY_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_TERRAIN, player); + MESSAGE("Mist swirled about the battlefield!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The mist disappeared from the battlefield."); + } +} diff --git a/test/terrain_psychic.c b/test/terrain_psychic.c index 2cddef070f..3ecfa99e06 100644 --- a/test/terrain_psychic.c +++ b/test/terrain_psychic.c @@ -136,3 +136,32 @@ SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority field moves", s16 dam MESSAGE("Sableye used Sunny Day!"); } } + +SINGLE_BATTLE_TEST("Psychic Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHIC_TERRAIN, player); + MESSAGE("The battlefield got weird!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The weirdness disappeared from the battlefield."); + } +} From c82c2c185ecc62b58e79ab5feb5e29b3e4268f8f Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 29 Apr 2023 18:29:50 +0200 Subject: [PATCH 124/131] Integrate ghoul's review Co-Authored-By: ghoulslash <41651341+ghoulslash@users.noreply.github.com> --- src/battle_script_commands.c | 10 ---------- src/battle_util.c | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 81c39f893c..ccbb488d2e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -15147,16 +15147,6 @@ static void Cmd_doweatherformchangeanimation(void) static void Cmd_tryweatherformdatachange(void) { CMD_ARGS(); - - u8 form; - - // gBattlescriptCurrInstr = cmd->nextInstr; - // form = TryWeatherFormChange(gBattleScripting.battler); - // if (form) - // { - // BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - // *(&gBattleStruct->formToChangeInto) = form - 1; - // } } // Water and Mud Sport diff --git a/src/battle_util.c b/src/battle_util.c index e3c4ceed69..aab0f2db6d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2487,7 +2487,7 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_WEATHER_FORM: - for (i = 0; i < gBattlersCount; ++i) + for (i = 0; i < gBattlersCount; i++) { if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) { @@ -10154,7 +10154,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) { u8 monId = gBattlerPartyIndexes[battlerId]; u8 side = GET_BATTLER_SIDE(battlerId); - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *party = GetBattlerParty(battlerId); u16 targetSpecies; if (!CanBattlerFormChange(battlerId, method)) From c7d39e561dd638e9da7b96768fb51c085ea5b58b Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 29 Apr 2023 20:41:54 +0200 Subject: [PATCH 125/131] Clarify weather function --- src/battle_script_commands.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ccbb488d2e..aead0fe3c2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -15147,6 +15147,8 @@ static void Cmd_doweatherformchangeanimation(void) static void Cmd_tryweatherformdatachange(void) { CMD_ARGS(); + + // removed in favor of new form system } // Water and Mud Sport From b30dad3e7aa4655ccb659cbbe3e909253d49be57 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sat, 29 Apr 2023 21:56:23 -0400 Subject: [PATCH 126/131] Fix anger shell activating when fainted (#2945) Co-authored-by: ghoulslash --- src/battle_util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_util.c b/src/battle_util.c index b89b9976ee..bf332e64df 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5767,6 +5767,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED + && IsBattlerAlive(gBattlerTarget) && (gBattleMons[gBattlerTarget].hp <= gBattleMons[gBattlerTarget].maxHP / 2) && !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove))) { From 176c6750aa9ce07d72647dc9487234421626a82d Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 30 Apr 2023 16:02:18 +0200 Subject: [PATCH 127/131] Set new animations as default (#2964) --- include/config/battle.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index d1d4fc52fc..4b3caf4abe 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -197,21 +197,21 @@ #define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level // Animation Settings -#define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. -#define B_NEW_LEECH_SEED_PARTICLE FALSE // If set to TRUE, it updates Leech Seed's animation particle. -#define B_NEW_HORN_ATTACK_PARTICLE FALSE // If set to TRUE, it updates Horn Attack's horn particle. +#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle. +#define B_NEW_LEECH_SEED_PARTICLE TRUE // If set to TRUE, it updates Leech Seed's animation particle. +#define B_NEW_HORN_ATTACK_PARTICLE TRUE // If set to TRUE, it updates Horn Attack's horn particle. #define B_NEW_ROCKS_PARTICLE TRUE // If set to TRUE, it updates rock particles. -#define B_NEW_LEAF_PARTICLE FALSE // If set to TRUE, it updates leaf particle. -#define B_NEW_EMBER_PARTICLES FALSE // If set to TRUE, it updates Ember's fire particle. -#define B_NEW_MEAN_LOOK_PARTICLE FALSE // If set to TRUE, it updates Mean Look's eye particle. -#define B_NEW_TEETH_PARTICLE FALSE // If set to TRUE, it updates Bite/Crunch teeth particle. -#define B_NEW_HANDS_FEET_PARTICLE FALSE // If set to TRUE, it updates chop/kick/punch particles. -#define B_NEW_SPIKES_PARTICLE FALSE // If set to TRUE, it updates Spikes particle. -#define B_NEW_FLY_BUBBLE_PARTICLE FALSE // If set to TRUE, it updates Fly's 'bubble' particle. -#define B_NEW_CURSE_NAIL_PARTICLE FALSE // If set to TRUE, it updates Curse's nail. -#define B_NEW_BATON_PASS_BALL_PARTICLE FALSE // If set to TRUE, it updates Baton Pass' Poké Ball sprite. -#define B_NEW_MORNING_SUN_STAR_PARTICLE FALSE // If set to TRUE, it updates Morning Sun's star particles. -#define B_NEW_IMPACT_PALETTE FALSE // If set to TRUE, it updates the basic 'hit' palette. -#define B_NEW_SURF_PARTICLE_PALETTE FALSE // If set to TRUE, it updates Surf's wave palette. +#define B_NEW_LEAF_PARTICLE TRUE // If set to TRUE, it updates leaf particle. +#define B_NEW_EMBER_PARTICLES TRUE // If set to TRUE, it updates Ember's fire particle. +#define B_NEW_MEAN_LOOK_PARTICLE TRUE // If set to TRUE, it updates Mean Look's eye particle. +#define B_NEW_TEETH_PARTICLE TRUE // If set to TRUE, it updates Bite/Crunch teeth particle. +#define B_NEW_HANDS_FEET_PARTICLE TRUE // If set to TRUE, it updates chop/kick/punch particles. +#define B_NEW_SPIKES_PARTICLE TRUE // If set to TRUE, it updates Spikes particle. +#define B_NEW_FLY_BUBBLE_PARTICLE TRUE // If set to TRUE, it updates Fly's 'bubble' particle. +#define B_NEW_CURSE_NAIL_PARTICLE TRUE // If set to TRUE, it updates Curse's nail. +#define B_NEW_BATON_PASS_BALL_PARTICLE TRUE // If set to TRUE, it updates Baton Pass' Poké Ball sprite. +#define B_NEW_MORNING_SUN_STAR_PARTICLE TRUE // If set to TRUE, it updates Morning Sun's star particles. +#define B_NEW_IMPACT_PALETTE TRUE // If set to TRUE, it updates the basic 'hit' palette. +#define B_NEW_SURF_PARTICLE_PALETTE TRUE // If set to TRUE, it updates Surf's wave palette. #endif // GUARD_CONFIG_BATTLE_H From 2d6282fece6327275b26e8697cc0f949d94a2c2f Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 30 Apr 2023 16:46:21 +0200 Subject: [PATCH 128/131] Fix for Burn Up/Double Shock (#2962) --- data/battle_scripts_1.s | 10 ++++--- test/move_effect_burn_up.c | 53 +++++++++++++++++++++++++++++++++ test/move_effect_double_shock.c | 53 +++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 test/move_effect_burn_up.c create mode 100644 test/move_effect_double_shock.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index be20f6809d..42219c7ee2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1444,8 +1444,9 @@ BattleScript_EffectBurnUp: goto BattleScript_ButItFailed BattleScript_BurnUpWorks: - setmoveeffect MOVE_EFFECT_BURN_UP | MOVE_EFFECT_CERTAIN - goto BattleScript_EffectHit + setmoveeffect MOVE_EFFECT_BURN_UP | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc BattleScript_BurnUpRemoveType:: losetype BS_ATTACKER, TYPE_FIRE @@ -1461,8 +1462,9 @@ BattleScript_EffectDoubleShock: goto BattleScript_ButItFailed BattleScript_DoubleShockWorks: - setmoveeffect MOVE_EFFECT_DOUBLE_SHOCK | MOVE_EFFECT_CERTAIN - goto BattleScript_EffectHit + setmoveeffect MOVE_EFFECT_DOUBLE_SHOCK | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc BattleScript_DoubleShockRemoveType:: losetype BS_ATTACKER, TYPE_ELECTRIC diff --git a/test/move_effect_burn_up.c b/test/move_effect_burn_up.c new file mode 100644 index 0000000000..a53b1afa86 --- /dev/null +++ b/test/move_effect_burn_up.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_BURN_UP].effect == EFFECT_BURN_UP); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_FIRE || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_CYNDAQUIL].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_CYNDAQUIL].types[1] == TYPE_FIRE); +} + +SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type") +{ + GIVEN { + PLAYER(SPECIES_CYNDAQUIL); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + MESSAGE("Cyndaquil burned itself out!"); + MESSAGE("Cyndaquil used Burn Up!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Burn Up fails if the user isn't a Fire-type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); } + MESSAGE("Wobbuffet used Burn Up!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type if enemy faints") +{ + GIVEN { + PLAYER(SPECIES_CYNDAQUIL); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent, hp: 0); + MESSAGE("Cyndaquil burned itself out!"); + } +} diff --git a/test/move_effect_double_shock.c b/test/move_effect_double_shock.c new file mode 100644 index 0000000000..c3651c4034 --- /dev/null +++ b/test/move_effect_double_shock.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_DOUBLE_SHOCK].effect == EFFECT_DOUBLE_SHOCK); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ELECTRIC || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ELECTRIC); + ASSUME(gSpeciesInfo[SPECIES_PIKACHU].types[0] == TYPE_ELECTRIC || gSpeciesInfo[SPECIES_PIKACHU].types[1] == TYPE_ELECTRIC); +} + +SINGLE_BATTLE_TEST("Double Shock user loses its Electric-type") +{ + GIVEN { + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SHOCK, player); + MESSAGE("Pikachu used up all of its electricity!"); + MESSAGE("Pikachu used Double Shock!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Double Shock fails if the user isn't an Electric-type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SHOCK, player); } + MESSAGE("Wobbuffet used Double Shock!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Double Shock user loses its Electric-type if enemy faints") +{ + GIVEN { + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SHOCK, player); + HP_BAR(opponent, hp: 0); + MESSAGE("Pikachu used up all of its electricity!"); + } +} From 32e63d8cc7bae997c2dc520a27a17ee18984b285 Mon Sep 17 00:00:00 2001 From: Ultimate_Bob Date: Mon, 1 May 2023 11:15:03 +1000 Subject: [PATCH 129/131] Don't copy opponent personality when swapping mon sprite during Mega Evolution (#2852) Co-authored-by: Eduardo Quezada D'Ottone --- data/battle_anim_scripts.s | 14 +++++----- include/battle.h | 2 ++ include/battle_gfx_sfx_util.h | 2 +- include/config/battle.h | 1 + src/battle_anim_effects_3.c | 4 ++- src/battle_controller_link_opponent.c | 1 + src/battle_controller_link_partner.c | 1 + src/battle_controller_opponent.c | 1 + src/battle_controller_player.c | 1 + src/battle_controller_player_partner.c | 1 + src/battle_controller_recorded_opponent.c | 1 + src/battle_controller_recorded_player.c | 1 + src/battle_controller_wally.c | 1 + src/battle_gfx_sfx_util.c | 34 +++++++++++++++++++---- src/battle_main.c | 1 + src/battle_script_commands.c | 1 + 16 files changed, 53 insertions(+), 14 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index adcb88c881..dcfdac88ed 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -22317,7 +22317,7 @@ Move_TRANSFORM: monbg ANIM_ATTACKER playsewithpan SE_M_TELEPORT, SOUND_PAN_ATTACKER waitplaysewithpan SE_M_MINIMIZE, SOUND_PAN_ATTACKER, 48 - createvisualtask AnimTask_TransformMon, 2, 0, 0 + createvisualtask AnimTask_TransformMon, 2, 0, 0, 1 waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -24406,7 +24406,7 @@ WeatherFormChangeContinue: monbg ANIM_ATTACKER playsewithpan SE_M_TELEPORT, SOUND_PAN_ATTACKER waitplaysewithpan SE_M_MINIMIZE, SOUND_PAN_ATTACKER, 48 - createvisualtask AnimTask_TransformMon, 2, 1, 0 + createvisualtask AnimTask_TransformMon, 2, 1, 0, 0 waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -24829,14 +24829,14 @@ General_WishHeal: General_IllusionOff: monbg ANIM_TARGET - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 waitforvisualfinish clearmonbg ANIM_TARGET end General_FormChange: monbg ANIM_ATTACKER - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -24865,7 +24865,7 @@ General_MegaEvolution: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14 waitforvisualfinish @@ -25011,7 +25011,7 @@ General_PrimalReversion_Alpha: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14 waitforvisualfinish @@ -25038,7 +25038,7 @@ General_PrimalReversion_Omega: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14 waitforvisualfinish diff --git a/include/battle.h b/include/battle.h index 4ba3cba6e3..35c3525b81 100644 --- a/include/battle.h +++ b/include/battle.h @@ -62,6 +62,7 @@ struct ResourceFlags struct DisableStruct { u32 transformedMonPersonality; + u32 transformedMonOtId; u16 disabledMove; u16 encoredMove; u8 protectUses; @@ -976,6 +977,7 @@ extern u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT]; extern u8 gBattlerInMenuId; extern bool8 gDoingBattleAnim; extern u32 gTransformedPersonalities[MAX_BATTLERS_COUNT]; +extern u32 gTransformedOtIds[MAX_BATTLERS_COUNT]; extern u8 gPlayerDpadHoldFrames; extern struct BattleSpriteData *gBattleSpritesDataPtr; extern struct MonSpritesGfx *gMonSpritesGfxPtr; diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index 491d5fefd1..9a0b79c313 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -23,7 +23,7 @@ bool8 BattleInitAllSprites(u8 *state1, u8 *battlerId); void ClearSpritesHealthboxAnimData(void); void CopyAllBattleSpritesInvisibilities(void); void CopyBattleSpriteInvisibility(u8 battlerId); -void HandleSpeciesGfxDataChange(u8 attacker, u8 target, bool8 notTransform, bool32 megaEvo, bool8 trackEnemyPersonality); +void HandleSpeciesGfxDataChange(u8 attacker, u8 target, bool8 castform, bool32 megaEvo, bool8 trackEnemyPersonality); void BattleLoadSubstituteOrMonSpriteGfx(u8 battlerId, bool8 loadMonSprite); void LoadBattleMonGfxAndAnimate(u8 battlerId, bool8 loadMonSprite, u8 spriteId); void TrySetBehindSubstituteSpriteBit(u8 battlerId, u16 move); diff --git a/include/config/battle.h b/include/config/battle.h index 4b3caf4abe..4861d046ca 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -99,6 +99,7 @@ // Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon. #define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain. #define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost. +#define B_TRANSFORM_SHINY GEN_LATEST // In Gen4+, Transform will copy the shiny state of the opponent instead of maintaining its own shiny state. #define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms. // Ability settings diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index ff5f044464..7d449c767e 100755 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -2350,6 +2350,8 @@ void AnimTask_TransformMon(u8 taskId) SetAnimBgAttribute(2, BG_ANIM_MOSAIC, 1); gTasks[taskId].data[10] = gBattleAnimArgs[0]; + gTasks[taskId].data[11] = gBattleAnimArgs[1]; + gTasks[taskId].data[12] = gBattleAnimArgs[2]; gTasks[taskId].data[0]++; break; case 1: @@ -2364,7 +2366,7 @@ void AnimTask_TransformMon(u8 taskId) } break; case 2: - HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10], gBattleAnimArgs[1], TRUE); + HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10], gTasks[taskId].data[11], gTasks[taskId].data[12]); GetBgDataForTransform(&animBg, gBattleAnimAttacker); if (IsContest()) diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 908363907b..b4936da5c2 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -1395,6 +1395,7 @@ static void LinkOpponentHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = LinkOpponentDoMoveAnimation; BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index 1ef5d63555..d07a92e93f 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -1232,6 +1232,7 @@ static void LinkPartnerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = LinkPartnerDoMoveAnimation; BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 4eda81b094..c3e4a90374 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1470,6 +1470,7 @@ static void OpponentHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = OpponentDoMoveAnimation; } diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 1065994164..b9eb566c02 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2709,6 +2709,7 @@ static void PlayerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = PlayerDoMoveAnimation; BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 4c54b68aa3..b94d5347aa 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -1433,6 +1433,7 @@ static void PlayerPartnerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = PlayerPartnerDoMoveAnimation; } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index e7fc6fd84a..ea98820547 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -1327,6 +1327,7 @@ static void RecordedOpponentHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = RecordedOpponentDoMoveAnimation; } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 87f5758399..8957b285ab 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -1335,6 +1335,7 @@ static void RecordedPlayerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = RecordedPlayerDoMoveAnimation; } diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index ae20c54ecf..fa1fa00fb2 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -1115,6 +1115,7 @@ static void WallyHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = WallyDoMoveAnimation; } diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index bc541f0a01..d926494a8d 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -551,7 +551,7 @@ bool8 IsBattleSEPlaying(u8 battlerId) static void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId, bool32 opponent) { - u32 monsPersonality, currentPersonality, otId, species, paletteOffset, position; + u32 monsPersonality, currentPersonality, otId, currentOtId, species, paletteOffset, position; const void *lzPaletteData; struct Pokemon *illusionMon = GetIllusionMonPtr(battlerId); if (illusionMon != NULL) @@ -561,18 +561,26 @@ static void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId, bool32 op return; monsPersonality = GetMonData(mon, MON_DATA_PERSONALITY); + otId = GetMonData(mon, MON_DATA_OT_ID); + if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE) { species = GetMonData(mon, MON_DATA_SPECIES); currentPersonality = monsPersonality; + currentOtId = otId; } else { species = gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies; - currentPersonality = gTransformedPersonalities[battlerId]; + #if B_TRANSFORM_SHINY >= GEN_4 + currentPersonality = gTransformedPersonalities[battlerId]; + currentOtId = gTransformedOtIds[battlerId]; + #else + currentPersonality = monsPersonality; + currentOtId = otId; + #endif } - otId = GetMonData(mon, MON_DATA_OT_ID); position = GetBattlerPosition(battlerId); if (opponent) { @@ -592,7 +600,7 @@ static void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId, bool32 op if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE) lzPaletteData = GetMonFrontSpritePal(mon); else - lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, otId, monsPersonality); + lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, currentOtId, currentPersonality); LZDecompressWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); @@ -880,10 +888,18 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 castform, bo if (GetBattlerSide(battlerAtk) == B_SIDE_PLAYER) { + #if B_TRANSFORM_SHINY >= GEN_4 if (trackEnemyPersonality) + { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); + otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + } else + #endif + { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); + otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + } otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); HandleLoadSpecialPokePic(FALSE, @@ -893,11 +909,19 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 castform, bo } else { + #if B_TRANSFORM_SHINY >= GEN_4 if (trackEnemyPersonality) + { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); + otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + + } else + #endif + { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + } HandleLoadSpecialPokePic(TRUE, gMonSpritesGfxPtr->sprites.ptr[position], diff --git a/src/battle_main.c b/src/battle_main.c index e59653f313..91d5c3aa50 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -226,6 +226,7 @@ EWRAM_DATA u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gBattlerInMenuId = 0; EWRAM_DATA bool8 gDoingBattleAnim = FALSE; EWRAM_DATA u32 gTransformedPersonalities[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA u32 gTransformedOtIds[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gPlayerDpadHoldFrames = 0; EWRAM_DATA struct BattleSpriteData *gBattleSpritesDataPtr = NULL; EWRAM_DATA struct MonSpritesGfx *gMonSpritesGfxPtr = NULL; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index aead0fe3c2..cdc8cfa904 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12881,6 +12881,7 @@ static void Cmd_transformdataexecution(void) gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disableTimer = 0; gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; + gDisableStructs[gBattlerAttacker].transformedMonOtId = gBattleMons[gBattlerTarget].otId; gDisableStructs[gBattlerAttacker].mimickedMoves = 0; gDisableStructs[gBattlerAttacker].usedMoves = 0; From 39b50d09dd9c18da8a0a81da355565338943c031 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Mon, 1 May 2023 11:19:10 +0200 Subject: [PATCH 130/131] Add missing CanGetFrostbite --- include/battle_util.h | 1 + src/battle_script_commands.c | 2 +- src/battle_util.c | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/battle_util.h b/include/battle_util.h index b83209a697..2644ca64a9 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -228,6 +228,7 @@ bool32 CanBePoisoned(u8 battlerAttacker, u8 battlerTarget); bool32 CanBeBurned(u8 battlerId); bool32 CanBeParalyzed(u8 battlerId); bool32 CanBeFrozen(u8 battlerId); +bool32 CanGetFrostbite(u8 battlerId); bool32 CanBeConfused(u8 battlerId); bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); u32 GetBattlerFriendshipScore(u8 battlerId); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index fecea28927..d81b3575dd 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3212,7 +3212,7 @@ void SetMoveEffect(bool32 primary, u32 certain) } break; case STATUS1_FROSTBITE: - if (!CanBeFrozen(gEffectBattler)) + if (!CanGetFrostbite(gEffectBattler)) break; statusChanged = TRUE; diff --git a/src/battle_util.c b/src/battle_util.c index 98b0b6744f..aa3c1ecac8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6507,6 +6507,20 @@ bool32 CanBeFrozen(u8 battlerId) return TRUE; } +bool32 CanGetFrostbite(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if (IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD + || ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE + || gBattleMons[battlerId].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battlerId) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + bool32 CanBeConfused(u8 battlerId) { if (GetBattlerAbility(battlerId) == ABILITY_OWN_TEMPO From dd96ac0c4ff3c45c6c29caab6d6e6e38b6971d8d Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Mon, 1 May 2023 15:35:05 +0200 Subject: [PATCH 131/131] Add Comatose check to AI "can be Xed" status checks --- src/battle_ai_util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 09815519af..f5cef9d903 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2766,6 +2766,7 @@ bool32 AI_CanSleep(u8 battler, u16 ability) { if (ability == ABILITY_INSOMNIA || ability == ABILITY_VITAL_SPIRIT + || ability == ABILITY_COMATOSE || gBattleMons[battler].status1 & STATUS1_ANY || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || (gFieldStatuses & (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN)) @@ -2839,6 +2840,7 @@ bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 static bool32 AI_CanBeParalyzed(u8 battler, u16 ability) { if (ability == ABILITY_LIMBER + || ability == ABILITY_COMATOSE || IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC) || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler)) @@ -2884,6 +2886,7 @@ bool32 AI_CanBeBurned(u8 battler, u16 ability) { if (ability == ABILITY_WATER_VEIL || ability == ABILITY_WATER_BUBBLE + || ability == ABILITY_COMATOSE || IS_BATTLER_OF_TYPE(battler, TYPE_FIRE) || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler) @@ -2895,6 +2898,7 @@ bool32 AI_CanBeBurned(u8 battler, u16 ability) bool32 AI_CanGetFrostbite(u8 battler, u16 ability) { if (ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler)