From e605ffba539fd54f2a5d105493c2943a6bdd91c1 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 4 Dec 2024 18:22:16 -0300 Subject: [PATCH 01/45] Fix recorded battle link player loops (#2071) --- src/recorded_battle.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 42866c723b..ebd2a5800f 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -35,13 +35,13 @@ struct RecordedBattleSave { struct Pokemon playerParty[PARTY_SIZE]; struct Pokemon opponentParty[PARTY_SIZE]; - u8 playersName[MAX_BATTLERS_COUNT][PLAYER_NAME_LENGTH + 1]; - u8 playersGender[MAX_BATTLERS_COUNT]; - u32 playersTrainerId[MAX_BATTLERS_COUNT]; - u8 playersLanguage[MAX_BATTLERS_COUNT]; + u8 playersName[MAX_LINK_PLAYERS][PLAYER_NAME_LENGTH + 1]; + u8 playersGender[MAX_LINK_PLAYERS]; + u32 playersTrainerId[MAX_LINK_PLAYERS]; + u8 playersLanguage[MAX_LINK_PLAYERS]; u32 rngSeed; u32 battleFlags; - u8 playersBattlers[MAX_BATTLERS_COUNT]; + u8 playersBattlers[MAX_LINK_PLAYERS]; u16 opponentA; u16 opponentB; u16 partnerId; @@ -85,7 +85,7 @@ EWRAM_DATA static u32 sAI_Scripts = 0; EWRAM_DATA static struct Pokemon sSavedPlayerParty[PARTY_SIZE] = {0}; EWRAM_DATA static struct Pokemon sSavedOpponentParty[PARTY_SIZE] = {0}; EWRAM_DATA static u16 sPlayerMonMoves[MAX_BATTLERS_COUNT / 2][MAX_MON_MOVES] = {0}; -EWRAM_DATA static struct PlayerInfo sPlayers[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA static struct PlayerInfo sPlayers[MAX_LINK_PLAYERS] = {0}; EWRAM_DATA static bool8 sIsPlaybackFinished = 0; EWRAM_DATA static u8 sRecordMixFriendName[PLAYER_NAME_LENGTH + 1] = {0}; EWRAM_DATA static u8 sRecordMixFriendClass = 0; @@ -148,7 +148,7 @@ void RecordedBattle_SetTrainerInfo(void) gRecordedBattleMultiplayerId = GetMultiplayerId(); linkPlayersCount = GetLinkPlayerCount(); - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { sPlayers[i].trainerId = gLinkPlayers[i].trainerId; sPlayers[i].gender = gLinkPlayers[i].gender; @@ -333,7 +333,7 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->opponentParty[i] = sSavedOpponentParty[i]; } - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { for (j = 0; j < PLAYER_NAME_LENGTH + 1; j++) battleSave->playersName[i][j] = sPlayers[i].name[j]; @@ -535,7 +535,7 @@ static void SetVariablesForRecordedBattle(struct RecordedBattleSave *src) gEnemyParty[i] = src->opponentParty[i]; } - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { for (var = FALSE, j = 0; j < PLAYER_NAME_LENGTH + 1; j++) { From 3f98c782973c912907ecc941aa98e519d15b27fc Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 4 Dec 2024 19:38:23 -0300 Subject: [PATCH 02/45] Added POKEMART_LIST_END to avoid users accidentally removing it (#1947) --- asm/macros/event.inc | 7 +++++++ data/maps/BattleFrontier_Mart/scripts.inc | 4 +--- .../EverGrandeCity_PokemonLeague_1F/scripts.inc | 4 +--- data/maps/FallarborTown_Mart/scripts.inc | 4 +--- data/maps/FortreeCity_DecorationShop/scripts.inc | 8 ++------ data/maps/FortreeCity_Mart/scripts.inc | 4 +--- data/maps/LavaridgeTown_HerbShop/scripts.inc | 4 +--- data/maps/LavaridgeTown_Mart/scripts.inc | 4 +--- .../LilycoveCity_DepartmentStore_2F/scripts.inc | 8 ++------ .../LilycoveCity_DepartmentStore_3F/scripts.inc | 8 ++------ .../LilycoveCity_DepartmentStore_4F/scripts.inc | 8 ++------ .../LilycoveCity_DepartmentStore_5F/scripts.inc | 16 ++++------------ data/maps/MauvilleCity_Mart/scripts.inc | 4 +--- data/maps/MossdeepCity_Mart/scripts.inc | 4 +--- data/maps/OldaleTown_Mart/scripts.inc | 8 ++------ data/maps/PetalburgCity_Mart/scripts.inc | 8 ++------ .../Route104_PrettyPetalFlowerShop/scripts.inc | 4 +--- data/maps/RustboroCity_Mart/scripts.inc | 8 ++------ data/maps/SlateportCity/scripts.inc | 16 ++++------------ data/maps/SlateportCity_Mart/scripts.inc | 4 +--- data/maps/SootopolisCity_Mart/scripts.inc | 4 +--- data/maps/TrainerHill_Entrance/scripts.inc | 8 ++------ data/maps/VerdanturfTown_Mart/scripts.inc | 4 +--- 23 files changed, 43 insertions(+), 108 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index b91ac68210..66aeb8482d 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1108,6 +1108,13 @@ .4byte \products .endm + @ Used as the endpoint for a Pokemart item list + .macro pokemartlistend + .2byte ITEM_NONE + release + end + .endm + @ Opens the Pokemart system and treats the list of items as decorations. @ Products should be a list of .2byte decoration values preceded by an .align 2 .macro pokemartdecoration products:req diff --git a/data/maps/BattleFrontier_Mart/scripts.inc b/data/maps/BattleFrontier_Mart/scripts.inc index 6afe6a0186..f118476cfe 100644 --- a/data/maps/BattleFrontier_Mart/scripts.inc +++ b/data/maps/BattleFrontier_Mart/scripts.inc @@ -28,9 +28,7 @@ BattleFrontier_Mart_Pokemart: .2byte ITEM_ZINC .2byte ITEM_CARBOS .2byte ITEM_HP_UP - .2byte ITEM_NONE - release - end + pokemartlistend BattleFrontier_Mart_EventScript_OldMan:: msgbox BattleFrontier_Mart_Text_ChaperonGrandson, MSGBOX_NPC diff --git a/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc b/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc index c13e716975..37e691fa3b 100644 --- a/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc +++ b/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc @@ -45,9 +45,7 @@ EverGrandeCity_PokemonLeague_1F_Pokemart: .2byte ITEM_FULL_HEAL .2byte ITEM_REVIVE .2byte ITEM_MAX_REPEL - .2byte ITEM_NONE - release - end + pokemartlistend @ The door guards only check for FLAG_BADGE06_GET because Winonas badge is the only one that can be skipped @ Its assumed the player has the remaining badges diff --git a/data/maps/FallarborTown_Mart/scripts.inc b/data/maps/FallarborTown_Mart/scripts.inc index cb92f28f52..0cdb11ee5e 100644 --- a/data/maps/FallarborTown_Mart/scripts.inc +++ b/data/maps/FallarborTown_Mart/scripts.inc @@ -25,9 +25,7 @@ FallarborTown_Mart_Pokemart: .2byte ITEM_X_DEFEND .2byte ITEM_DIRE_HIT .2byte ITEM_GUARD_SPEC - .2byte ITEM_NONE - release - end + pokemartlistend FallarborTown_Mart_EventScript_Woman:: msgbox FallarborTown_Mart_Text_DecidingSkittyEvolve, MSGBOX_NPC diff --git a/data/maps/FortreeCity_DecorationShop/scripts.inc b/data/maps/FortreeCity_DecorationShop/scripts.inc index 4394312876..4da66f27b9 100644 --- a/data/maps/FortreeCity_DecorationShop/scripts.inc +++ b/data/maps/FortreeCity_DecorationShop/scripts.inc @@ -29,9 +29,7 @@ FortreeCity_DecorationShop_PokemartDecor_Desks: .2byte DECOR_BRICK_DESK .2byte DECOR_CAMP_DESK .2byte DECOR_HARD_DESK - .2byte DECOR_NONE - release - end + pokemartlistend FortreeCity_DecorationShop_EventScript_ClerkChairs:: lock @@ -53,9 +51,7 @@ FortreeCity_DecorationShop_PokemartDecor_Chairs: .2byte DECOR_BRICK_CHAIR .2byte DECOR_CAMP_CHAIR .2byte DECOR_HARD_CHAIR - .2byte DECOR_NONE - release - end + pokemartlistend FortreeCity_DecorationShop_Text_MerchandiseSentToPC: .string "Merchandise you buy here is sent to\n" diff --git a/data/maps/FortreeCity_Mart/scripts.inc b/data/maps/FortreeCity_Mart/scripts.inc index c37716bc85..0986e68c0c 100644 --- a/data/maps/FortreeCity_Mart/scripts.inc +++ b/data/maps/FortreeCity_Mart/scripts.inc @@ -23,9 +23,7 @@ FortreeCity_Mart_Pokemart: .2byte ITEM_REVIVE .2byte ITEM_SUPER_REPEL .2byte ITEM_WOOD_MAIL - .2byte ITEM_NONE - release - end + pokemartlistend FortreeCity_Mart_EventScript_Woman:: msgbox FortreeCity_Mart_Text_SuperRepelBetter, MSGBOX_NPC diff --git a/data/maps/LavaridgeTown_HerbShop/scripts.inc b/data/maps/LavaridgeTown_HerbShop/scripts.inc index dbe1b564ac..22e3851e9d 100644 --- a/data/maps/LavaridgeTown_HerbShop/scripts.inc +++ b/data/maps/LavaridgeTown_HerbShop/scripts.inc @@ -17,9 +17,7 @@ LavaridgeTown_HerbShop_Pokemart: .2byte ITEM_ENERGY_ROOT .2byte ITEM_HEAL_POWDER .2byte ITEM_REVIVAL_HERB - .2byte ITEM_NONE - release - end + pokemartlistend LavaridgeTown_HerbShop_EventScript_ExpertM:: msgbox LavaridgeTown_HerbShop_Text_HerbalMedicineWorksButMonWillDislike, MSGBOX_NPC diff --git a/data/maps/LavaridgeTown_Mart/scripts.inc b/data/maps/LavaridgeTown_Mart/scripts.inc index 001df31401..8df5d02dfc 100644 --- a/data/maps/LavaridgeTown_Mart/scripts.inc +++ b/data/maps/LavaridgeTown_Mart/scripts.inc @@ -22,9 +22,7 @@ LavaridgeTown_Mart_Pokemart: .2byte ITEM_REVIVE .2byte ITEM_SUPER_REPEL .2byte ITEM_X_SPEED - .2byte ITEM_NONE - release - end + pokemartlistend LavaridgeTown_Mart_EventScript_ExpertM:: msgbox LavaridgeTown_Mart_Text_XSpeedFirstStrike, MSGBOX_NPC diff --git a/data/maps/LilycoveCity_DepartmentStore_2F/scripts.inc b/data/maps/LilycoveCity_DepartmentStore_2F/scripts.inc index 478f5cfd31..0a502a4f0e 100644 --- a/data/maps/LilycoveCity_DepartmentStore_2F/scripts.inc +++ b/data/maps/LilycoveCity_DepartmentStore_2F/scripts.inc @@ -36,9 +36,7 @@ LilycoveCity_DepartmentStore_2F_Pokemart1: .2byte ITEM_ICE_HEAL .2byte ITEM_AWAKENING .2byte ITEM_FLUFFY_TAIL - .2byte ITEM_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_2F_EventScript_ClerkRight:: lock @@ -62,9 +60,7 @@ LilycoveCity_DepartmentStore_2F_Pokemart2: .2byte ITEM_MAX_REPEL .2byte ITEM_WAVE_MAIL .2byte ITEM_MECH_MAIL - .2byte ITEM_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_2F_Text_LearnToUseItemsProperly: .string "Learn to use items properly.\n" diff --git a/data/maps/LilycoveCity_DepartmentStore_3F/scripts.inc b/data/maps/LilycoveCity_DepartmentStore_3F/scripts.inc index 20480068b8..bc42b293be 100644 --- a/data/maps/LilycoveCity_DepartmentStore_3F/scripts.inc +++ b/data/maps/LilycoveCity_DepartmentStore_3F/scripts.inc @@ -19,9 +19,7 @@ LilycoveCity_DepartmentStore_3F_Pokemart_Vitamins: .2byte ITEM_ZINC .2byte ITEM_CARBOS .2byte ITEM_HP_UP - .2byte ITEM_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_3F_EventScript_ClerkRight:: lock @@ -42,9 +40,7 @@ LilycoveCity_DepartmentStore_3F_Pokemart_StatBoosters: .2byte ITEM_DIRE_HIT .2byte ITEM_GUARD_SPEC .2byte ITEM_X_ACCURACY - .2byte ITEM_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_3F_EventScript_TriathleteM:: msgbox LilycoveCity_DepartmentStore_3F_Text_ItemsBestForTougheningPokemon, MSGBOX_NPC diff --git a/data/maps/LilycoveCity_DepartmentStore_4F/scripts.inc b/data/maps/LilycoveCity_DepartmentStore_4F/scripts.inc index 760abc600d..0d6403b206 100644 --- a/data/maps/LilycoveCity_DepartmentStore_4F/scripts.inc +++ b/data/maps/LilycoveCity_DepartmentStore_4F/scripts.inc @@ -29,9 +29,7 @@ LilycoveCity_DepartmentStore_4F_Pokemart_AttackTMs: .2byte ITEM_TM_THUNDER .2byte ITEM_TM_BLIZZARD .2byte ITEM_TM_HYPER_BEAM - .2byte ITEM_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_4F_EventScript_ClerkRight:: lock @@ -49,9 +47,7 @@ LilycoveCity_DepartmentStore_4F_Pokemart_DefenseTMs: .2byte ITEM_TM_SAFEGUARD .2byte ITEM_TM_REFLECT .2byte ITEM_TM_LIGHT_SCREEN - .2byte ITEM_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_4F_Text_AttackOrDefenseTM: .string "Hmm…\p" diff --git a/data/maps/LilycoveCity_DepartmentStore_5F/scripts.inc b/data/maps/LilycoveCity_DepartmentStore_5F/scripts.inc index a9683d13c9..f75a48e708 100644 --- a/data/maps/LilycoveCity_DepartmentStore_5F/scripts.inc +++ b/data/maps/LilycoveCity_DepartmentStore_5F/scripts.inc @@ -41,9 +41,7 @@ LilycoveCity_DepartmentStore_5F_Pokemart_Dolls: .2byte DECOR_SKITTY_DOLL .2byte DECOR_SWABLU_DOLL .2byte DECOR_GULPIN_DOLL - .2byte DECOR_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_5F_EventScript_ClerkMidLeft:: lock @@ -66,9 +64,7 @@ LilycoveCity_DepartmentStore_5F_Pokemart_Cushions: .2byte DECOR_GRASS_CUSHION .2byte DECOR_FIRE_CUSHION .2byte DECOR_WATER_CUSHION - .2byte DECOR_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_5F_EventScript_ClerkMidRight:: lock @@ -91,9 +87,7 @@ LilycoveCity_DepartmentStore_5F_Pokemart_Posters: .2byte DECOR_LONG_POSTER .2byte DECOR_SEA_POSTER .2byte DECOR_SKY_POSTER - .2byte DECOR_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_5F_EventScript_ClerkFarRight:: lock @@ -117,9 +111,7 @@ LilycoveCity_DepartmentStore_5F_Pokemart_Mats: .2byte DECOR_GLITTER_MAT .2byte DECOR_JUMP_MAT .2byte DECOR_SPIN_MAT - .2byte DECOR_NONE - release - end + pokemartlistend LilycoveCity_DepartmentStore_5F_EventScript_PokefanF:: msgbox LilycoveCity_DepartmentStore_5F_Text_PlaceFullOfCuteDolls, MSGBOX_NPC diff --git a/data/maps/MauvilleCity_Mart/scripts.inc b/data/maps/MauvilleCity_Mart/scripts.inc index 4cf5bc20bb..3a416b5907 100644 --- a/data/maps/MauvilleCity_Mart/scripts.inc +++ b/data/maps/MauvilleCity_Mart/scripts.inc @@ -25,9 +25,7 @@ MauvilleCity_Mart_Pokemart: .2byte ITEM_GUARD_SPEC .2byte ITEM_DIRE_HIT .2byte ITEM_X_ACCURACY - .2byte ITEM_NONE - release - end + pokemartlistend MauvilleCity_Mart_EventScript_ExpertM:: msgbox MauvilleCity_Mart_Text_ItemsToTemporarilyElevateStats, MSGBOX_NPC diff --git a/data/maps/MossdeepCity_Mart/scripts.inc b/data/maps/MossdeepCity_Mart/scripts.inc index 50edddd09a..b66fbe4209 100644 --- a/data/maps/MossdeepCity_Mart/scripts.inc +++ b/data/maps/MossdeepCity_Mart/scripts.inc @@ -22,9 +22,7 @@ MossdeepCity_Mart_Pokemart: .2byte ITEM_MAX_REPEL .2byte ITEM_X_ATTACK .2byte ITEM_X_DEFEND - .2byte ITEM_NONE - release - end + pokemartlistend MossdeepCity_Mart_EventScript_Woman:: msgbox MossdeepCity_Mart_Text_ReviveIsFantastic, MSGBOX_NPC diff --git a/data/maps/OldaleTown_Mart/scripts.inc b/data/maps/OldaleTown_Mart/scripts.inc index 0b3c7b1a34..1e1aacbb10 100644 --- a/data/maps/OldaleTown_Mart/scripts.inc +++ b/data/maps/OldaleTown_Mart/scripts.inc @@ -18,9 +18,7 @@ OldaleTown_Mart_Pokemart_Basic: .2byte ITEM_ANTIDOTE .2byte ITEM_PARALYZE_HEAL .2byte ITEM_AWAKENING - .2byte ITEM_NONE - release - end + pokemartlistend OldaleTown_Mart_ExpandedItems:: pokemart OldaleTown_Mart_Pokemart_Expanded @@ -35,9 +33,7 @@ OldaleTown_Mart_Pokemart_Expanded: .2byte ITEM_ANTIDOTE .2byte ITEM_PARALYZE_HEAL .2byte ITEM_AWAKENING - .2byte ITEM_NONE - release - end + pokemartlistend OldaleTown_Mart_EventScript_Woman:: lock diff --git a/data/maps/PetalburgCity_Mart/scripts.inc b/data/maps/PetalburgCity_Mart/scripts.inc index abaa7b5b0e..27393c51bf 100644 --- a/data/maps/PetalburgCity_Mart/scripts.inc +++ b/data/maps/PetalburgCity_Mart/scripts.inc @@ -25,9 +25,7 @@ PetalburgCity_Mart_Pokemart_Basic: .2byte ITEM_X_ATTACK .2byte ITEM_X_DEFEND .2byte ITEM_ORANGE_MAIL - .2byte ITEM_NONE - release - end + pokemartlistend PetalburgCity_Mart_EventScript_ExpandedItems:: pokemart PetalburgCity_Mart_Pokemart_Expanded @@ -50,9 +48,7 @@ PetalburgCity_Mart_Pokemart_Expanded: .2byte ITEM_X_ATTACK .2byte ITEM_X_DEFEND .2byte ITEM_ORANGE_MAIL - .2byte ITEM_NONE - release - end + pokemartlistend PetalburgCity_Mart_EventScript_Woman:: msgbox PetalburgCity_Mart_Text_WeakWillGrowStronger, MSGBOX_NPC diff --git a/data/maps/Route104_PrettyPetalFlowerShop/scripts.inc b/data/maps/Route104_PrettyPetalFlowerShop/scripts.inc index 5f0ec28fa5..e239ea658b 100644 --- a/data/maps/Route104_PrettyPetalFlowerShop/scripts.inc +++ b/data/maps/Route104_PrettyPetalFlowerShop/scripts.inc @@ -59,9 +59,7 @@ Route104_PrettyPetalFlowerShop_Pokemart_Plants: .2byte DECOR_COLORFUL_PLANT .2byte DECOR_BIG_PLANT .2byte DECOR_GORGEOUS_PLANT - .2byte DECOR_NONE - release - end + pokemartlistend Route104_PrettyPetalFlowerShop_EventScript_WailmerPailGirl:: lock diff --git a/data/maps/RustboroCity_Mart/scripts.inc b/data/maps/RustboroCity_Mart/scripts.inc index 18120cb4de..5d6a7fe5f7 100644 --- a/data/maps/RustboroCity_Mart/scripts.inc +++ b/data/maps/RustboroCity_Mart/scripts.inc @@ -28,9 +28,7 @@ RustboroCity_Mart_Pokemart_Basic: .2byte ITEM_X_SPEED .2byte ITEM_X_ATTACK .2byte ITEM_X_DEFEND - .2byte ITEM_NONE - release - end + pokemartlistend RustboroCity_Mart_EventScript_PokemartExpanded:: pokemart RustboroCity_Mart_Pokemart_Expanded @@ -52,9 +50,7 @@ RustboroCity_Mart_Pokemart_Expanded: .2byte ITEM_X_SPEED .2byte ITEM_X_ATTACK .2byte ITEM_X_DEFEND - .2byte ITEM_NONE - release - end + pokemartlistend RustboroCity_Mart_EventScript_PokefanF:: msgbox RustboroCity_Mart_Text_BuyingHealsInCaseOfShroomish, MSGBOX_NPC diff --git a/data/maps/SlateportCity/scripts.inc b/data/maps/SlateportCity/scripts.inc index ae3910750e..5438a7f364 100644 --- a/data/maps/SlateportCity/scripts.inc +++ b/data/maps/SlateportCity/scripts.inc @@ -154,9 +154,7 @@ SlateportCity_Pokemart_EnergyGuru: .2byte ITEM_ZINC .2byte ITEM_CALCIUM .2byte ITEM_HP_UP - .2byte ITEM_NONE - release - end + pokemartlistend SlateportCity_EventScript_EffortRibbonWoman:: lock @@ -514,9 +512,7 @@ SlateportCity_PokemartDecor_Dolls: .2byte DECOR_AZURILL_DOLL .2byte DECOR_MARILL_DOLL .2byte DECOR_SKITTY_DOLL - .2byte DECOR_NONE - release - end + pokemartlistend SlateportCity_EventScript_ComeBackWithSecretPower:: msgbox gText_ComeBackWithSecretPower, MSGBOX_DEFAULT @@ -550,9 +546,7 @@ SlateportCity_PokemartDecor: .2byte DECOR_A_NOTE_MAT .2byte DECOR_B_NOTE_MAT .2byte DECOR_C_HIGH_NOTE_MAT - .2byte DECOR_NONE - release - end + pokemartlistend SlateportCity_EventScript_PowerTMClerk:: lock @@ -568,9 +562,7 @@ SlateportCity_EventScript_PowerTMClerk:: SlateportCity_Pokemart_PowerTMs: .2byte ITEM_TM_HIDDEN_POWER .2byte ITEM_TM_SECRET_POWER - .2byte ITEM_NONE - release - end + pokemartlistend @ Scene with Capt Sterns interview and Team Aqua announcing plans to steal Submarine SlateportCity_EventScript_CaptStern:: diff --git a/data/maps/SlateportCity_Mart/scripts.inc b/data/maps/SlateportCity_Mart/scripts.inc index a0c0a8612e..ce7dd45b86 100644 --- a/data/maps/SlateportCity_Mart/scripts.inc +++ b/data/maps/SlateportCity_Mart/scripts.inc @@ -22,9 +22,7 @@ SlateportCity_Mart_Pokemart: .2byte ITEM_ESCAPE_ROPE .2byte ITEM_REPEL .2byte ITEM_HARBOR_MAIL - .2byte ITEM_NONE - release - end + pokemartlistend SlateportCity_Mart_EventScript_BlackBelt:: msgbox SlateportCity_Mart_Text_SomeItemsOnlyAtMart, MSGBOX_NPC diff --git a/data/maps/SootopolisCity_Mart/scripts.inc b/data/maps/SootopolisCity_Mart/scripts.inc index 3cade5fbc4..5539eb8be1 100644 --- a/data/maps/SootopolisCity_Mart/scripts.inc +++ b/data/maps/SootopolisCity_Mart/scripts.inc @@ -22,9 +22,7 @@ SootopolisCity_Mart_Pokemart: .2byte ITEM_X_ATTACK .2byte ITEM_X_DEFEND .2byte ITEM_SHADOW_MAIL - .2byte ITEM_NONE - release - end + pokemartlistend SootopolisCity_Mart_EventScript_FatMan:: lock diff --git a/data/maps/TrainerHill_Entrance/scripts.inc b/data/maps/TrainerHill_Entrance/scripts.inc index 2dd001a3ba..83a12e1c97 100644 --- a/data/maps/TrainerHill_Entrance/scripts.inc +++ b/data/maps/TrainerHill_Entrance/scripts.inc @@ -265,9 +265,7 @@ TrainerHill_Entrance_Pokemart_Basic: .2byte ITEM_DIRE_HIT .2byte ITEM_GUARD_SPEC .2byte ITEM_X_ACCURACY - .2byte ITEM_NONE - release - end + pokemartlistend TrainerHill_Entrance_EventScript_ExpandedPokemart:: pokemart TrainerHill_Entrance_Pokemart_Expanded @@ -289,9 +287,7 @@ TrainerHill_Entrance_Pokemart_Expanded: .2byte ITEM_DIRE_HIT .2byte ITEM_GUARD_SPEC .2byte ITEM_X_ACCURACY - .2byte ITEM_NONE - release - end + pokemartlistend TrainerHill_Entrance_Text_StillGettingReady: .string "This is the TRAINER HILL where\n" diff --git a/data/maps/VerdanturfTown_Mart/scripts.inc b/data/maps/VerdanturfTown_Mart/scripts.inc index 7eb340df2a..e67ccd0e60 100644 --- a/data/maps/VerdanturfTown_Mart/scripts.inc +++ b/data/maps/VerdanturfTown_Mart/scripts.inc @@ -24,9 +24,7 @@ VerdanturfTown_Mart_Pokemart: .2byte ITEM_REPEL .2byte ITEM_X_SPECIAL .2byte ITEM_FLUFFY_TAIL - .2byte ITEM_NONE - release - end + pokemartlistend VerdanturfTown_Mart_EventScript_Boy:: msgbox VerdanturfTown_Mart_Text_XSpecialIsCrucial, MSGBOX_NPC From 5483e05db65f2085fe8c4969eb3f1f9dcec3e1a0 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 5 Dec 2024 12:46:50 -0300 Subject: [PATCH 03/45] Fixed brace style inconsistencies --- src/AgbRfu_LinkManager.c | 2 ++ src/battle_anim_effects_1.c | 2 ++ src/battle_anim_effects_2.c | 4 +++ src/battle_anim_electric.c | 6 ++++ src/battle_anim_ghost.c | 2 ++ src/battle_anim_throw.c | 14 +++++++++ src/battle_controller_opponent.c | 12 ++++++-- src/battle_gfx_sfx_util.c | 8 +++++ src/battle_main.c | 34 ++++++++++++++++++++ src/battle_message.c | 6 ++++ src/battle_script_commands.c | 41 +++++++++++++++++++++---- src/battle_util.c | 10 ++++++ src/berry.c | 4 +++ src/berry_crush.c | 2 ++ src/bike.c | 2 ++ src/contest.c | 2 ++ src/contest_effect.c | 15 +++++++-- src/decompress.c | 12 ++++++++ src/evolution_graphics.c | 32 +++++++++++++++++++ src/field_camera.c | 2 ++ src/field_door.c | 2 ++ src/field_effect.c | 15 ++++++--- src/item_use.c | 12 ++++++++ src/librfu_sio32id.c | 2 ++ src/link_rfu_2.c | 11 +++++-- src/lottery_corner.c | 4 +++ src/mauville_old_man.c | 6 ++++ src/mini_printf.c | 18 ++++++----- src/party_menu.c | 2 ++ src/player_pc.c | 2 ++ src/pokedex.c | 6 ++++ src/pokemon.c | 15 ++++++++- src/pokenav_conditions_search_results.c | 10 ++++++ src/pokenav_menu_handler_gfx.c | 2 ++ src/slot_machine.c | 2 ++ src/sprite.c | 4 +++ src/tv.c | 3 +- 37 files changed, 301 insertions(+), 27 deletions(-) diff --git a/src/AgbRfu_LinkManager.c b/src/AgbRfu_LinkManager.c index d696c01d3c..b53b69c48b 100644 --- a/src/AgbRfu_LinkManager.c +++ b/src/AgbRfu_LinkManager.c @@ -59,7 +59,9 @@ void rfu_LMAN_REQ_sendData(bool8 clockChangeFlag) clockChangeFlag = FALSE; } else + { lman.parentAck_flag = 0; + } rfu_REQ_sendData(clockChangeFlag); } diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 3a558969b5..ee532f4134 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -4043,7 +4043,9 @@ static void AnimMilkBottle_Step1(struct Sprite *sprite) sprite->data[6]++; } else if (sprite->data[7] > 0) + { sprite->data[7]--; + } SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[6], sprite->data[7])); if (sprite->data[6] == 16 && sprite->data[7] == 0) diff --git a/src/battle_anim_effects_2.c b/src/battle_anim_effects_2.c index 3d2e72cacb..bf7e774f6b 100644 --- a/src/battle_anim_effects_2.c +++ b/src/battle_anim_effects_2.c @@ -2209,7 +2209,9 @@ static void AnimTask_Splash_Step(u8 taskId) task->data[4] -= 2; } else + { task->data[1]++; + } break; case 3: if (!RunAffineAnimFromTaskData(task)) @@ -2956,7 +2958,9 @@ static void AnimTask_SpeedDust_Step(u8 taskId) task->data[8] = 1; } else + { task->data[8] = 2; + } } } break; diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c index b6a82b8d9a..cc36e608f8 100644 --- a/src/battle_anim_electric.c +++ b/src/battle_anim_electric.c @@ -597,7 +597,9 @@ static void AnimZapCannonSpark_Step(struct Sprite *sprite) sprite->invisible ^= 1; } else + { DestroyAnimSprite(sprite); + } } static void AnimThunderboltOrb_Step(struct Sprite *sprite) @@ -870,7 +872,9 @@ static void AnimTask_ElectricChargingParticles_Step(u8 taskId) } } else if(task->data[7] == 0) + { DestroyAnimVisualTask(taskId); + } } static void AnimElectricChargingParticles_Step(struct Sprite *sprite) @@ -991,7 +995,9 @@ void AnimTask_VoltTackleAttackerReappear(u8 taskId) gSprites[task->data[15]].x2 = task->data[14]; } else + { task->data[0]++; + } } break; diff --git a/src/battle_anim_ghost.c b/src/battle_anim_ghost.c index d6afd4c304..6cb7da5c20 100644 --- a/src/battle_anim_ghost.c +++ b/src/battle_anim_ghost.c @@ -280,7 +280,9 @@ static void AnimConfuseRayBallBounce_Step2(struct Sprite *sprite) sprite->callback = DestroyAnimSpriteAndDisableBlend; } else + { UpdateConfuseRayBallBlend(sprite); + } } static void UpdateConfuseRayBallBlend(struct Sprite *sprite) diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index 951794fc54..956020b305 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -1147,7 +1147,9 @@ static void SpriteCB_Ball_Wobble_Step(struct Sprite *sprite) gBattleSpritesDataPtr->animationData->ballSubpx &= 0xFF; } else + { gBattleSpritesDataPtr->animationData->ballSubpx += 176; + } sprite->sTimer++; sprite->affineAnimPaused = FALSE; @@ -1172,7 +1174,9 @@ static void SpriteCB_Ball_Wobble_Step(struct Sprite *sprite) ChangeSpriteAffineAnim(sprite, BALL_ROTATE_RIGHT); } else + { sprite->affineAnimPaused = TRUE; + } break; case BALL_ROLL_2: if (gBattleSpritesDataPtr->animationData->ballSubpx > 255) @@ -1181,7 +1185,9 @@ static void SpriteCB_Ball_Wobble_Step(struct Sprite *sprite) gBattleSpritesDataPtr->animationData->ballSubpx &= 0xFF; } else + { gBattleSpritesDataPtr->animationData->ballSubpx += 176; + } sprite->sTimer++; sprite->affineAnimPaused = FALSE; @@ -1216,7 +1222,9 @@ static void SpriteCB_Ball_Wobble_Step(struct Sprite *sprite) gBattleSpritesDataPtr->animationData->ballSubpx &= 0xFF; } else + { gBattleSpritesDataPtr->animationData->ballSubpx += 176; + } sprite->sTimer++; sprite->affineAnimPaused = FALSE; @@ -1390,7 +1398,9 @@ static void SpriteCB_Ball_FadeOut(struct Sprite *sprite) static void DestroySpriteAfterOneFrame(struct Sprite *sprite) { if (sprite->sFrame == 0) + { sprite->sFrame = -1; + } else { FreeSpriteOamMatrix(sprite); @@ -1410,7 +1420,9 @@ static void MakeCaptureStars(struct Sprite *sprite) u8 subpriority; if (sprite->subpriority) + { subpriority = sprite->subpriority - 1; + } else { subpriority = 0; @@ -2358,7 +2370,9 @@ static void SpriteCB_ShinyStars_Diagonal(struct Sprite *sprite) { // Delayed four frames to de-sync from encircling stars if (sprite->sTimer < 4) + { sprite->sTimer++; + } else { sprite->invisible = FALSE; diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index dc3652b457..c01dcb442f 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -257,7 +257,9 @@ static void Intro_WaitForShinyAnimAndHealthbox(void) FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); } else + { return; + } } else if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].finishedShinyMonAnim) { @@ -270,13 +272,17 @@ static void Intro_WaitForShinyAnimAndHealthbox(void) FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); } else + { return; + } } - gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].triedShinyMonAnim = FALSE; - gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].finishedShinyMonAnim = FALSE; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].triedShinyMonAnim = FALSE; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].finishedShinyMonAnim = FALSE; } else + { return; + } gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].introEndDelay = 3; gBattlerControllerFuncs[gActiveBattler] = Intro_DelayAndEnd; @@ -331,7 +337,9 @@ static void Intro_TryShinyAnimShowHealthbox(void) m4aMPlayContinue(&gMPlayInfo_BGM); } else + { m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + } } gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].bgmRestored = TRUE; bgmRestored = TRUE; diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index ed8cf572ea..2deced13c0 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -773,13 +773,21 @@ bool8 BattleLoadAllHealthBoxesGfx(u8 state) LoadCompressedSpriteSheet(&sSpriteSheet_SinglesPlayerHealthbox); } else if (state == 3) + { LoadCompressedSpriteSheet(&sSpriteSheet_SinglesOpponentHealthbox); + } else if (state == 4) + { LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[0]]); + } else if (state == 5) + { LoadCompressedSpriteSheet(&sSpriteSheets_HealthBar[gBattlerPositions[1]]); + } else + { retVal = TRUE; + } } else { diff --git a/src/battle_main.c b/src/battle_main.c index 7ee8d8cf55..25b1cfa844 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -1654,7 +1654,9 @@ static void CB2_HandleStartMultiBattle(void) gBattleCommunication[MULTIUSE_STATE]++; } else + { break; + } // fall through case 3: if (IsLinkTaskFinished()) @@ -3084,7 +3086,9 @@ static void BattleStartClearSetData(void) gHitMarker |= HITMARKER_NO_ANIMATIONS; } else if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) && GetBattleSceneInRecordedBattle()) + { gHitMarker |= HITMARKER_NO_ANIMATIONS; + } gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle; @@ -3584,7 +3588,9 @@ static void BattleIntroPrintOpponentSendsOut(void) return; if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + { position = B_POSITION_OPPONENT_LEFT; + } else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER) @@ -3593,7 +3599,9 @@ static void BattleIntroPrintOpponentSendsOut(void) position = B_POSITION_PLAYER_LEFT; } else + { position = B_POSITION_OPPONENT_LEFT; + } PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(position)); gBattleMainFunc = BattleIntroOpponent1SendsOutMonAnimation; @@ -3604,7 +3612,9 @@ static void BattleIntroOpponent2SendsOutMonAnimation(void) u32 position; if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + { position = B_POSITION_OPPONENT_RIGHT; + } else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER) @@ -3613,7 +3623,9 @@ static void BattleIntroOpponent2SendsOutMonAnimation(void) position = B_POSITION_PLAYER_RIGHT; } else + { position = B_POSITION_OPPONENT_RIGHT; + } for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) { @@ -3641,10 +3653,14 @@ static void BattleIntroOpponent1SendsOutMonAnimation(void) position = B_POSITION_PLAYER_LEFT; } else + { position = B_POSITION_OPPONENT_LEFT; + } } else + { position = B_POSITION_OPPONENT_LEFT; + } if (gBattleControllerExecFlags) return; @@ -3699,7 +3715,9 @@ static void BattleIntroPrintPlayerSendsOut(void) u8 position; if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + { position = B_POSITION_PLAYER_LEFT; + } else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER) @@ -3708,7 +3726,9 @@ static void BattleIntroPrintPlayerSendsOut(void) position = B_POSITION_OPPONENT_LEFT; } else + { position = B_POSITION_PLAYER_LEFT; + } if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(position)); @@ -3722,7 +3742,9 @@ static void BattleIntroPlayer2SendsOutMonAnimation(void) u32 position; if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + { position = B_POSITION_PLAYER_RIGHT; + } else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER) @@ -3731,7 +3753,9 @@ static void BattleIntroPlayer2SendsOutMonAnimation(void) position = B_POSITION_OPPONENT_RIGHT; } else + { position = B_POSITION_PLAYER_RIGHT; + } for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) { @@ -3754,7 +3778,9 @@ static void BattleIntroPlayer1SendsOutMonAnimation(void) u32 position; if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) + { position = B_POSITION_PLAYER_LEFT; + } else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER) @@ -3763,7 +3789,9 @@ static void BattleIntroPlayer1SendsOutMonAnimation(void) position = B_POSITION_OPPONENT_LEFT; } else + { position = B_POSITION_PLAYER_LEFT; + } if (gBattleControllerExecFlags) return; @@ -4678,7 +4706,9 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves) moveBattler1 = gBattleMons[battler1].moves[*(gBattleStruct->chosenMovePositions + battler1)]; } else + { moveBattler1 = MOVE_NONE; + } if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE) { @@ -4688,7 +4718,9 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves) moveBattler2 = gBattleMons[battler2].moves[*(gBattleStruct->chosenMovePositions + battler2)]; } else + { moveBattler2 = MOVE_NONE; + } } // both move priorities are different than 0 @@ -4705,7 +4737,9 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves) // else battler1 has more speed } else if (gBattleMoves[moveBattler1].priority < gBattleMoves[moveBattler2].priority) + { strikesFirst = 1; // battler2's move has greater priority + } // else battler1's move has greater priority } diff --git a/src/battle_message.c b/src/battle_message.c index e50fcff3de..d539bc540d 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2350,7 +2350,9 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = gStringVar2; } else + { toCpy = gBattleTextBuff2; + } break; case B_TXT_BUFF3: if (gBattleTextBuff3[0] == B_BUFF_PLACEHOLDER_BEGIN) @@ -2359,7 +2361,9 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = gStringVar3; } else + { toCpy = gBattleTextBuff3; + } break; case B_TXT_COPY_VAR_1: toCpy = gStringVar1; @@ -2486,7 +2490,9 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = text; } else + { toCpy = sText_EnigmaBerry; + } } } else diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6f43c6af70..1891ea9285 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1769,7 +1769,9 @@ static void Cmd_attackanimation(void) gActiveBattler = gBattlerAttacker; if (gBattleMons[gBattlerTarget].status2 & STATUS2_SUBSTITUTE) + { multihit = gMultiHitCounter; + } else if (gMultiHitCounter != 0 && gMultiHitCounter != 1) { if (gBattleMons[gBattlerTarget].hp <= gBattleMoveDamage) @@ -1778,7 +1780,9 @@ static void Cmd_attackanimation(void) multihit = gMultiHitCounter; } else + { multihit = gMultiHitCounter; + } BtlController_EmitMoveAnimation(BUFFER_A, gCurrentMove, gBattleScripting.animTurn, gBattleMovePower, gBattleMoveDamage, gBattleMons[gBattlerAttacker].friendship, &gDisableStructs[gBattlerAttacker], multihit); gBattleScripting.animTurn++; @@ -2276,7 +2280,9 @@ void SetMoveEffect(bool8 primary, u8 certain) {} } else + { gActiveBattler = gBattlersCount; + } if (gBattleMons[gEffectBattler].status1) break; @@ -2409,7 +2415,9 @@ void SetMoveEffect(bool8 primary, u8 certain) RESET_RETURN } else + { break; + } } if (gBattleMons[gEffectBattler].status1) break; @@ -3111,7 +3119,9 @@ static void Cmd_jumpifability(void) gBattleScripting.battlerWithAbility = battlerId - 1; } else + { gBattlescriptCurrInstr += 7; + } } else if (gBattlescriptCurrInstr[1] == BS_NOT_ATTACKER_SIDE) { @@ -3124,7 +3134,9 @@ static void Cmd_jumpifability(void) gBattleScripting.battlerWithAbility = battlerId - 1; } else + { gBattlescriptCurrInstr += 7; + } } else { @@ -3137,7 +3149,9 @@ static void Cmd_jumpifability(void) gBattleScripting.battlerWithAbility = battlerId; } else + { gBattlescriptCurrInstr += 7; + } } } @@ -3387,13 +3401,10 @@ static void Cmd_getexp(void) { if (gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId && !(gAbsentBattlerFlags & gBitTable[2])) gBattleStruct->expGetterBattlerId = 2; + else if (!(gAbsentBattlerFlags & gBitTable[0])) + gBattleStruct->expGetterBattlerId = 0; else - { - if (!(gAbsentBattlerFlags & gBitTable[0])) - gBattleStruct->expGetterBattlerId = 0; - else - gBattleStruct->expGetterBattlerId = 2; - } + gBattleStruct->expGetterBattlerId = 2; } else { @@ -8558,11 +8569,17 @@ static void Cmd_presentdamagecalculation(void) s32 rand = Random() & 0xFF; if (rand < 102) + { gDynamicBasePower = 40; + } else if (rand < 178) + { gDynamicBasePower = 80; + } else if (rand < 204) + { gDynamicBasePower = 120; + } else { gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 4; @@ -8570,10 +8587,15 @@ static void Cmd_presentdamagecalculation(void) gBattleMoveDamage = 1; gBattleMoveDamage *= -1; } + if (rand < 204) + { gBattlescriptCurrInstr = BattleScript_HitFromCritCalc; + } else if (gBattleMons[gBattlerTarget].maxHP == gBattleMons[gBattlerTarget].hp) + { gBattlescriptCurrInstr = BattleScript_AlreadyAtFullHp; + } else { gMoveResultFlags &= ~MOVE_RESULT_DOESNT_AFFECT_FOE; @@ -8910,6 +8932,7 @@ static void Cmd_trydobeatup(void) && !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS)) break; } + if (gBattleCommunication[0] < PARTY_SIZE) { PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattleCommunication[0]) @@ -8927,9 +8950,13 @@ static void Cmd_trydobeatup(void) gBattleCommunication[0]++; } else if (beforeLoop != 0) + { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); + } else + { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 5); + } } } @@ -9907,7 +9934,9 @@ static void Cmd_handleballthrow(void) } } else + { ballMultiplier = sBallCatchBonuses[gLastUsedItem - ITEM_ULTRA_BALL]; + } odds = (catchRate * ballMultiplier / 10) * (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2) diff --git a/src/battle_util.c b/src/battle_util.c index d79c61b382..6e201a2956 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1336,9 +1336,13 @@ u8 DoFieldEndTurnEffects(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_STOPPED; } else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) + { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOWNPOUR_CONTINUES; + } else + { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_CONTINUES; + } } else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) { @@ -3824,7 +3828,9 @@ u8 GetMoveTarget(u16 move, u8 setTarget) case MOVE_TARGET_SELECTED: side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp) + { targetBattler = gSideTimers[side].followmeTarget; + } else { side = GetBattlerSide(gBattlerAttacker); @@ -3853,7 +3859,9 @@ u8 GetMoveTarget(u16 move, u8 setTarget) case MOVE_TARGET_RANDOM: side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp) + { targetBattler = gSideTimers[side].followmeTarget; + } else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) @@ -3874,7 +3882,9 @@ u8 GetMoveTarget(u16 move, u8 setTarget) targetBattler ^= BIT_FLANK; } else + { targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GET_BATTLER_SIDE(gBattlerAttacker))); + } break; case MOVE_TARGET_USER_OR_SELECTED: case MOVE_TARGET_USER: diff --git a/src/berry.c b/src/berry.c index 389a09a106..543041e526 100644 --- a/src/berry.c +++ b/src/berry.c @@ -980,7 +980,9 @@ bool32 IsEnigmaBerryValid(void) const struct Berry *GetBerryInfo(u8 berry) { if (berry == ITEM_TO_BERRY(ITEM_ENIGMA_BERRY) && IsEnigmaBerryValid()) + { return (struct Berry *)(&gSaveBlock1Ptr->enigmaBerry.berry); + } else { if (berry == BERRY_NONE || berry > ITEM_TO_BERRY(LAST_BERRY_INDEX)) @@ -1219,7 +1221,9 @@ static u8 CalcBerryYieldInternal(u16 max, u16 min, u8 water) u32 extraYield; if (water == 0) + { return min; + } else { randMin = (max - min) * (water - 1); diff --git a/src/berry_crush.c b/src/berry_crush.c index 05e708162d..c7bff2abcd 100644 --- a/src/berry_crush.c +++ b/src/berry_crush.c @@ -3398,7 +3398,9 @@ static u32 Cmd_StopGame(struct BerryCrushGame *game, u8 *args) break; case 2: if (game->gfx.counter != 0) + { game->gfx.counter--; + } else { RunOrScheduleCommand(CMD_CLOSE_LINK, SCHEDULE_CMD, NULL); diff --git a/src/bike.c b/src/bike.c index ae9dfd3e91..d8a3d1ab52 100644 --- a/src/bike.c +++ b/src/bike.c @@ -372,7 +372,9 @@ static u8 AcroBikeHandleInputWheelieStanding(u8 *newDirection, u16 newKeys, u16 gPlayerAvatar.runningState = NOT_MOVING; if (heldKeys & B_BUTTON) + { gPlayerAvatar.bikeFrameCounter++; + } else { // B button was released. diff --git a/src/contest.c b/src/contest.c index 40a42a3529..0615f7b504 100644 --- a/src/contest.c +++ b/src/contest.c @@ -2667,7 +2667,9 @@ static void Task_EndAppeals(u8 taskId) CalculateFinalScores(); ContestClearGeneralTextWindow(); if (!(gLinkContestFlags & LINK_CONTEST_FLAG_IS_LINK)) + { BravoTrainerPokemonProfile_BeforeInterview1(eContestantStatus[gContestPlayerMonIndex].prevMove); + } else { CalculateContestLiveUpdateData(); diff --git a/src/contest_effect.c b/src/contest_effect.c index 24de8e1692..92cc5a169c 100644 --- a/src/contest_effect.c +++ b/src/contest_effect.c @@ -619,15 +619,18 @@ static void ContestEffect_QualityDependsOnTiming(void) { appeal = 10; SetContestantEffectStringID(eContestAppealResults.contestant, CONTEST_STRING_APPEAL_NOT_VERY_WELL); - } else if (rval < 6) + } + else if (rval < 6) { appeal = 20; SetContestantEffectStringID(eContestAppealResults.contestant, CONTEST_STRING_APPEAL_SLIGHTLY_WELL2); - } else if (rval < 8) + } + else if (rval < 8) { appeal = 40; SetContestantEffectStringID(eContestAppealResults.contestant, CONTEST_STRING_APPEAL_PRETTY_WELL2); - } else if (rval < 9) + } + else if (rval < 9) { appeal = 60; SetContestantEffectStringID(eContestAppealResults.contestant, CONTEST_STRING_APPEAL_VERY_WELL); @@ -868,7 +871,9 @@ static void ContestEffect_ScrambleNextTurnOrder(void) break; } else + { rval--; + } } } } @@ -908,7 +913,9 @@ static void ContestEffect_BadlyStartleMonsWithGoodAppeals(void) eContestAppealResults.jam = RoundUp(eContestAppealResults.jam); } else + { eContestAppealResults.jam = 10; + } eContestAppealResults.jamQueue[0] = i; eContestAppealResults.jamQueue[1] = CONTESTANT_NONE; if (WasAtLeastOneOpponentJammed()) @@ -1071,7 +1078,9 @@ static s16 RoundTowardsZero(s16 score) score -= 10 - absScore; } else + { score -= absScore; + } return score; } diff --git a/src/decompress.c b/src/decompress.c index 55807e89bb..491ae8587f 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -100,9 +100,13 @@ void LoadSpecialPokePic(const struct CompressedSpriteSheet *src, void *dest, s32 LZ77UnCompWram(gMonFrontPicTable[i].data, dest); } else if (species > NUM_SPECIES) // is species unknown? draw the ? icon + { LZ77UnCompWram(gMonFrontPicTable[0].data, dest); + } else + { LZ77UnCompWram(src->data, dest); + } DuplicateDeoxysTiles(dest, species); DrawSpindaSpots(species, personality, dest, isFrontPic); @@ -327,9 +331,13 @@ void LoadSpecialPokePic_2(const struct CompressedSpriteSheet *src, void *dest, s LZ77UnCompWram(gMonFrontPicTable[i].data, dest); } else if (species > NUM_SPECIES) // is species unknown? draw the ? icon + { LZ77UnCompWram(gMonFrontPicTable[0].data, dest); + } else + { LZ77UnCompWram(src->data, dest); + } DuplicateDeoxysTiles(dest, species); DrawSpindaSpots(species, personality, dest, isFrontPic); @@ -385,9 +393,13 @@ void LoadSpecialPokePic_DontHandleDeoxys(const struct CompressedSpriteSheet *src LZ77UnCompWram(gMonFrontPicTable[i].data, dest); } else if (species > NUM_SPECIES) // is species unknown? draw the ? icon + { LZ77UnCompWram(gMonFrontPicTable[0].data, dest); + } else + { LZ77UnCompWram(src->data, dest); + } DrawSpindaSpots(species, personality, dest, isFrontPic); } diff --git a/src/evolution_graphics.c b/src/evolution_graphics.c index 96ff1b52df..1568c18d5f 100644 --- a/src/evolution_graphics.c +++ b/src/evolution_graphics.c @@ -150,7 +150,9 @@ static void SpriteCB_Sparkle_SpiralUpward(struct Sprite *sprite) sprite->oam.matrixNum = matrixNum; } else + { DestroySprite(sprite); + } } static void CreateSparkle_SpiralUpward(u8 trigIdx) @@ -178,7 +180,9 @@ static void SpriteCB_Sparkle_ArcDown(struct Sprite *sprite) sprite->sTimer++; } else + { DestroySprite(sprite); + } } static void CreateSparkle_ArcDown(u8 trigIdx) @@ -206,7 +210,9 @@ static void SpriteCB_Sparkle_CircleInward(struct Sprite *sprite) sprite->sTrigIdx += 4; } else + { DestroySprite(sprite); + } } static void CreateSparkle_CircleInward(u8 trigIdx, u8 speed) @@ -238,7 +244,9 @@ static void SpriteCB_Sparkle_Spray(struct Sprite *sprite) sprite->sTrigIdx++; matrixNum = 31 - (sprite->sTrigIdx * 12 / 128); if (sprite->sTrigIdx > 64) + { sprite->subpriority = 1; + } else { sprite->invisible = FALSE; @@ -252,7 +260,9 @@ static void SpriteCB_Sparkle_Spray(struct Sprite *sprite) sprite->sTimer++; } else + { DestroySprite(sprite); + } } static void CreateSparkle_Spray(u8 id) @@ -348,7 +358,9 @@ static void Task_Sparkles_ArcDown(u8 taskId) gTasks[taskId].tTimer++; } else + { gTasks[taskId].func = Task_Sparkles_ArcDown_End; + } } static void Task_Sparkles_ArcDown_End(u8 taskId) @@ -388,7 +400,9 @@ static void Task_Sparkles_CircleInward(u8 taskId) gTasks[taskId].tTimer++; } else + { gTasks[taskId].func = Task_Sparkles_CircleInward_End; + } } static void Task_Sparkles_CircleInward_End(u8 taskId) @@ -437,7 +451,9 @@ static void Task_Sparkles_SprayAndFlash(u8 taskId) gTasks[taskId].tTimer++; } else + { gTasks[taskId].func = Task_Sparkles_SprayAndFlash_End; + } } static void Task_Sparkles_SprayAndFlash_End(u8 taskId) @@ -486,7 +502,9 @@ static void Task_Sparkles_SprayAndFlashTrade(u8 taskId) gTasks[taskId].tTimer++; } else + { gTasks[taskId].func = Task_Sparkles_SprayAndFlash_End; + } } #undef tTimer @@ -560,9 +578,13 @@ static void Task_CycleEvolutionMonSprite_Init(u8 taskId) static void Task_CycleEvolutionMonSprite_TryEnd(u8 taskId) { if (gTasks[taskId].tEvoStopped) + { EndOnPreEvoMon(taskId); + } else if (gTasks[taskId].tScaleSpeed == 128) + { EndOnPostEvoMon(taskId); + } else { gTasks[taskId].tScaleSpeed += 2; @@ -574,7 +596,9 @@ static void Task_CycleEvolutionMonSprite_TryEnd(u8 taskId) static void Task_CycleEvolutionMonSprite_UpdateSize(u8 taskId) { if (gTasks[taskId].tEvoStopped) + { gTasks[taskId].func = EndOnPreEvoMon; + } else { u16 oamMatrixArg; @@ -583,7 +607,9 @@ static void Task_CycleEvolutionMonSprite_UpdateSize(u8 taskId) { // Set pre-evo sprite growth if (gTasks[taskId].tPreEvoScale < MON_MAX_SCALE - gTasks[taskId].tScaleSpeed) + { gTasks[taskId].tPreEvoScale += gTasks[taskId].tScaleSpeed; + } else { gTasks[taskId].tPreEvoScale = MON_MAX_SCALE; @@ -592,7 +618,9 @@ static void Task_CycleEvolutionMonSprite_UpdateSize(u8 taskId) // Set post-evo sprite shrink if (gTasks[taskId].tPostEvoScale > MON_MIN_SCALE + gTasks[taskId].tScaleSpeed) + { gTasks[taskId].tPostEvoScale -= gTasks[taskId].tScaleSpeed; + } else { gTasks[taskId].tPostEvoScale = MON_MIN_SCALE; @@ -603,7 +631,9 @@ static void Task_CycleEvolutionMonSprite_UpdateSize(u8 taskId) { // Set post-evo sprite growth if (gTasks[taskId].tPostEvoScale < MON_MAX_SCALE - gTasks[taskId].tScaleSpeed) + { gTasks[taskId].tPostEvoScale += gTasks[taskId].tScaleSpeed; + } else { gTasks[taskId].tPostEvoScale = MON_MAX_SCALE; @@ -612,7 +642,9 @@ static void Task_CycleEvolutionMonSprite_UpdateSize(u8 taskId) // Set pre-evo sprite shrink if (gTasks[taskId].tPreEvoScale > MON_MIN_SCALE + gTasks[taskId].tScaleSpeed) + { gTasks[taskId].tPreEvoScale -= gTasks[taskId].tScaleSpeed; + } else { gTasks[taskId].tPreEvoScale = MON_MIN_SCALE; diff --git a/src/field_camera.c b/src/field_camera.c index 290ddddaf1..e76ba3d855 100644 --- a/src/field_camera.c +++ b/src/field_camera.c @@ -231,7 +231,9 @@ static void DrawMetatileAt(const struct MapLayout *mapLayout, u16 offset, int x, if (metatileId > NUM_METATILES_TOTAL) metatileId = 0; if (metatileId < NUM_METATILES_IN_PRIMARY) + { metatiles = mapLayout->primaryTileset->metatiles; + } else { metatiles = mapLayout->secondaryTileset->metatiles; diff --git a/src/field_door.c b/src/field_door.c index 255233ec23..908a65a453 100644 --- a/src/field_door.c +++ b/src/field_door.c @@ -437,7 +437,9 @@ static const struct DoorGraphics *GetDoorGraphics(const struct DoorGraphics *gfx static s8 StartDoorAnimationTask(const struct DoorGraphics *gfx, const struct DoorAnimFrame *frames, u32 x, u32 y) { if (FuncIsActiveTask(Task_AnimateDoor) == TRUE) + { return -1; + } else { u8 taskId = CreateTask(Task_AnimateDoor, 0x50); diff --git a/src/field_effect.c b/src/field_effect.c index d907c3f16d..5dcc4b3c08 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -1293,7 +1293,8 @@ static void CreateHofMonitorSprite(s16 taskId, s16 x, s16 y, bool8 isSmallMonito { spriteId = CreateSpriteAtEnd(&sSpriteTemplate_HofMonitorBig, x, y, 0); SetSubspriteTables(&gSprites[spriteId], &sSubspriteTable_HofMonitorBig); - } else + } + else { spriteId = CreateSpriteAtEnd(&sSpriteTemplate_HofMonitorSmall, x, y, 0); } @@ -2003,7 +2004,8 @@ static bool8 LavaridgeGymB1FWarpEffect_Rise(struct Task *task, struct ObjectEven { task->data[1] <<= 1; } - } else if (!(task->data[2] & 4) && (task->data[1] > 0)) + } + else if (!(task->data[2] & 4) && (task->data[1] > 0)) { task->data[1] >>= 1; } @@ -2017,7 +2019,8 @@ static bool8 LavaridgeGymB1FWarpEffect_Rise(struct Task *task, struct ObjectEven { task->data[3]++; } - } else + } + else { task->data[4] = 1; } @@ -2169,7 +2172,8 @@ static bool8 LavaridgeGym1FWarpEffect_AshPuff(struct Task *task, struct ObjectEv gFieldEffectArguments[3] = sprite->oam.priority; task->data[1] = FieldEffectStart(FLDEFF_ASH_PUFF); task->data[0]++; - } else + } + else { task->data[1]++; ObjectEventSetHeldMovement(objectEvent, GetWalkInPlaceFasterMovementAction(objectEvent->facingDirection)); @@ -2499,7 +2503,8 @@ static void TeleportWarpInFieldEffect_SpinEnter(struct Task *task) objectEvent->triggerGroundEffectsOnMove = TRUE; sprite->subspriteMode = task->data[14]; } - } else + } + else { sprite->oam.priority = 1; if (sprite->subspriteMode != SUBSPRITES_OFF) diff --git a/src/item_use.c b/src/item_use.c index abd80e0eae..322eaf76c0 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -122,7 +122,9 @@ static void SetUpItemUseOnFieldCallback(u8 taskId) SetUpItemUseCallback(taskId); } else + { sItemUseOnFieldCB(taskId); + } } static void FieldCB_UseItemOnField(void) @@ -148,7 +150,9 @@ static void DisplayCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyIte DisplayItemMessageInBattlePyramid(taskId, gText_DadsAdvice, Task_CloseBattlePyramidBagMessage); } else + { DisplayItemMessageOnField(taskId, gStringVar4, Task_CloseCantUseKeyItemMessage); + } } static void DisplayDadsAdviceCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyItemOnField) @@ -202,7 +206,9 @@ void ItemUseOutOfBattle_Bike(u8 taskId) PlayerGetDestCoords(&coordsX, &coordsY); behavior = MapGridGetMetatileBehaviorAt(coordsX, coordsY); if (FlagGet(FLAG_SYS_CYCLING_ROAD) == TRUE || MetatileBehavior_IsVerticalRail(behavior) == TRUE || MetatileBehavior_IsHorizontalRail(behavior) == TRUE || MetatileBehavior_IsIsolatedVerticalRail(behavior) == TRUE || MetatileBehavior_IsIsolatedHorizontalRail(behavior) == TRUE) + { DisplayCannotDismountBikeMessage(taskId, tUsingRegisteredKeyItem); + } else { if (Overworld_IsBikingAllowed() == TRUE && IsBikingDisallowedByPlayer() == 0) @@ -211,7 +217,9 @@ void ItemUseOutOfBattle_Bike(u8 taskId) SetUpItemUseOnFieldCallback(taskId); } else + { DisplayDadsAdviceCannotUseItemMessage(taskId, tUsingRegisteredKeyItem); + } } } @@ -264,7 +272,9 @@ void ItemUseOutOfBattle_Rod(u8 taskId) SetUpItemUseOnFieldCallback(taskId); } else + { DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); + } } static void ItemUseOnFieldCB_Rod(u8 taskId) @@ -951,7 +961,9 @@ void ItemUseInBattle_PokeBall(u8 taskId) DisplayItemMessage(taskId, FONT_NORMAL, gText_BoxFull, CloseItemMessage); } else + { DisplayItemMessageInBattlePyramid(taskId, gText_BoxFull, Task_CloseBattlePyramidBagMessage); + } } static void Task_CloseStatIncreaseMessage(u8 taskId) diff --git a/src/librfu_sio32id.c b/src/librfu_sio32id.c index 32391d781c..c40bb825b3 100644 --- a/src/librfu_sio32id.c +++ b/src/librfu_sio32id.c @@ -145,7 +145,9 @@ static void Sio32IDIntr(void) } } else + { gRfuSIO32Id.lastId = regSIODATA32; + } } else { diff --git a/src/link_rfu_2.c b/src/link_rfu_2.c index 4c4323c1ed..6b20cf9678 100644 --- a/src/link_rfu_2.c +++ b/src/link_rfu_2.c @@ -1175,7 +1175,9 @@ static void RfuHandleReceiveCommand(u8 unused) gRfu.numBlocksReceived[i] = 0; } else + { gRfu.numBlocksReceived[i]++; + } } } } @@ -1302,7 +1304,9 @@ bool32 Rfu_InitBlockSend(const u8 *src, size_t size) gRfu.sendBlock.count = (size / 12) + r4; gRfu.sendBlock.next = 0; if (size > BLOCK_BUFFER_SIZE) + { gRfu.sendBlock.payload = src; + } else { if (src != gBlockSendBuffer) @@ -1629,9 +1633,8 @@ static bool8 CheckForLeavingGroupMembers(void) } else if (gRfuSlotStatusNI[gRfu.childSlot]->recv.state == SLOT_STATE_RECV_FAILED) - rfu_clearSlot(TYPE_NI_RECV, i); { - + rfu_clearSlot(TYPE_NI_RECV, i); } } } @@ -1777,7 +1780,9 @@ static void Task_PlayerExchange(u8 taskId) gTasks[taskId].tState = 101; } else + { gTasks[taskId].tState = 2; + } break; case 101: if (gSendCmd[0] == 0) @@ -1798,7 +1803,9 @@ static void Task_PlayerExchange(u8 taskId) } } else + { gTasks[taskId].tState++; + } break; case 4: if (AreAllPlayersFinishedReceiving()) diff --git a/src/lottery_corner.c b/src/lottery_corner.c index 052e2cfc38..117a5d6331 100644 --- a/src/lottery_corner.c +++ b/src/lottery_corner.c @@ -76,7 +76,9 @@ void PickLotteryCornerTicket(void) } } else // Pokémon are always arranged from populated spots first to unpopulated, so the moment a NONE species is found, that's the end of the list. + { break; + } } for (i = 0; i < TOTAL_BOXES_COUNT; i++) @@ -134,7 +136,9 @@ static u8 GetMatchingDigits(u16 winNumber, u16 otId) matchingDigits++; } else + { break; + } } return matchingDigits; } diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c index dda6e6bffa..7338afb94b 100644 --- a/src/mauville_old_man.c +++ b/src/mauville_old_man.c @@ -481,7 +481,9 @@ static void BardSing(struct Task *task, struct BardSong *song) GetWordPhonemes(song, MACRO1(word)); song->currWord++; if (song->sound->songLengthId != 0xFF) + { song->state = 0; + } else { song->state = 3; @@ -531,7 +533,9 @@ static void BardSing(struct Task *task, struct BardSong *song) { song->currPhoneme++; if (song->currPhoneme != 6 && song->sound[song->currPhoneme].songLengthId != 0xFF) + { song->state = 0; + } else { song->state = 3; @@ -850,7 +854,9 @@ void SanitizeReceivedRubyOldMan(union OldMan * oldMan, u32 version, u32 language trader->language[i] = LANGUAGE_JAPANESE; } else + { trader->language[i] = language; + } } } else diff --git a/src/mini_printf.c b/src/mini_printf.c index e4b8937242..17665cdf06 100644 --- a/src/mini_printf.c +++ b/src/mini_printf.c @@ -167,9 +167,9 @@ static s32 _putsEncoded(char *s, s32 len, void *buf) static s32 mini_strlen(const char *s) { - s32 len = 0; - while (s[len] != '\0') len++; - return len; + s32 len = 0; + while (s[len] != '\0') len++; + return len; } static s32 mini_itoa(s32 value, u32 radix, s32 uppercase, bool32 unsig, char *buffer) @@ -274,7 +274,8 @@ s32 mini_vpprintf(void* buf, const char *fmt, va_list va) { len = 1; len = _putsAscii(&ch, len, buf); - } else + } + else { char pad_char = ' '; s32 pad_to = 0; @@ -310,7 +311,8 @@ s32 mini_vpprintf(void* buf, const char *fmt, va_list va) if(l) { len = mini_itoa(va_arg(va, u32), 10, 0, (ch=='u'), bf2); - } else + } + else { if(ch == 'u') { @@ -352,7 +354,8 @@ s32 mini_vpprintf(void* buf, const char *fmt, va_list va) { len = mini_pad(ptr, len, pad_char, pad_to, bf); len = _putsAscii(bf, len, buf); - } else + } + else { len = _putsAscii(ptr, len, buf); } @@ -364,7 +367,8 @@ s32 mini_vpprintf(void* buf, const char *fmt, va_list va) { len = mini_pad(ptr, len, pad_char, pad_to, bf); len = _putsEncoded(bf, len, buf); - } else + } + else { len = _putsEncoded(ptr, len, buf); } diff --git a/src/party_menu.c b/src/party_menu.c index 56625d09a3..cbd469713a 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4800,7 +4800,9 @@ static void Task_LearnNextMoveOrClosePartyMenu(u8 taskId) if (IsFanfareTaskInactive() && ((JOY_NEW(A_BUTTON)) || (JOY_NEW(B_BUTTON)))) { if (gPartyMenu.learnMoveState == 1) + { Task_TryLearningNextMove(taskId); + } else { if (gPartyMenu.learnMoveState == 2) // never occurs diff --git a/src/player_pc.c b/src/player_pc.c index 009aa7810f..81170a86c9 100644 --- a/src/player_pc.c +++ b/src/player_pc.c @@ -880,7 +880,9 @@ static void Mailbox_CancelMoveToBag(u8 taskId) static void Mailbox_Give(u8 taskId) { if (CalculatePlayerPartyCount() == 0) + { Mailbox_NoPokemonForMail(taskId); + } else { FadeScreen(FADE_TO_BLACK, 0); diff --git a/src/pokedex.c b/src/pokedex.c index c0b20bf9d6..030020df89 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -2396,7 +2396,9 @@ static void CreateMonListEntry(u8 position, u16 b, u16 ignored) if (vOffset >= LIST_SCROLL_STEP) vOffset -= LIST_SCROLL_STEP; if (entryNum < 0 || entryNum >= NATIONAL_DEX_COUNT || sPokedexView->pokedexList[entryNum].dexNum == 0xFFFF) + { ClearMonListEntry(17, vOffset * 2, ignored); + } else { ClearMonListEntry(17, vOffset * 2, ignored); @@ -2685,7 +2687,9 @@ static bool8 TryDoInfoScreenScroll(void) } if (sPokedexView->selectedPokemon == selectedPokemon) + { return FALSE; + } else { sPokedexView->selectedPokemon = selectedPokemon; @@ -2708,7 +2712,9 @@ static bool8 TryDoInfoScreenScroll(void) } if (sPokedexView->selectedPokemon == selectedPokemon) + { return FALSE; + } else { sPokedexView->selectedPokemon = selectedPokemon; diff --git a/src/pokemon.c b/src/pokemon.c index d59f46ada1..e98182b0ae 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2874,8 +2874,11 @@ void CalculateMonStats(struct Pokemon *mon) else { if (currentHP == 0 && oldMaxHP == 0) + { currentHP = newMaxHP; - else if (currentHP != 0) { + } + 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 @@ -2884,7 +2887,9 @@ void CalculateMonStats(struct Pokemon *mon) #endif } else + { return; + } } SetMonData(mon, MON_DATA_HP, ¤tHP); @@ -6394,11 +6399,17 @@ void ClearBattleMonForms(void) u16 GetBattleBGM(void) { if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON) + { return MUS_VS_KYOGRE_GROUDON; + } else if (gBattleTypeFlags & BATTLE_TYPE_REGI) + { return MUS_VS_REGI; + } else if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) + { return MUS_VS_TRAINER; + } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { u8 trainerClass; @@ -6445,7 +6456,9 @@ u16 GetBattleBGM(void) } } else + { return MUS_VS_WILD; + } } void PlayBattleBGM(void) diff --git a/src/pokenav_conditions_search_results.c b/src/pokenav_conditions_search_results.c index 1817398020..e42f35481b 100644 --- a/src/pokenav_conditions_search_results.c +++ b/src/pokenav_conditions_search_results.c @@ -184,13 +184,21 @@ static bool32 HandleConditionSearchInput_WaitSetup(struct Pokenav_SearchResults static u32 HandleConditionSearchInput(struct Pokenav_SearchResults *menu) { if (JOY_REPEAT(DPAD_UP)) + { return CONDITION_SEARCH_FUNC_MOVE_UP; + } else if (JOY_REPEAT(DPAD_DOWN)) + { return CONDITION_SEARCH_FUNC_MOVE_DOWN; + } else if (JOY_NEW(DPAD_LEFT)) + { return CONDITION_SEARCH_FUNC_PAGE_UP; + } else if (JOY_NEW(DPAD_RIGHT)) + { return CONDITION_SEARCH_FUNC_PAGE_DOWN; + } else if (JOY_NEW(B_BUTTON)) { // Exiting back to main search menu @@ -207,7 +215,9 @@ static u32 HandleConditionSearchInput(struct Pokenav_SearchResults *menu) return CONDITION_SEARCH_FUNC_SELECT_MON; } else + { return CONDITION_SEARCH_FUNC_NONE; + } } static u32 ReturnToConditionSearchList(struct Pokenav_SearchResults *menu) diff --git a/src/pokenav_menu_handler_gfx.c b/src/pokenav_menu_handler_gfx.c index ede88affdb..e223b7caba 100644 --- a/src/pokenav_menu_handler_gfx.c +++ b/src/pokenav_menu_handler_gfx.c @@ -505,7 +505,9 @@ static u32 LoopedTask_OpenMenu(s32 state) ShowBg(2); ShowBg(3); if (gfx->pokenavAlreadyOpen) + { PokenavFadeScreen(POKENAV_FADE_FROM_BLACK); + } else { PlaySE(SE_POKENAV_ON); diff --git a/src/slot_machine.c b/src/slot_machine.c index 34c7ef8849..217767fc9e 100644 --- a/src/slot_machine.c +++ b/src/slot_machine.c @@ -2324,7 +2324,9 @@ static bool8 ReelTask_MoveToStop(struct Task *task) memcpy(reelStopShocks, sReelStopShocks, sizeof(sReelStopShocks)); reelPixelPos = sSlotMachine->reelPixelOffsets[task->tReelId] % REEL_SYMBOL_HEIGHT; if (reelPixelPos != 0) + { reelPixelPos = AdvanceSlotReelToNextSymbol(task->tReelId, sSlotMachine->reelSpeed); + } else if (sSlotMachine->reelExtraTurns[task->tReelId]) { sSlotMachine->reelExtraTurns[task->tReelId]--; diff --git a/src/sprite.c b/src/sprite.c index 0736269be0..d11277400f 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -1090,9 +1090,13 @@ void ContinueAffineAnim(struct Sprite *sprite) u8 matrixNum = GetSpriteMatrixNum(sprite); if (sAffineAnimStates[matrixNum].delayCounter) + { AffineAnimDelay(matrixNum, sprite); + } else if (sprite->affineAnimPaused) + { return; + } else { s16 type; diff --git a/src/tv.c b/src/tv.c index 9ab9fc8969..26d568642f 100644 --- a/src/tv.c +++ b/src/tv.c @@ -5364,7 +5364,8 @@ static void DoTVShow3CheersForPokeblocks(void) if (show->threeCheers.sheen > 24) { StringCopy(gStringVar2, gText_Excellent); - } else if (show->threeCheers.sheen > 22) + } + else if (show->threeCheers.sheen > 22) { StringCopy(gStringVar2, gText_VeryGood); } From 861c579c11d995c1f5d3c7d3c591988935913697 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 13 Dec 2024 23:39:51 +0100 Subject: [PATCH 04/45] remove sBirchSpeechPlatformBlackPal (#2075) --- graphics/birch_speech/bg2.pal | 10 +++++++++- src/main_menu.c | 3 +-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/graphics/birch_speech/bg2.pal b/graphics/birch_speech/bg2.pal index 3457f9b455..33f619ee44 100644 --- a/graphics/birch_speech/bg2.pal +++ b/graphics/birch_speech/bg2.pal @@ -1,6 +1,6 @@ JASC-PAL 0100 -8 +16 255 255 164 255 255 106 222 222 90 @@ -9,3 +9,11 @@ JASC-PAL 123 123 49 90 90 32 57 57 16 +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/src/main_menu.c b/src/main_menu.c index 6a6ee99557..10b34728b3 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -255,7 +255,6 @@ static const u16 sBirchSpeechBgPals[][16] = { static const u32 sBirchSpeechShadowGfx[] = INCBIN_U32("graphics/birch_speech/shadow.4bpp.lz"); static const u32 sBirchSpeechBgMap[] = INCBIN_U32("graphics/birch_speech/map.bin.lz"); static const u16 sBirchSpeechBgGradientPal[] = INCBIN_U16("graphics/birch_speech/bg2.gbapal"); -static const u16 sBirchSpeechPlatformBlackPal[] = {RGB_BLACK, RGB_BLACK, RGB_BLACK, RGB_BLACK, RGB_BLACK, RGB_BLACK, RGB_BLACK, RGB_BLACK}; #define MENU_LEFT 2 #define MENU_TOP_WIN0 1 @@ -1278,7 +1277,7 @@ static void Task_NewGameBirchSpeech_Init(u8 taskId) LZ77UnCompVram(sBirchSpeechShadowGfx, (void *)VRAM); LZ77UnCompVram(sBirchSpeechBgMap, (void *)(BG_SCREEN_ADDR(7))); LoadPalette(sBirchSpeechBgPals, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); - LoadPalette(sBirchSpeechPlatformBlackPal, BG_PLTT_ID(0) + 1, PLTT_SIZEOF(8)); + LoadPalette(&sBirchSpeechBgGradientPal[8], BG_PLTT_ID(0) + 1, PLTT_SIZEOF(8)); ScanlineEffect_Stop(); ResetSpriteData(); FreeAllSpritePalettes(); From beeca545aa8dfc1c38f826f5b8ecbba84f6624b3 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Sun, 15 Dec 2024 09:10:42 -0500 Subject: [PATCH 05/45] Fix HGSS dex sort orders working incorrectly (#5790) --- src/pokedex_plus_hgss.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index 74b57fa3a5..8782044769 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -2560,11 +2560,11 @@ static void CreatePokedexList(u8 dexMode, u8 order) } break; case ORDER_ALPHABETICAL: - for (i = 0; i < NUM_SPECIES - 1; i++) + for (i = 0; i < NATIONAL_DEX_COUNT; i++) { temp_dexNum = gPokedexOrder_Alphabetical[i]; - if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN)) + if ((!temp_isHoennDex || NationalToHoennOrder(temp_dexNum) != 0) && GetSetPokedexFlag(temp_dexNum, FLAG_GET_SEEN)) { sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum; sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE; @@ -2578,7 +2578,7 @@ static void CreatePokedexList(u8 dexMode, u8 order) { temp_dexNum = gPokedexOrder_Weight[i]; - if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) + if ((!temp_isHoennDex || NationalToHoennOrder(temp_dexNum) != 0) && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) { sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum; sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE; @@ -2592,7 +2592,7 @@ static void CreatePokedexList(u8 dexMode, u8 order) { temp_dexNum = gPokedexOrder_Weight[i]; - if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) + if ((!temp_isHoennDex || NationalToHoennOrder(temp_dexNum) != 0) && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) { sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum; sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE; @@ -2606,7 +2606,7 @@ static void CreatePokedexList(u8 dexMode, u8 order) { temp_dexNum = gPokedexOrder_Height[i]; - if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) + if ((!temp_isHoennDex || NationalToHoennOrder(temp_dexNum) != 0) && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) { sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum; sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE; @@ -2620,7 +2620,7 @@ static void CreatePokedexList(u8 dexMode, u8 order) { temp_dexNum = gPokedexOrder_Height[i]; - if (NationalToHoennOrder(temp_dexNum) <= temp_dexCount && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) + if ((!temp_isHoennDex || NationalToHoennOrder(temp_dexNum) != 0) && GetSetPokedexFlag(temp_dexNum, FLAG_GET_CAUGHT)) { sPokedexView->pokedexList[sPokedexView->pokemonListCount].dexNum = temp_dexNum; sPokedexView->pokedexList[sPokedexView->pokemonListCount].seen = TRUE; From c7a2ef337197ae1acfd6cd3cf8577b6b4a904a4f Mon Sep 17 00:00:00 2001 From: iriv24 <40581123+iriv24@users.noreply.github.com> Date: Sun, 15 Dec 2024 10:04:06 -0500 Subject: [PATCH 06/45] Prevent Key Items that open other menus from causing a crash if registered and used from the field (#5810) --- src/item_use.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/item_use.c b/src/item_use.c index c04d9b9911..c9be4f5caa 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1400,9 +1400,17 @@ void ItemUseOutOfBattle_ZygardeCube(u8 taskId) void ItemUseOutOfBattle_Fusion(u8 taskId) { - gItemUseCB = ItemUseCB_Fusion; - gTasks[taskId].data[0] = FALSE; - SetUpItemUseCallback(taskId); + if (!gTasks[taskId].tUsingRegisteredKeyItem) + { + gItemUseCB = ItemUseCB_Fusion; + gTasks[taskId].data[0] = FALSE; + SetUpItemUseCallback(taskId); + } + else + { + // TODO: handle key items with callbacks to menus allow to be used by registering them. + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); + } } void Task_UseHoneyOnField(u8 taskId) @@ -1552,10 +1560,18 @@ static void ItemUseOnFieldCB_TownMap(u8 taskId) void ItemUseOutOfBattle_TownMap(u8 taskId) { - sItemUseOnFieldCB = ItemUseOnFieldCB_TownMap; - gFieldCallback = FieldCB_UseItemOnField; - gBagMenu->newScreenCallback = CB2_ReturnToField; - Task_FadeAndCloseBagMenu(taskId); + if (!gTasks[taskId].tUsingRegisteredKeyItem) + { + sItemUseOnFieldCB = ItemUseOnFieldCB_TownMap; + gFieldCallback = FieldCB_UseItemOnField; + gBagMenu->newScreenCallback = CB2_ReturnToField; + Task_FadeAndCloseBagMenu(taskId); + } + else + { + // TODO: handle key items with callbacks to menus allow to be used by registering them. + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); + } } #undef tUsingRegisteredKeyItem From 39bc916ca82879a86e33b4ee197575cac390c5d9 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 15 Dec 2024 12:04:30 -0300 Subject: [PATCH 07/45] Fix website not showing the "How to add mon" 1.10 tutorial (#5813) --- docs/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 597534e318..21584f3ad7 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -12,6 +12,7 @@ - [How to add a new move](tutorials/how_to_new_move.md) - [How to add a new trainer class](tutorials/how_to_trainer_class.md) - [How to add a new Pokémon]() + - [v1.10.x](tutorials/how_to_new_pokemon_1_10_0.md) - [v1.9.x](tutorials/how_to_new_pokemon_1_9_0.md) - [v1.8.x](tutorials/how_to_new_pokemon_1_8_0.md) - [v1.7.x](tutorials/how_to_new_pokemon_1_7_0.md) From 12f199c641996798c852492230fc1b8c59df5bd3 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:54:50 +0100 Subject: [PATCH 08/45] Fixes absorb still draining HP when flinched (#5814) --- src/battle_script_commands.c | 4 +++- test/battle/move_effect/absorb.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 12a2e215bf..f37a18b2ed 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5674,7 +5674,9 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_ABSORB: - if (gMovesInfo[gCurrentMove].effect == EFFECT_ABSORB) + if (gMovesInfo[gCurrentMove].effect == EFFECT_ABSORB + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && TARGET_TURN_DAMAGED) { if (gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && gMovesInfo[gCurrentMove].healingMove) { diff --git a/test/battle/move_effect/absorb.c b/test/battle/move_effect/absorb.c index d046876b1b..f06c970585 100644 --- a/test/battle/move_effect/absorb.c +++ b/test/battle/move_effect/absorb.c @@ -125,4 +125,20 @@ SINGLE_BATTLE_TEST("Draining Kiss recovers 75% of the damage dealt") } } +SINGLE_BATTLE_TEST("Absorb does not drain any HP if user flinched") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_FAKE_OUT); MOVE(player, MOVE_ABSORB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player); + MESSAGE("The opposing Wobbuffet had its energy drained!"); + } + } +} + TO_DO_BATTLE_TEST("Absorb recovers 50% of the damage dealt to a Substitute"); From 99ba36b446c79c4b671077c966a71eeacfc9c446 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 17 Dec 2024 09:47:37 +0100 Subject: [PATCH 09/45] Fixes Tidy Up (#5819) --- data/battle_scripts_1.s | 6 ++++++ src/battle_script_commands.c | 4 ++-- test/battle/move_effect/tidy_up.c | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 1eb74cea31..2441b9547d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -134,7 +134,11 @@ BattleScript_EffectTidyUp:: pause B_WAIT_TIME_MED ppreduce waitstate + saveattacker + savetarget trytidyup FALSE, BattleScript_EffectTidyUpDoMoveAnimation + restoreattacker + restoretarget goto BattleScript_EffectDragonDanceFromStatUp BattleScript_EffectTidyUpDoMoveAnimation:: @@ -143,6 +147,8 @@ BattleScript_EffectTidyUpDoMoveAnimation:: trytidyup TRUE, NULL printstring STRINGID_TIDYINGUPCOMPLETE waitmessage B_WAIT_TIME_LONG + restoreattacker + restoretarget goto BattleScript_EffectDragonDanceFromStatUp BattleScript_EffectUpperHand:: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f37a18b2ed..1d03cf3f56 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8839,8 +8839,8 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) static bool32 TryTidyUpClear(u32 battlerAtk, bool32 clear) { - s32 i; - u8 saveBattler = gBattlerAttacker; + u32 i; + u32 saveBattler = gBattlerAttacker; for (i = 0; i < NUM_BATTLE_SIDES; i++) { diff --git a/test/battle/move_effect/tidy_up.c b/test/battle/move_effect/tidy_up.c index 986e9a2ba3..fcb78ba962 100644 --- a/test/battle/move_effect/tidy_up.c +++ b/test/battle/move_effect/tidy_up.c @@ -99,3 +99,24 @@ AI_SINGLE_BATTLE_TEST("AI will try to remove hazards if slower then target even TURN { EXPECT_MOVE(opponent, MOVE_TIDY_UP); } } } + +SINGLE_BATTLE_TEST("Tidy Up raises Attack and Speed by one after clearing hazards on opposing field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STEALTH_ROCK); } + TURN { MOVE(player, MOVE_TIDY_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TIDY_UP, player); + MESSAGE("Tidying up complete!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Attack rose!"); + MESSAGE("Wobbuffet's Speed rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} From 11bc9bd2f2c9067b2de21f8a902902febbba2809 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Wed, 18 Dec 2024 08:39:34 -0500 Subject: [PATCH 10/45] Ally Switch extra battlerId tracking (#5823) Co-authored-by: ghoulslash --- src/battle_anim_effects_1.c | 77 +++++++++++++++++++++++++++ test/battle/move_effect/ally_switch.c | 74 +++++++++++++++++++++++++ test/battle/move_effect/sticky_web.c | 28 ++++++++++ 3 files changed, 179 insertions(+) diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index d5efe499eb..1d50cee3d1 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6642,6 +6642,79 @@ static void ReloadBattlerSprites(u32 battler, struct Pokemon *party) } } +static void TrySwapSkyDropTargets(u32 battlerAtk, u32 battlerPartner) +{ + u32 i, temp; + + // battlerAtk is using Ally Switch + // check if our partner is the target of sky drop + // If so, change that index to battlerAtk + for (i = 0; i < gBattlersCount; i++) { + if (gBattleStruct->skyDropTargets[i] == battlerPartner) { + gBattleStruct->skyDropTargets[i] = battlerAtk; + break; + } + } + + // Then swap our own sky drop targets with the partner in case our partner is mid-skydrop + SWAP(gBattleStruct->skyDropTargets[battlerAtk], gBattleStruct->skyDropTargets[battlerPartner], temp); +} + +#define TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, side, field) \ + if (gSideTimers[side].field == battlerAtk) \ + gSideTimers[side].field = battlerPartner; \ + else if (gSideTimers[side].field == battlerPartner) \ + gSideTimers[side].field = battlerAtk; + +static void TrySwapStickyWebBattlerId(u32 battlerAtk, u32 battlerPartner) +{ + u32 atkSide = GetBattlerSide(battlerAtk); + u32 oppSide = GetBattlerSide(BATTLE_OPPOSITE(battlerAtk)); + + // not all of these are needed to be swapped, but are done so to be robust to anything in the future that might care about them + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, reflectBattlerId); + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, lightscreenBattlerId); + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, mistBattlerId); + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, safeguardBattlerId); + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, auroraVeilBattlerId); + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, tailwindBattlerId); + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, luckyChantBattlerId); + + // if we've set sticky web on the opposing side, need to swap stickyWebBattlerId for mirror armor + TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, oppSide, stickyWebBattlerId); +} +#undef TRY_SIDE_TIMER_BATTLER_ID_SWAP + +static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner) +{ + u32 i, temp; + u32 oppSide = GetBattlerSide(BATTLE_OPPOSITE(battlerAtk)); + + // if used future sight on opposing side, properly track who used it + if (gSideStatuses[oppSide] & SIDE_STATUS_FUTUREATTACK) { + for (i = 0; i < gBattlersCount; i++) { + if (IsAlly(i,battlerAtk)) + continue; // only on opposing side + if (gWishFutureKnock.futureSightBattlerIndex[i] == battlerAtk) { + // if target was attacked with future sight from us, now they'll be the partner slot + gWishFutureKnock.futureSightBattlerIndex[i] = battlerPartner; + gWishFutureKnock.futureSightPartyIndex[i] = gBattlerPartyIndexes[battlerPartner]; + break; + } else if (gWishFutureKnock.futureSightBattlerIndex[i] == battlerPartner) { + gWishFutureKnock.futureSightBattlerIndex[i] = battlerAtk; + gWishFutureKnock.futureSightPartyIndex[i] = gBattlerPartyIndexes[battlerAtk]; + break; + } + } + } + + // swap wish party indices + if (gWishFutureKnock.wishCounter[battlerAtk] > 0 + || gWishFutureKnock.wishCounter[battlerPartner] > 0) { + SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp); + } +} + static void AnimTask_AllySwitchDataSwap(u8 taskId) { s32 i, j; @@ -6692,6 +6765,10 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SwitchTwoBattlersInParty(battlerAtk, battlerPartner); SWAP(gBattlerPartyIndexes[battlerAtk], gBattlerPartyIndexes[battlerPartner], temp); + TrySwapSkyDropTargets(battlerAtk, battlerPartner); + TrySwapStickyWebBattlerId(battlerAtk, battlerPartner); + TrySwapWishBattlerIds(battlerAtk, battlerPartner); + // For Snipe Shot and abilities Stalwart/Propeller Tail - keep the original target. for (i = 0; i < MAX_BATTLERS_COUNT; i++) { diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index c7aa52d7c5..974730f120 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -203,5 +203,79 @@ DOUBLE_BATTLE_TEST("Ally Switch works if ally used two-turn move like Dig") } } +DOUBLE_BATTLE_TEST("Ally switch swaps sky drop targets if being used by partner") +{ + u8 visibility; + GIVEN { + ASSUME(gMovesInfo[MOVE_SKY_DROP].effect == EFFECT_SKY_DROP); + PLAYER(SPECIES_FEAROW) { Speed(100); } + PLAYER(SPECIES_XATU) { Speed(150); } + OPPONENT(SPECIES_ARON) { Speed(25); Ability(ABILITY_STURDY); } + OPPONENT(SPECIES_WYNAUT) { Speed(30); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SKY_DROP, target: opponentLeft); } + TURN { MOVE(playerRight, MOVE_ALLY_SWITCH); SKIP_TURN(playerLeft); MOVE(opponentRight, MOVE_MUD_SPORT); MOVE(opponentLeft, MOVE_IRON_DEFENSE); } + } SCENE { + MESSAGE("Fearow used Sky Drop!"); + MESSAGE("Fearow took the opposing Aron into the sky!"); + // turn 2 + MESSAGE("Xatu used Ally Switch!"); + MESSAGE("Xatu and Fearow switched places!"); + MESSAGE("Fearow used Sky Drop!"); + HP_BAR(opponentLeft); + MESSAGE("The opposing Wynaut used Mud Sport!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MUD_SPORT, opponentRight); + MESSAGE("The opposing Aron used Iron Defense!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_DEFENSE, opponentLeft); + } THEN { + // all battlers should be visible + visibility = gBattleSpritesDataPtr->battlerData[0].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[1].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[2].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[3].invisible; + EXPECT_EQ(visibility, 0); + } +} + +DOUBLE_BATTLE_TEST("Ally switch swaps opposing sky drop targets if partner is being held in the air") +{ + u8 visibility; + GIVEN { + ASSUME(gMovesInfo[MOVE_SKY_DROP].effect == EFFECT_SKY_DROP); + PLAYER(SPECIES_ARON) { Speed(25); Ability(ABILITY_STURDY); } + PLAYER(SPECIES_WYNAUT) { Speed(30); } + OPPONENT(SPECIES_FEAROW) { Speed(100); } + OPPONENT(SPECIES_XATU) { Speed(150); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SKY_DROP, target: playerLeft); } + TURN { MOVE(opponentRight, MOVE_ALLY_SWITCH); SKIP_TURN(opponentLeft); MOVE(playerRight, MOVE_MUD_SPORT); MOVE(playerLeft, MOVE_IRON_DEFENSE); } + } SCENE { + MESSAGE("The opposing Fearow used Sky Drop!"); + MESSAGE("The opposing Fearow took Aron into the sky!"); + // turn 2 + MESSAGE("The opposing Xatu used Ally Switch!"); + MESSAGE("The opposing Xatu and the opposing Fearow switched places!"); + MESSAGE("The opposing Fearow used Sky Drop!"); + HP_BAR(playerLeft); + MESSAGE("Wynaut used Mud Sport!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MUD_SPORT, playerRight); + MESSAGE("Aron used Iron Defense!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_DEFENSE, playerLeft); + } THEN { + // all battlers should be visible + visibility = gBattleSpritesDataPtr->battlerData[0].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[1].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[2].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[3].invisible; + EXPECT_EQ(visibility, 0); + } +} + // Triple Battles required to test //TO_DO_BATTLE_TEST("Ally Switch fails if the user is in the middle of the field in a Triple Battle"); diff --git a/test/battle/move_effect/sticky_web.c b/test/battle/move_effect/sticky_web.c index f1fff0fd1e..e99368aa7d 100644 --- a/test/battle/move_effect/sticky_web.c +++ b/test/battle/move_effect/sticky_web.c @@ -271,3 +271,31 @@ SINGLE_BATTLE_TEST("Sticky Web is placed on the correct side after Memento") MESSAGE("A sticky web has been laid out on the ground around your team!"); } } + +DOUBLE_BATTLE_TEST("Sticky Web setter has their speed lowered with Mirror Armor even after Ally Switch") +{ + GIVEN { + PLAYER(SPECIES_SQUIRTLE); + PLAYER(SPECIES_CHARMANDER); + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); } // Iron Ball, so that flying type Corviknight is affected by Sticky Web. + OPPONENT(SPECIES_CATERPIE); + OPPONENT(SPECIES_NATU); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); } + TURN { MOVE(opponentRight, MOVE_ALLY_SWITCH); } + TURN { SWITCH(playerRight, 2); } + } SCENE { + // Turn 1 - set up sticky web + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentLeft); + MESSAGE("A sticky web has been laid out on the ground around your team!"); + // Turn 2 - ally switch + MESSAGE("The opposing Natu used Ally Switch!"); + // turn 3 - send our corviknight + SEND_IN_MESSAGE("Corviknight"); + MESSAGE("Corviknight was caught in a sticky web!"); + ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR); + // sticky web setter - caterpie (now opponentRight) gets speed lowered + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Caterpie's Speed fell!"); + } +} From 8f59d9c94fcd29163b5c03ebc2389aef4ea8de79 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 18 Dec 2024 21:39:32 +0100 Subject: [PATCH 11/45] Fixes Shed Tail substitute health (#5826) --- src/battle_script_commands.c | 5 ++++- test/battle/move_effect/shed_tail.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1d03cf3f56..7d342b0b73 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12638,7 +12638,10 @@ static void Cmd_setsubstitute(void) gBattleMons[gBattlerAttacker].status2 |= STATUS2_SUBSTITUTE; gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_WRAPPED; - gDisableStructs[gBattlerAttacker].substituteHP = gBattleMoveDamage; + if (factor == 2) + gDisableStructs[gBattlerAttacker].substituteHP = gBattleMoveDamage / 2; + else + gDisableStructs[gBattlerAttacker].substituteHP = gBattleMoveDamage; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SUBSTITUTE; gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE; } diff --git a/test/battle/move_effect/shed_tail.c b/test/battle/move_effect/shed_tail.c index 51d7652460..6e337f4fe7 100644 --- a/test/battle/move_effect/shed_tail.c +++ b/test/battle/move_effect/shed_tail.c @@ -99,3 +99,26 @@ AI_SINGLE_BATTLE_TEST("AI will use Shed Tail to pivot to another mon while in da TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_SHED_TAIL); } } } + +SINGLE_BATTLE_TEST("Shed Tail creates a Substitute with 1/4 of user maximum health") +{ + u32 hp; + PARAMETRIZE { hp = 160; } + PARAMETRIZE { hp = 164; } + + GIVEN { + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); + PLAYER(SPECIES_BULBASAUR) { MaxHP(hp); } + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_CHARMANDER); + } WHEN { + TURN { MOVE(player, MOVE_SHED_TAIL); MOVE(opponent, MOVE_DRAGON_RAGE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHED_TAIL, player); + if (hp == 160) + MESSAGE("Bulbasaur's substitute faded!"); + else + NOT MESSAGE("Bulbasaur's substitute faded!"); + } +} From f4a0cc0055b4117d2f8b90da3cfc573be70be0a9 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:51:03 +0000 Subject: [PATCH 12/45] Adds Thief/Covet config to send stolen item to bag and Pickup config to pickup user's item in wild battles (#5829) --- include/config/battle.h | 2 + src/battle_script_commands.c | 34 +++-- src/battle_util.c | 2 +- test/battle/ability/pickup.c | 19 ++- .../battle/move_effect_secondary/steal_item.c | 129 ++++++++++++++++++ 5 files changed, 174 insertions(+), 12 deletions(-) create mode 100644 test/battle/move_effect_secondary/steal_item.c diff --git a/include/config/battle.h b/include/config/battle.h index f38be8949c..db3e6dcc77 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -154,6 +154,7 @@ #define B_ABILITY_TRIGGER_CHANCE GEN_LATEST // In Gen3, Shed Skin, Cute Charm, Flame Body, Static and Poison Point have a 1/3 chance to trigger. In Gen 4+ it's 30%. // In Gen3, Effect Spore has a 10% chance to sleep, poison or paralyze, with an equal chance. // In Gen4, it's 30%. In Gen5+ it has 11% to sleep, 9% chance to poison and 10% chance to paralyze. +#define B_PICKUP_WILD GEN_LATEST // In Gen9+, Pickup allows its user to pickup its own used item at the end of the turn in wild battles. // Item settings #define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. @@ -163,6 +164,7 @@ #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_RETURN_STOLEN_NPC_ITEMS GEN_LATEST // In Gen5+, Thief and Covet no longer steal items from NPCs. +#define B_STEAL_WILD_ITEMS GEN_LATEST // In Gen9, Thief and Covet steal a wild pokemon's item and send it to the bag. Before Gen9, the stolen item would be held by the Thief/Covet user. #define B_RESTORE_HELD_BATTLE_ITEMS GEN_LATEST // In Gen9, all non-berry items are restored after battle. #define B_SOUL_DEW_BOOST GEN_LATEST // In Gens3-6, Soul Dew boosts Latis' 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. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7d342b0b73..1bbef29586 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2852,17 +2852,26 @@ static void CheckSetUnburden(u8 battler) void StealTargetItem(u8 battlerStealer, u8 battlerItem) { gLastUsedItem = gBattleMons[battlerItem].item; - gBattleMons[battlerItem].item = 0; + gBattleMons[battlerItem].item = ITEM_NONE; - RecordItemEffectBattle(battlerItem, 0); - RecordItemEffectBattle(battlerStealer, ItemId_GetHoldEffect(gLastUsedItem)); - gBattleMons[battlerStealer].item = gLastUsedItem; + if (B_STEAL_WILD_ITEMS >= GEN_9 + && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)) + && MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_STEAL_ITEM) + && battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this + { + AddBagItem(gLastUsedItem, 1); + } + else + { + RecordItemEffectBattle(battlerStealer, ItemId_GetHoldEffect(gLastUsedItem)); + gBattleMons[battlerStealer].item = gLastUsedItem; + gBattleResources->flags->flags[battlerStealer] &= ~RESOURCE_FLAG_UNBURDEN; + BtlController_EmitSetMonData(battlerStealer, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gLastUsedItem), &gLastUsedItem); // set attacker item + MarkBattlerForControllerExec(battlerStealer); + } + RecordItemEffectBattle(battlerItem, ITEM_NONE); CheckSetUnburden(battlerItem); - gBattleResources->flags->flags[battlerStealer] &= ~RESOURCE_FLAG_UNBURDEN; - - BtlController_EmitSetMonData(battlerStealer, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gLastUsedItem), &gLastUsedItem); // set attacker item - MarkBattlerForControllerExec(battlerStealer); BtlController_EmitSetMonData(battlerItem, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[battlerItem].item); // remove target item MarkBattlerForControllerExec(battlerItem); @@ -3544,8 +3553,13 @@ void SetMoveEffect(bool32 primary, bool32 certain) else { StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item - gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) - gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later + + if (!(B_STEAL_WILD_ITEMS >= GEN_9 + && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) + { + gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) + gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later + } BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_ItemSteal; } diff --git a/src/battle_util.c b/src/battle_util.c index d2f5314742..def2742a1b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11557,7 +11557,7 @@ u16 GetUsedHeldItem(u32 battler) bool32 CantPickupItem(u32 battler) { // Used by RandomUniformExcept() for RNG_PICKUP - if (battler == gBattlerAttacker && gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK)) + if (battler == gBattlerAttacker && (B_PICKUP_WILD < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) return TRUE; return !(IsBattlerAlive(battler) && GetUsedHeldItem(battler) && gBattleStruct->canPickupItem & (1u << battler)); } diff --git a/test/battle/ability/pickup.c b/test/battle/ability/pickup.c index 927e1b3468..a6dabb66cc 100644 --- a/test/battle/ability/pickup.c +++ b/test/battle/ability/pickup.c @@ -23,7 +23,24 @@ SINGLE_BATTLE_TEST("Pickup grants an item used by another Pokémon") } } -SINGLE_BATTLE_TEST("Pickup doesn't grant the user their item") +WILD_BATTLE_TEST("Pickup grants an item used by itself in wild battles (Gen 9)") +{ + GIVEN { + ASSUME(B_PICKUP_WILD >= GEN_9); + PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + ABILITY_POPUP(player, ABILITY_PICKUP); + MESSAGE("Zigzagoon found one Sitrus Berry!"); + } THEN { + EXPECT_EQ(player->item, ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Pickup doesn't grant the user their item outside wild battles") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect_secondary/steal_item.c b/test/battle/move_effect_secondary/steal_item.c new file mode 100644 index 0000000000..8a4ae931d2 --- /dev/null +++ b/test/battle/move_effect_secondary/steal_item.c @@ -0,0 +1,129 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE); + ASSUME(MoveHasAdditionalEffect(MOVE_COVET, MOVE_EFFECT_STEAL_ITEM) == TRUE); +} + +SINGLE_BATTLE_TEST("Thief and Covet steal target's held item") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } THEN { + EXPECT_EQ(player->item, ITEM_HYPER_POTION); + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Thief and Covet steal player's held item if opponent is a trainer") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + ASSUME(B_TRAINERS_KNOCK_OFF_ITEMS == TRUE); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, player); + } THEN { + EXPECT_EQ(opponent->item, ITEM_HYPER_POTION); + EXPECT_EQ(player->item, ITEM_NONE); + } +} + +WILD_BATTLE_TEST("Thief and Covet don't steal player's held item if opponent is a wild mon") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + ASSUME(B_TRAINERS_KNOCK_OFF_ITEMS == TRUE); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, player); + } THEN { + EXPECT_EQ(player->item, ITEM_HYPER_POTION); + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Thief and Covet don't steal target's held item if user is holding an item") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POTION); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } THEN { + EXPECT_EQ(player->item, ITEM_POTION); + EXPECT_EQ(opponent->item, ITEM_HYPER_POTION); + } +} + +SINGLE_BATTLE_TEST("Thief and Covet don't steal target's held item if target has no item") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } +} + +// Test can't currently verify if the item is sent to Bag +WILD_BATTLE_TEST("Thief and Covet steal target's held item and it's added to Bag in wild battles (Gen 9)") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + ASSUME(B_STEAL_WILD_ITEMS >= GEN_9); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} From 6bba281360f0a1a0b03007e1154eb0c47a20396a Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:54:42 +0000 Subject: [PATCH 13/45] Fixes Clear Amulet displaying the wrong battler and Starting Status displaying the wrong message (#5831) --- src/battle_message.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/battle_message.c b/src/battle_message.c index 76b9fde5cc..7841c18eac 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -707,7 +707,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_NOONEWILLBEABLETORUNAWAY] = COMPOUND_STRING("No one will be able to run away during the next turn!"), [STRINGID_DESTINYKNOTACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} fell in love because of the {B_LAST_ITEM}!"), [STRINGID_CLOAKEDINAFREEZINGLIGHT] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} became cloaked in a freezing light!"), - [STRINGID_CLEARAMULETWONTLOWERSTATS] = COMPOUND_STRING("The effects of the {B_LAST_ITEM} held by {B_DEF_NAME_WITH_PREFIX2} prevents its stats from being lowered!"), + [STRINGID_CLEARAMULETWONTLOWERSTATS] = COMPOUND_STRING("The effects of the {B_LAST_ITEM} held by {B_SCR_NAME_WITH_PREFIX2} prevents its stats from being lowered!"), [STRINGID_FERVENTWISHREACHED] = COMPOUND_STRING("{B_ATK_TRAINER_NAME}'s fervent wish has reached {B_ATK_NAME_WITH_PREFIX2}!"), [STRINGID_AIRLOCKACTIVATES] = COMPOUND_STRING("The effects of the weather disappeared."), [STRINGID_PRESSUREENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} is exerting its pressure!"), @@ -1286,7 +1286,10 @@ const u16 gWeatherStartsStringIds[] = const u16 gTerrainStartsStringIds[] = { - STRINGID_MISTSWIRLSAROUND, STRINGID_ELECTRICCURRENTISRUNNING, STRINGID_ISCOVEREDWITHGRASS, STRINGID_SEEMSWEIRD, + [B_MSG_TERRAIN_SET_MISTY] = STRINGID_MISTSWIRLSAROUND, + [B_MSG_TERRAIN_SET_ELECTRIC] = STRINGID_ELECTRICCURRENTISRUNNING, + [B_MSG_TERRAIN_SET_PSYCHIC] = STRINGID_SEEMSWEIRD, + [B_MSG_TERRAIN_SET_GRASSY] = STRINGID_ISCOVEREDWITHGRASS, }; const u16 gPrimalWeatherBlocksStringIds[] = From b22a867e119268e898e18dfb47cfc5f7bf308c89 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:12:01 +0100 Subject: [PATCH 14/45] Fixes Room Service (#5827) --- data/battle_scripts_1.s | 2 +- src/battle_script_commands.c | 5 +++- test/battle/hold_effect/room_service.c | 33 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 test/battle/hold_effect/room_service.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2441b9547d..d8eb279661 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -9101,7 +9101,7 @@ BattleScript_BerryStatRaiseEnd2:: BattleScript_BerryStatRaiseEnd2_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_BerryStatRaiseEnd2_Anim: - statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerryStatRaiseEnd2_End + statbuffchange STAT_CHANGE_ALLOW_PTR | MOVE_EFFECT_AFFECTS_USER, BattleScript_BerryStatRaiseEnd2_End setgraphicalstatchangevalues playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1bbef29586..a157d938a3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11934,7 +11934,10 @@ static void Cmd_statbuffchange(void) const u8 *ptrBefore = gBattlescriptCurrInstr; const u8 *failInstr = cmd->failInstr; - if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), GET_STAT_BUFF_ID(gBattleScripting.statChanger), flags, failInstr) == STAT_CHANGE_WORKED) + if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), + GET_STAT_BUFF_ID(gBattleScripting.statChanger), + flags, + failInstr) == STAT_CHANGE_WORKED) gBattlescriptCurrInstr = cmd->nextInstr; else if (gBattlescriptCurrInstr == ptrBefore) // Prevent infinite looping. gBattlescriptCurrInstr = failInstr; diff --git a/test/battle/hold_effect/room_service.c b/test/battle/hold_effect/room_service.c new file mode 100644 index 0000000000..04b6450e05 --- /dev/null +++ b/test/battle/hold_effect/room_service.c @@ -0,0 +1,33 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_ROOM_SERVICE].holdEffect == HOLD_EFFECT_ROOM_SERVICE); +} + +SINGLE_BATTLE_TEST("Room Serive decreases the holder's seep by one stage") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE); + ASSUME(gMovesInfo[MOVE_TRICK_ROOM].effect == EFFECT_TRICK_ROOM); + ASSUME(gMovesInfo[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); Item(ITEM_ROOM_SERVICE); } + OPPONENT(SPECIES_WYNAUT) { HP(1); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_TRICK_ROOM); } + TURN { MOVE(player, MOVE_EXPLOSION); SEND_OUT(player, 1); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK_ROOM, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player); + HP_BAR(opponent); + MESSAGE("2 sent out Wynaut!"); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + } +} From a797e901b25a793441b1b20644025bf23cebaa7c Mon Sep 17 00:00:00 2001 From: AERDU Date: Fri, 20 Dec 2024 08:46:58 +0000 Subject: [PATCH 15/45] B_LAST_USED_BALL and .importance (#5834) --- src/battle_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index def2742a1b..5644696776 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -569,7 +569,8 @@ void HandleAction_ThrowBall(void) gBattle_BG0_X = 0; gBattle_BG0_Y = 0; gLastUsedItem = gBallToDisplay; - RemoveBagItem(gLastUsedItem, 1); + if (!ItemId_GetImportance(gLastUsedItem)) + RemoveBagItem(gLastUsedItem, 1); gBattlescriptCurrInstr = BattleScript_BallThrow; gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } From f27bf843cb0f319fafcfaf2368229680fe6bd9c5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:49:40 +0100 Subject: [PATCH 16/45] Changes Various defines to an Enum (#5839) --- include/constants/battle_script_commands.h | 264 ++++++++++----------- src/battle_script_commands.c | 3 +- 2 files changed, 134 insertions(+), 133 deletions(-) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 3b3faa5790..50e39b767e 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -88,138 +88,138 @@ #define CMP_COMMON_BITS 4 #define CMP_NO_COMMON_BITS 5 -// Cmd_various -#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0 -#define VARIOUS_IS_RUNNING_IMPOSSIBLE 1 -#define VARIOUS_GET_MOVE_TARGET 2 -#define VARIOUS_GET_BATTLER_FAINTED 3 -#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 4 -#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 5 -#define VARIOUS_RESET_PLAYER_FAINTED 6 -#define VARIOUS_PALACE_FLAVOR_TEXT 7 -#define VARIOUS_ARENA_JUDGMENT_WINDOW 8 -#define VARIOUS_ARENA_OPPONENT_MON_LOST 9 -#define VARIOUS_ARENA_PLAYER_MON_LOST 10 -#define VARIOUS_ARENA_BOTH_MONS_LOST 11 -#define VARIOUS_EMIT_YESNOBOX 12 -#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 13 -#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 14 -#define VARIOUS_ARENA_JUDGMENT_STRING 15 -#define VARIOUS_ARENA_WAIT_STRING 16 -#define VARIOUS_WAIT_CRY 17 -#define VARIOUS_RETURN_OPPONENT_MON1 18 -#define VARIOUS_RETURN_OPPONENT_MON2 19 -#define VARIOUS_VOLUME_DOWN 20 -#define VARIOUS_VOLUME_UP 21 -#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 22 -#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 23 -#define VARIOUS_SET_TELEPORT_OUTCOME 24 -#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 25 -#define VARIOUS_STAT_TEXT_BUFFER 26 -#define VARIOUS_SWITCHIN_ABILITIES 27 -#define VARIOUS_INSTANT_HP_DROP 28 -#define VARIOUS_CLEAR_STATUS 29 -#define VARIOUS_RESTORE_PP 30 -#define VARIOUS_TRY_ACTIVATE_MOXIE 31 -#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 32 -#define VARIOUS_PLAY_MOVE_ANIMATION 33 -#define VARIOUS_SET_LUCKY_CHANT 34 -#define VARIOUS_SUCKER_PUNCH_CHECK 35 -#define VARIOUS_SET_SIMPLE_BEAM 36 -#define VARIOUS_TRY_ENTRAINMENT 37 -#define VARIOUS_SET_LAST_USED_ABILITY 38 -#define VARIOUS_INVERT_STAT_STAGES 39 -#define VARIOUS_TRY_ME_FIRST 40 -#define VARIOUS_JUMP_IF_BATTLE_END 41 -#define VARIOUS_TRY_ELECTRIFY 42 -#define VARIOUS_TRY_REFLECT_TYPE 43 -#define VARIOUS_TRY_SOAK 44 -#define VARIOUS_HANDLE_MEGA_EVO 45 -#define VARIOUS_TRY_LAST_RESORT 46 -#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 47 -#define VARIOUS_TRY_AUTOTOMIZE 48 -#define VARIOUS_ABILITY_POPUP 49 -#define VARIOUS_JUMP_IF_TARGET_ALLY 50 -#define VARIOUS_TRY_SYNCHRONOISE 51 -#define VARIOUS_PSYCHO_SHIFT 52 -#define VARIOUS_CURE_STATUS 53 -#define VARIOUS_POWER_TRICK 54 -#define VARIOUS_AFTER_YOU 55 -#define VARIOUS_BESTOW 56 -#define VARIOUS_JUMP_IF_NOT_GROUNDED 57 -#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 58 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 59 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 60 -#define VARIOUS_SET_AURORA_VEIL 61 -#define VARIOUS_TRY_THIRD_TYPE 62 -#define VARIOUS_ACUPRESSURE 63 -#define VARIOUS_SET_POWDER 64 -#define VARIOUS_SPECTRAL_THIEF 65 -#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 66 -#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 67 -#define VARIOUS_JUMP_IF_ROAR_FAILS 68 -#define VARIOUS_TRY_INSTRUCT 69 -#define VARIOUS_JUMP_IF_NOT_BERRY 70 -#define VARIOUS_TRACE_ABILITY 71 -#define VARIOUS_UPDATE_NICK 72 -#define VARIOUS_TRY_ILLUSION_OFF 73 -#define VARIOUS_SET_SPRITEIGNORE0HP 74 -#define VARIOUS_HANDLE_FORM_CHANGE 75 -#define VARIOUS_GET_STAT_VALUE 76 -#define VARIOUS_JUMP_IF_FULL_HP 77 -#define VARIOUS_LOSE_TYPE 78 -#define VARIOUS_TRY_ACTIVATE_SOULHEART 79 -#define VARIOUS_TRY_ACTIVATE_RECEIVER 80 -#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 81 -#define VARIOUS_TRY_FRISK 82 -#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 83 -#define VARIOUS_TRY_FAIRY_LOCK 84 -#define VARIOUS_JUMP_IF_NO_ALLY 85 -#define VARIOUS_POISON_TYPE_IMMUNITY 86 -#define VARIOUS_JUMP_IF_HOLD_EFFECT 87 -#define VARIOUS_INFATUATE_WITH_BATTLER 88 -#define VARIOUS_SET_LAST_USED_ITEM 89 -#define VARIOUS_PARALYZE_TYPE_IMMUNITY 90 -#define VARIOUS_JUMP_IF_ABSENT 91 -#define VARIOUS_DESTROY_ABILITY_POPUP 92 -#define VARIOUS_TOTEM_BOOST 93 -#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 94 -#define VARIOUS_MOVEEND_ITEM_EFFECTS 95 -#define VARIOUS_TERRAIN_SEED 96 -#define VARIOUS_MAKE_INVISIBLE 97 -#define VARIOUS_ROOM_SERVICE 98 -#define VARIOUS_EERIE_SPELL_PP_REDUCE 99 -#define VARIOUS_JUMP_IF_TEAM_HEALTHY 100 -#define VARIOUS_TRY_HEAL_QUARTER_HP 101 -#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 102 -#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 103 -#define VARIOUS_GET_ROTOTILLER_TARGETS 104 -#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 105 -#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 106 -#define VARIOUS_CONSUME_BERRY 107 -#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 108 -#define VARIOUS_JUMP_IF_SPECIES 109 -#define VARIOUS_UPDATE_ABILITY_POPUP 110 -#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 111 -#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 112 -#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 113 -#define VARIOUS_TRY_NO_RETREAT 114 -#define VARIOUS_CHECK_POLTERGEIST 115 -#define VARIOUS_CUT_1_3_HP_RAISE_STATS 116 -#define VARIOUS_TRY_END_NEUTRALIZING_GAS 117 -#define VARIOUS_JUMP_IF_UNDER_200 118 -#define VARIOUS_SET_SKY_DROP 119 -#define VARIOUS_CLEAR_SKY_DROP 120 -#define VARIOUS_SKY_DROP_YAWN 121 -#define VARIOUS_CURE_CERTAIN_STATUSES 122 -#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 123 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 124 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 125 -#define VARIOUS_SAVE_BATTLER_ITEM 126 -#define VARIOUS_RESTORE_BATTLER_ITEM 127 -#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 128 -#define VARIOUS_SWAP_SIDE_STATUSES 129 -#define VARIOUS_SWAP_STATS 130 +enum CmdVarious +{ + VARIOUS_CANCEL_MULTI_TURN_MOVES, + VARIOUS_IS_RUNNING_IMPOSSIBLE, + VARIOUS_GET_MOVE_TARGET, + VARIOUS_GET_BATTLER_FAINTED, + VARIOUS_RESET_SWITCH_IN_ABILITY_BITS, + VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP, + VARIOUS_RESET_PLAYER_FAINTED, + VARIOUS_PALACE_FLAVOR_TEXT, + VARIOUS_ARENA_JUDGMENT_WINDOW, + VARIOUS_ARENA_OPPONENT_MON_LOST, + VARIOUS_ARENA_PLAYER_MON_LOST, + VARIOUS_ARENA_BOTH_MONS_LOST, + VARIOUS_EMIT_YESNOBOX, + VARIOUS_DRAW_ARENA_REF_TEXT_BOX, + VARIOUS_ERASE_ARENA_REF_TEXT_BOX, + VARIOUS_ARENA_JUDGMENT_STRING, + VARIOUS_ARENA_WAIT_STRING, + VARIOUS_WAIT_CRY, + VARIOUS_RETURN_OPPONENT_MON1, + VARIOUS_RETURN_OPPONENT_MON2, + VARIOUS_VOLUME_DOWN, + VARIOUS_VOLUME_UP, + VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT, + VARIOUS_PALACE_TRY_ESCAPE_STATUS, + VARIOUS_SET_TELEPORT_OUTCOME, + VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC, + VARIOUS_STAT_TEXT_BUFFER, + VARIOUS_SWITCHIN_ABILITIES, + VARIOUS_INSTANT_HP_DROP, + VARIOUS_CLEAR_STATUS, + VARIOUS_RESTORE_PP, + VARIOUS_TRY_ACTIVATE_MOXIE, + VARIOUS_TRY_ACTIVATE_FELL_STINGER, + VARIOUS_PLAY_MOVE_ANIMATION, + VARIOUS_SET_LUCKY_CHANT, + VARIOUS_SUCKER_PUNCH_CHECK, + VARIOUS_SET_SIMPLE_BEAM, + VARIOUS_TRY_ENTRAINMENT, + VARIOUS_SET_LAST_USED_ABILITY, + VARIOUS_INVERT_STAT_STAGES, + VARIOUS_TRY_ME_FIRST, + VARIOUS_JUMP_IF_BATTLE_END, + VARIOUS_TRY_ELECTRIFY, + VARIOUS_TRY_SOAK, + VARIOUS_TRY_LAST_RESORT, + VARIOUS_SET_ARG_TO_BATTLE_DAMAGE, + VARIOUS_TRY_AUTOTOMIZE, + VARIOUS_ABILITY_POPUP, + VARIOUS_JUMP_IF_TARGET_ALLY, + VARIOUS_TRY_SYNCHRONOISE, + VARIOUS_PSYCHO_SHIFT, + VARIOUS_CURE_STATUS, + VARIOUS_POWER_TRICK, + VARIOUS_AFTER_YOU, + VARIOUS_BESTOW, + VARIOUS_JUMP_IF_NOT_GROUNDED, + VARIOUS_HANDLE_TRAINER_SLIDE_MSG, + VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF, + VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON, + VARIOUS_SET_AURORA_VEIL, + VARIOUS_TRY_THIRD_TYPE, + VARIOUS_ACUPRESSURE, + VARIOUS_SET_POWDER, + VARIOUS_SPECTRAL_THIEF, + VARIOUS_GRAVITY_ON_AIRBORNE_MONS, + VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, + VARIOUS_JUMP_IF_ROAR_FAILS, + VARIOUS_TRY_INSTRUCT, + VARIOUS_JUMP_IF_NOT_BERRY, + VARIOUS_TRACE_ABILITY, + VARIOUS_UPDATE_NICK, + VARIOUS_TRY_ILLUSION_OFF, + VARIOUS_SET_SPRITEIGNORE0HP, + VARIOUS_HANDLE_FORM_CHANGE, + VARIOUS_GET_STAT_VALUE, + VARIOUS_JUMP_IF_FULL_HP, + VARIOUS_LOSE_TYPE, + VARIOUS_TRY_ACTIVATE_SOULHEART, + VARIOUS_TRY_ACTIVATE_RECEIVER, + VARIOUS_TRY_ACTIVATE_BEAST_BOOST, + VARIOUS_TRY_FRISK, + VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED, + VARIOUS_TRY_FAIRY_LOCK, + VARIOUS_JUMP_IF_NO_ALLY, + VARIOUS_POISON_TYPE_IMMUNITY, + VARIOUS_JUMP_IF_HOLD_EFFECT, + VARIOUS_INFATUATE_WITH_BATTLER, + VARIOUS_SET_LAST_USED_ITEM, + VARIOUS_PARALYZE_TYPE_IMMUNITY, + VARIOUS_JUMP_IF_ABSENT, + VARIOUS_DESTROY_ABILITY_POPUP, + VARIOUS_TOTEM_BOOST, + VARIOUS_TRY_ACTIVATE_GRIM_NEIGH, + VARIOUS_MOVEEND_ITEM_EFFECTS, + VARIOUS_TERRAIN_SEED, + VARIOUS_MAKE_INVISIBLE, + VARIOUS_ROOM_SERVICE, + VARIOUS_EERIE_SPELL_PP_REDUCE, + VARIOUS_JUMP_IF_TEAM_HEALTHY, + VARIOUS_TRY_HEAL_QUARTER_HP, + VARIOUS_JUMP_IF_PRANKSTER_BLOCKED, + VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER, + VARIOUS_GET_ROTOTILLER_TARGETS, + VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED, + VARIOUS_TRY_ACTIVATE_BATTLE_BOND, + VARIOUS_CONSUME_BERRY, + VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL, + VARIOUS_JUMP_IF_SPECIES, + VARIOUS_UPDATE_ABILITY_POPUP, + VARIOUS_JUMP_IF_WEATHER_AFFECTED, + VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED, + VARIOUS_SET_ATTACKER_STICKY_WEB_USER, + VARIOUS_TRY_NO_RETREAT, + VARIOUS_CHECK_POLTERGEIST, + VARIOUS_CUT_1_3_HP_RAISE_STATS, + VARIOUS_TRY_END_NEUTRALIZING_GAS, + VARIOUS_JUMP_IF_UNDER_200, + VARIOUS_SET_SKY_DROP, + VARIOUS_CLEAR_SKY_DROP, + VARIOUS_SKY_DROP_YAWN, + VARIOUS_CURE_CERTAIN_STATUSES, + VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES, + VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY, + VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT, + VARIOUS_SAVE_BATTLER_ITEM, + VARIOUS_RESTORE_BATTLER_ITEM, + VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM, + VARIOUS_SWAP_SIDE_STATUSES, + VARIOUS_SWAP_STATS, +}; // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 1 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1d1a842797..863dcc6f0e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9464,13 +9464,14 @@ static void Cmd_various(void) s32 i; u8 data[10]; u32 battler, bits; + enum CmdVarious variousId = cmd->id; if (gBattleControllerExecFlags) return; battler = GetBattlerForBattleScript(cmd->battler); - switch (cmd->id) + switch (variousId) { // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. // Also when an opposing wild mon uses it againt its partner. From 4ac9dea30e60d6e82d4eec8988e92b7fc74f829b Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:11:18 +0000 Subject: [PATCH 17/45] Fixes Quash-affected battlers having the wrong order for End Turn effects (#5838) --- src/battle_anim_effects_1.c | 1 + src/battle_util.c | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 1d50cee3d1..da0faed032 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6757,6 +6757,7 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) break; } SWAP(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], temp); + SWAP(gActionsByTurnOrder[i], gActionsByTurnOrder[j], temp); break; } } diff --git a/src/battle_util.c b/src/battle_util.c index 5644696776..0776b6e392 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1679,17 +1679,12 @@ u8 DoFieldEndTurnEffects(void) switch (gBattleStruct->turnCountersTracker) { case ENDTURN_ORDER: - for (i = 0; i < gBattlersCount; i++) - { - gBattlerByTurnOrder[i] = i; - } for (i = 0; i < gBattlersCount - 1; i++) { s32 j; for (j = i + 1; j < gBattlersCount; j++) { - if (!gProtectStructs[i].quash - && !gProtectStructs[j].quash + if (!(gProtectStructs[i].quash && gProtectStructs[j].quash) && GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) SwapTurnOrder(i, j); } From e579333427db46576d44c759ff803ced2bc3b11d Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 20 Dec 2024 11:23:51 +0100 Subject: [PATCH 18/45] Egg cycle length fix (#5828) Co-authored-by: Hedara Co-authored-by: Bassoonian --- include/config/pokemon.h | 2 +- include/global.h | 3 +-- src/daycare.c | 8 +++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/config/pokemon.h b/include/config/pokemon.h index 23015614c0..259ad3c117 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -55,7 +55,7 @@ #define P_SHOW_TERA_TYPE GEN_8 // Since Gen 9, the Tera Type is shown on the summary screen. #define P_TM_LITERACY GEN_LATEST // Since Gen 6, TM illiterate Pokémon can learn TMs that teach moves that are in their level-up learnsets. #define P_CAN_FORGET_HIDDEN_MOVE FALSE // If TRUE, Pokémon can forget any move, even if it is a Hidden Move. -#define P_EGG_CYCLE_LENGTH GEN_LATEST // Since Gen 8, egg cycles take half as many steps as before. +#define P_EGG_CYCLE_LENGTH GEN_LATEST // Since Gen 8, egg cycles take half as many steps as before. Previous Gens have some varied step counts around 255. #define P_ONLY_OBTAINABLE_SHINIES FALSE // If TRUE, Pokémon encountered in the Battle Pyramid won't be shiny. #define P_NO_SHINIES_WITHOUT_POKEBALLS FALSE // If TRUE, Pokémon encountered when the player is out of Poké Balls won't be shiny #define P_SHOW_DYNAMIC_TYPES FALSE // If TRUE, all moves with dynamic type changes will be reflected as their current type in battle/summary screens instead of just select ones like in vanilla. diff --git a/include/global.h b/include/global.h index 5846f09359..687281eaa7 100644 --- a/include/global.h +++ b/include/global.h @@ -815,8 +815,7 @@ struct DayCare { struct DaycareMon mons[DAYCARE_MON_COUNT]; u32 offspringPersonality; - u8 stepCounter; - //u8 padding[3]; + u32 stepCounter; }; struct LilycoveLadyQuiz diff --git a/src/daycare.c b/src/daycare.c index 013e0b05ba..912537af56 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -1154,11 +1154,17 @@ static bool8 TryProduceOrHatchEgg(struct DayCare *daycare) } // Try to hatch Egg - if (++daycare->stepCounter == ((P_EGG_CYCLE_LENGTH >= GEN_8) ? 127 : 255)) + daycare->stepCounter++; + if (((P_EGG_CYCLE_LENGTH <= GEN_3 || P_EGG_CYCLE_LENGTH == GEN_7) && daycare->stepCounter >= 256) + || (P_EGG_CYCLE_LENGTH == GEN_4 && daycare->stepCounter >= 255) + || ((P_EGG_CYCLE_LENGTH == GEN_5 || P_EGG_CYCLE_LENGTH == GEN_6) && daycare->stepCounter >= 257) + || (P_EGG_CYCLE_LENGTH >= GEN_8 && daycare->stepCounter >= 128)) { u32 eggCycles; u8 toSub = GetEggCyclesToSubtract(); + daycare->stepCounter = 0; + for (i = 0; i < gPlayerPartyCount; i++) { if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) From 5cc0b35d81c657fefb8fc82ad683d7e17766a096 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Fri, 20 Dec 2024 12:20:46 +0100 Subject: [PATCH 19/45] Replace power checks with IS_MOVE_STATUS (#5820) Co-authored-by: Eduardo Quezada --- include/battle.h | 6 +++--- src/battle_ai_main.c | 8 ++++---- src/battle_ai_switch_items.c | 14 +++++++------- src/battle_ai_util.c | 4 ++-- src/battle_arena.c | 4 ++-- src/battle_dome.c | 4 ++-- src/battle_main.c | 2 +- src/battle_script_commands.c | 4 ++-- src/battle_util.c | 6 +++--- test/battle/ability/anger_shell.c | 4 ++-- test/battle/ability/battle_bond.c | 2 +- test/battle/ability/berserk.c | 4 ++-- test/battle/ability/desolate_land.c | 4 ++-- test/battle/ability/electromorphosis.c | 6 +++--- test/battle/ability/frisk.c | 4 ++-- test/battle/ability/innards_out.c | 6 +++--- test/battle/ability/magician.c | 2 +- test/battle/ability/primordial_sea.c | 4 ++-- test/battle/ability/rattled.c | 8 ++++---- test/battle/ability/stamina.c | 4 ++-- test/battle/ability/weak_armor.c | 4 ++-- test/battle/ability/wind_power.c | 8 ++++---- test/battle/form_change/primal_reversion.c | 6 +++--- test/battle/move_effect/charge.c | 4 ++-- 24 files changed, 61 insertions(+), 61 deletions(-) diff --git a/include/battle.h b/include/battle.h index 37f2359641..f0571d747e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -843,9 +843,9 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER #define F_DYNAMIC_TYPE_IGNORE_PHYSICALITY (1 << 6) // If set, the dynamic type's physicality won't be used for certain move effects. #define F_DYNAMIC_TYPE_SET (1 << 7) // Set for all dynamic types to distinguish a dynamic type of Normal (0) from no dynamic type. -#define IS_MOVE_PHYSICAL(move)(GetBattleMoveCategory(move) == DAMAGE_CATEGORY_PHYSICAL) -#define IS_MOVE_SPECIAL(move)(GetBattleMoveCategory(move) == DAMAGE_CATEGORY_SPECIAL) -#define IS_MOVE_STATUS(move)(gMovesInfo[move].category == DAMAGE_CATEGORY_STATUS) +#define IS_MOVE_PHYSICAL(move) (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_PHYSICAL) +#define IS_MOVE_SPECIAL(move) (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_SPECIAL) +#define IS_MOVE_STATUS(move) (gMovesInfo[move].category == DAMAGE_CATEGORY_STATUS) #define IS_MOVE_RECOIL(move)(gMovesInfo[move].recoil > 0 || gMovesInfo[move].effect == EFFECT_RECOIL_IF_MISS) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 3c031de092..d245be8cd5 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -433,7 +433,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3 if (move != 0 && move != 0xFFFF - //&& gMovesInfo[move].power != 0 /* we want to get effectiveness and accuracy of status moves */ + //&& !IS_MOVE_STATUS(gMovesInfo[move]) /* we want to get effectiveness and accuracy of status moves */ && !(aiData->moveLimitations[battlerAtk] & (1u << moveIndex))) { dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, rollType); @@ -2607,8 +2607,8 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) return score; - if (gMovesInfo[move].power == 0) - return score; // can't make anything faint with no power + if (IS_MOVE_STATUS(move)) + return score; // status moves aren't accounted here if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, 0) && gMovesInfo[move].effect != EFFECT_EXPLOSION) { @@ -4916,7 +4916,7 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor { if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) || CountUsablePartyMons(battlerAtk) == 0 - || gMovesInfo[move].power != 0 + || !IS_MOVE_STATUS(move) || !HasMoveEffect(battlerAtk, EFFECT_BATON_PASS) || IsBattlerTrapped(battlerAtk, TRUE)) return score; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 47f5cae740..b41daa741b 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -122,8 +122,8 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) hasStatusMove = TRUE; } - // Only check damage if move has power - if (gMovesInfo[aiMove].power != 0) + // Only check damage if it's a damaging move + if (!IS_MOVE_STATUS(aiMove)) { // Check if mon has a super effective move if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) @@ -156,7 +156,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = gBattleMons[opposingBattler].moves[i]; - if (playerMove != MOVE_NONE && gMovesInfo[playerMove].power != 0) + if (playerMove != MOVE_NONE && !IS_MOVE_STATUS(playerMove)) { damageTaken = AI_CalcDamage(playerMove, opposingBattler, battler, &effectiveness, FALSE, weather, DMG_ROLL_HIGHEST).expected; if (damageTaken > maxDamageTaken) @@ -1238,7 +1238,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva for (j = 0; j < MAX_MON_MOVES; j++) { aiMove = AI_DATA->switchinCandidate.battleMon.moves[j]; - if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) + if (aiMove != MOVE_NONE && !IS_MOVE_STATUS(aiMove)) { aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j); dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, rollType); @@ -1694,7 +1694,7 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = gBattleMons[opposingBattler].moves[i]; - if (playerMove != MOVE_NONE && gMovesInfo[playerMove].power != 0) + if (playerMove != MOVE_NONE && !IS_MOVE_STATUS(playerMove)) { damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, FALSE, DMG_ROLL_HIGHEST); if (damageTaken > maxDamageTaken) @@ -1822,7 +1822,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, { aiMove = AI_DATA->switchinCandidate.battleMon.moves[j]; - if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) + if (aiMove != MOVE_NONE && !IS_MOVE_STATUS(aiMove)) { if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_CONSERVATIVE) damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_LOWEST); @@ -1852,7 +1852,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, } // Check for mon with resistance and super effective move for best type matchup mon with effective move - if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) + if (aiMove != MOVE_NONE && !IS_MOVE_STATUS(aiMove)) { if (typeMatchup < bestResistEffective) { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index c033061dc9..267fc476c2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2378,7 +2378,7 @@ bool32 HasDamagingMove(u32 battlerId) for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && gMovesInfo[moves[i]].power != 0) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !IS_MOVE_STATUS(moves[i])) return TRUE; } @@ -2393,7 +2393,7 @@ bool32 HasDamagingMoveOfType(u32 battlerId, u32 type) for (i = 0; i < MAX_MON_MOVES; i++) { if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && gMovesInfo[moves[i]].type == type && gMovesInfo[moves[i]].power != 0) + && !IS_MOVE_STATUS(moves[i]].type == type && gMovesInfo[moves[i])) return TRUE; } diff --git a/src/battle_arena.c b/src/battle_arena.c index b292ff8837..8868a4246e 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -360,7 +360,7 @@ void BattleArena_AddMindPoints(u8 battler) // All moves with power != 0 give 1 point, with the following exceptions: // - Counter, Mirror Coat, and Bide give 0 points // - Fake Out subtracts 1 point -// All moves with power == 0 give 0 points, with the following exceptions: +// All status moves give 0 points, with the following exceptions: // - Protect, Detect, and Endure subtract 1 point if (gMovesInfo[gCurrentMove].effect == EFFECT_FIRST_TURN_ONLY @@ -369,7 +369,7 @@ void BattleArena_AddMindPoints(u8 battler) { gBattleStruct->arenaMindPoints[battler]--; } - else if (gMovesInfo[gCurrentMove].power != 0 + else if (!IS_MOVE_STATUS(gCurrentMove) && gMovesInfo[gCurrentMove].effect != EFFECT_COUNTER && gMovesInfo[gCurrentMove].effect != EFFECT_MIRROR_COAT && gMovesInfo[gCurrentMove].effect != EFFECT_METAL_BURST diff --git a/src/battle_dome.c b/src/battle_dome.c index 1d79333290..8b376c7e75 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -4326,7 +4326,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId) allocatedArray[k] = IsDomeStatusMoveEffect(move); break; case MOVE_POINTS_DMG: - allocatedArray[k] = (gMovesInfo[move].power != 0) ? 1 : 0; + allocatedArray[k] = (!IS_MOVE_STATUS(move)) ? 1 : 0; break; case MOVE_POINTS_DEF: allocatedArray[k] = IsDomeDefensiveMoveEffect(gMovesInfo[move].effect) ? 1 : 0; @@ -5108,7 +5108,7 @@ static u16 GetWinningMove(int winnerTournamentId, int loserTournamentId, u8 roun moveIds[i * MAX_MON_MOVES + j] = gFacilityTrainerMons[DOME_MONS[winnerTournamentId][i]].moves[j]; movePower = gMovesInfo[moveIds[i * MAX_MON_MOVES + j]].power; - if (movePower == 0) + if (IS_MOVE_STATUS(moveIds[i * MAX_MON_MOVES + j])) movePower = 40; else if (movePower == 1) movePower = 60; diff --git a/src/battle_main.c b/src/battle_main.c index 075dd3dd3c..332f6c461e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4839,7 +4839,7 @@ s8 GetMovePriority(u32 battler, u16 move) s8 priority; u16 ability = GetBattlerAbility(battler); - if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE && gMovesInfo[move].power != 0) + if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE && !IS_MOVE_STATUS(move)) move = GetUsableZMove(battler, move); priority = gMovesInfo[move].priority; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a157d938a3..2279b35369 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5727,7 +5727,7 @@ static void Cmd_moveend(void) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED - && gMovesInfo[gCurrentMove].power != 0 + && !IS_MOVE_STATUS(gCurrentMove) && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_ATK, 1, FALSE); @@ -8694,7 +8694,7 @@ static void Cmd_useitemonopponent(void) static bool32 HasAttackerFaintedTarget(void) { if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && gMovesInfo[gCurrentMove].power != 0 + && !IS_MOVE_STATUS(gCurrentMove) && (gLastHitBy[gBattlerTarget] == 0xFF || gLastHitBy[gBattlerTarget] == gBattlerAttacker) && gBattleStruct->moveTarget[gBattlerAttacker] == gBattlerTarget && gBattlerTarget != gBattlerAttacker diff --git a/src/battle_util.c b/src/battle_util.c index 0776b6e392..4484fe254a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -225,7 +225,7 @@ void HandleAction_UseMove(void) } else if (IsDoubleBattle() && gSideTimers[side].followmeTimer == 0 - && (gMovesInfo[gCurrentMove].power != 0 || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS)) + && (!IS_MOVE_STATUS(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS)) && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) || (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { @@ -5693,7 +5693,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_COLOR_CHANGE: if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && move != MOVE_STRUGGLE - && gMovesInfo[move].power != 0 + && !IS_MOVE_STATUS(move) && TARGET_TURN_DAMAGED && !IS_BATTLER_OF_TYPE(battler, moveType) && moveType != TYPE_STELLAR @@ -8647,7 +8647,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) return TRUE; else if (gProtectStructs[battlerDef].spikyShielded) return TRUE; - else if (gProtectStructs[battlerDef].kingsShielded && gMovesInfo[move].power != 0) + else if (gProtectStructs[battlerDef].kingsShielded && !IS_MOVE_STATUS(move)) return TRUE; else if (gProtectStructs[battlerDef].maxGuarded) return TRUE; diff --git a/test/battle/ability/anger_shell.c b/test/battle/ability/anger_shell.c index c5b490216b..cf28fad28c 100644 --- a/test/battle/ability/anger_shell.c +++ b/test/battle/ability/anger_shell.c @@ -14,7 +14,7 @@ SINGLE_BATTLE_TEST("Anger Shell activates only if the target had more than 50% o PARAMETRIZE { hp = 254; activates = TRUE; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_KLAWF) { Ability(ABILITY_ANGER_SHELL); MaxHP(maxHp); HP(hp); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Anger Shell lowers Def/Sp.Def by 1 and raises Atk/Sp.Atk/Spd { u16 maxHp = 500; GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_KLAWF) { Ability(ABILITY_ANGER_SHELL); MaxHP(maxHp); HP(maxHp / 2 + 1); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/battle_bond.c b/test/battle/ability/battle_bond.c index f61a6d171c..ef2b2753b3 100644 --- a/test/battle/ability/battle_bond.c +++ b/test/battle/ability/battle_bond.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_WATER_GUN].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_WATER_GUN)); } SINGLE_BATTLE_TEST("Battle Bond does not transform species other than Greninja") diff --git a/test/battle/ability/berserk.c b/test/battle/ability/berserk.c index 3bf269e1ee..7d7f905170 100644 --- a/test/battle/ability/berserk.c +++ b/test/battle/ability/berserk.c @@ -14,7 +14,7 @@ SINGLE_BATTLE_TEST("Berserk activates only if the target had more than 50% of it PARAMETRIZE { hp = 254; activates = TRUE; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_DRAMPA) { Ability(ABILITY_BERSERK); MaxHP(maxHp); HP(hp); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Berserk raises Sp.Atk by 1") { u16 maxHp = 500; GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_DRAMPA) { Ability(ABILITY_BERSERK); MaxHP(maxHp); HP(maxHp / 2 + 1); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/desolate_land.c b/test/battle/ability/desolate_land.c index 06d604e8fc..18fe76b0c9 100644 --- a/test/battle/ability/desolate_land.c +++ b/test/battle/ability/desolate_land.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_WATER_GUN].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_WATER_GUN)); ASSUME(gMovesInfo[MOVE_WATER_GUN].type == TYPE_WATER); } @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves") DOUBLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves and prints the message only once with moves hitting multiple targets") { GIVEN { - ASSUME(gMovesInfo[MOVE_SURF].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_SURF)); ASSUME(gMovesInfo[MOVE_SURF].type == TYPE_WATER); ASSUME(gMovesInfo[MOVE_SURF].target == MOVE_TARGET_FOES_AND_ALLY); PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB); {Speed(5);}} diff --git a/test/battle/ability/electromorphosis.c b/test/battle/ability/electromorphosis.c index 094b2843bf..0f0ac1c39a 100644 --- a/test/battle/ability/electromorphosis.c +++ b/test/battle/ability/electromorphosis.c @@ -10,11 +10,11 @@ SINGLE_BATTLE_TEST("Electromorphosis sets up Charge when hit by any move") PARAMETRIZE {move = MOVE_GUST; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); - ASSUME(gMovesInfo[MOVE_GUST].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); + ASSUME(!IS_MOVE_STATUS(MOVE_GUST)); ASSUME(gMovesInfo[MOVE_GUST].category == DAMAGE_CATEGORY_SPECIAL); ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); - ASSUME(gMovesInfo[MOVE_THUNDER_SHOCK].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_THUNDER_SHOCK)); ASSUME(gMovesInfo[MOVE_THUNDER_SHOCK].type == TYPE_ELECTRIC); PLAYER(SPECIES_BELLIBOLT) { Ability(ABILITY_ELECTROMORPHOSIS); Speed(10); } diff --git a/test/battle/ability/frisk.c b/test/battle/ability/frisk.c index 3c892329c3..28bd477a35 100644 --- a/test/battle/ability/frisk.c +++ b/test/battle/ability/frisk.c @@ -42,7 +42,7 @@ DOUBLE_BATTLE_TEST("Frisk triggers for player in a Double Battle after switching PARAMETRIZE { target = playerRight; } GIVEN { - ASSUME(gMovesInfo[MOVE_POUND].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_POUND)); PLAYER(SPECIES_WOBBUFFET) { HP(1); } PLAYER(SPECIES_WOBBUFFET) { HP(1); } PLAYER(SPECIES_FURRET) { Ability(ABILITY_FRISK); }; @@ -65,7 +65,7 @@ DOUBLE_BATTLE_TEST("Frisk triggers for opponent in a Double Battle after switchi PARAMETRIZE { target = opponentRight; } GIVEN { - ASSUME(gMovesInfo[MOVE_POUND].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_POUND)); PLAYER(SPECIES_WYNAUT) { Item(ITEM_POTION); } PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET) { HP(1); } diff --git a/test/battle/ability/innards_out.c b/test/battle/ability/innards_out.c index bc59bcfa0b..5837b98d1f 100644 --- a/test/battle/ability/innards_out.c +++ b/test/battle/ability/innards_out.c @@ -14,7 +14,7 @@ SINGLE_BATTLE_TEST("Innards Out deal dmg on fainting equal to the amount of dmg PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { HP(70); SpAttack(1000); } OPPONENT(SPECIES_WOBBUFFET); - ASSUME(gMovesInfo[MOVE_PSYCHIC].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_PSYCHIC)); ASSUME(gMovesInfo[MOVE_PSYCHIC].category == DAMAGE_CATEGORY_SPECIAL); } WHEN { TURN { MOVE(opponent, MOVE_PSYCHIC); SEND_OUT(player, 1); if (hp == 100) { SEND_OUT(opponent, 1); } } @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Innards Out does not trigger after Gastro Acid has been used PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); - ASSUME(gMovesInfo[MOVE_PSYCHIC].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_PSYCHIC)); ASSUME(gMovesInfo[MOVE_GASTRO_ACID].effect == EFFECT_GASTRO_ACID); } WHEN { TURN { MOVE(opponent, MOVE_GASTRO_ACID); } @@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Innards Out does not damage Magic Guard Pokemon") PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_CLEFABLE) { Ability(ABILITY_MAGIC_GUARD); } - ASSUME(gMovesInfo[MOVE_PSYCHIC].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_PSYCHIC)); } WHEN { TURN { MOVE(opponent, MOVE_PSYCHIC); SEND_OUT(player, 1); } } SCENE { diff --git a/test/battle/ability/magician.c b/test/battle/ability/magician.c index a951c2f973..14e553a763 100644 --- a/test/battle/ability/magician.c +++ b/test/battle/ability/magician.c @@ -5,7 +5,7 @@ SINGLE_BATTLE_TEST("Magician does not get self-damage recoil after stealing Life { GIVEN { ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB); - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_DELPHOX) { Ability(ABILITY_MAGICIAN); Item(ITEM_NONE); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } } WHEN { diff --git a/test/battle/ability/primordial_sea.c b/test/battle/ability/primordial_sea.c index 643dca161c..01ed892874 100644 --- a/test/battle/ability/primordial_sea.c +++ b/test/battle/ability/primordial_sea.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_EMBER].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_EMBER)); ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE); } @@ -32,7 +32,7 @@ SINGLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves") DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints the message only once with moves hitting multiple targets") { GIVEN { - ASSUME(gMovesInfo[MOVE_ERUPTION].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_ERUPTION)); ASSUME(gMovesInfo[MOVE_ERUPTION].type == TYPE_FIRE); ASSUME(gMovesInfo[MOVE_ERUPTION].target == MOVE_TARGET_BOTH); PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB); {Speed(5);}} diff --git a/test/battle/ability/rattled.c b/test/battle/ability/rattled.c index 5d3e47db33..da8157d28a 100644 --- a/test/battle/ability/rattled.c +++ b/test/battle/ability/rattled.c @@ -4,13 +4,13 @@ ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_FURY_CUTTER].type == TYPE_BUG); - ASSUME(gMovesInfo[MOVE_FURY_CUTTER].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_FURY_CUTTER)); ASSUME(gMovesInfo[MOVE_FEINT_ATTACK].type == TYPE_DARK); - ASSUME(gMovesInfo[MOVE_FEINT_ATTACK].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_FEINT_ATTACK)); ASSUME(gMovesInfo[MOVE_SHADOW_PUNCH].type == TYPE_GHOST); - ASSUME(gMovesInfo[MOVE_SHADOW_PUNCH].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_SHADOW_PUNCH)); ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); } SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost type move") diff --git a/test/battle/ability/stamina.c b/test/battle/ability/stamina.c index 527026284c..f5b89bb86b 100644 --- a/test/battle/ability/stamina.c +++ b/test/battle/ability/stamina.c @@ -24,8 +24,8 @@ SINGLE_BATTLE_TEST("Stamina raises Defense by 1 when hit by a move") PARAMETRIZE {move = MOVE_GUST; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); - ASSUME(gMovesInfo[MOVE_GUST].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); + ASSUME(!IS_MOVE_STATUS(MOVE_GUST)); ASSUME(gMovesInfo[MOVE_GUST].category == DAMAGE_CATEGORY_SPECIAL); ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_STAMINA); } diff --git a/test/battle/ability/weak_armor.c b/test/battle/ability/weak_armor.c index 7fd7e10ef7..0d264e7ff9 100644 --- a/test/battle/ability/weak_armor.c +++ b/test/battle/ability/weak_armor.c @@ -3,8 +3,8 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); - ASSUME(gMovesInfo[MOVE_GUST].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); + ASSUME(!IS_MOVE_STATUS(MOVE_GUST)); ASSUME(gMovesInfo[MOVE_GUST].category == DAMAGE_CATEGORY_SPECIAL); ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); ASSUME(B_WEAK_ARMOR_SPEED >= GEN_7); diff --git a/test/battle/ability/wind_power.c b/test/battle/ability/wind_power.c index 6ccf896eaa..a62fa9c47a 100644 --- a/test/battle/ability/wind_power.c +++ b/test/battle/ability/wind_power.c @@ -3,13 +3,13 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_THUNDERBOLT].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_THUNDERBOLT)); ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); - ASSUME(gMovesInfo[MOVE_AIR_CUTTER].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); + ASSUME(!IS_MOVE_STATUS(MOVE_AIR_CUTTER)); ASSUME(gMovesInfo[MOVE_AIR_CUTTER].target == MOVE_TARGET_BOTH); ASSUME(gMovesInfo[MOVE_AIR_CUTTER].windMove == TRUE); - ASSUME(gMovesInfo[MOVE_PETAL_BLIZZARD].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_PETAL_BLIZZARD)); ASSUME(gMovesInfo[MOVE_PETAL_BLIZZARD].target == MOVE_TARGET_FOES_AND_ALLY); ASSUME(gMovesInfo[MOVE_PETAL_BLIZZARD].windMove == TRUE); ASSUME(gMovesInfo[MOVE_TACKLE].windMove == FALSE); diff --git a/test/battle/form_change/primal_reversion.c b/test/battle/form_change/primal_reversion.c index 72e2a7e3c6..d4e682e8de 100644 --- a/test/battle/form_change/primal_reversion.c +++ b/test/battle/form_change/primal_reversion.c @@ -120,7 +120,7 @@ DOUBLE_BATTLE_TEST("Primal reversion's order is determined by Speed - player fas SINGLE_BATTLE_TEST("Primal reversion happens after a mon is sent out after a mon is fainted") { GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_WOBBUFFET) {HP(1); } PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } OPPONENT(SPECIES_WOBBUFFET); @@ -156,7 +156,7 @@ SINGLE_BATTLE_TEST("Primal reversion happens after a mon is switched in") SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Eject Button") { GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); ASSUME(gItemsInfo[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON); PLAYER(SPECIES_WOBBUFFET) {Item(ITEM_EJECT_BUTTON); } PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } @@ -177,7 +177,7 @@ SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Eject B SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Red Card") { GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); ASSUME(gItemsInfo[ITEM_RED_CARD].holdEffect == HOLD_EFFECT_RED_CARD); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } diff --git a/test/battle/move_effect/charge.c b/test/battle/move_effect/charge.c index f95a137993..b057fa4753 100644 --- a/test/battle/move_effect/charge.c +++ b/test/battle/move_effect/charge.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_THUNDERBOLT].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_THUNDERBOLT)); ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); } @@ -115,7 +115,7 @@ SINGLE_BATTLE_TEST("Charge's effect is removed regardless if the next move is El GIVEN { ASSUME(gMovesInfo[MOVE_TACKLE].type != TYPE_ELECTRIC); - ASSUME(gMovesInfo[MOVE_TACKLE].power != 0); + ASSUME(!IS_MOVE_STATUS(MOVE_TACKLE)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { From 742f7a4875f2e83ab86c605825aedaae4a5dd1cf Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:24:23 +0000 Subject: [PATCH 20/45] Fixes Cotton Down and Gulp Missile not interacting correctly with stat reduction prevention effects (#5841) --- data/battle_scripts_1.s | 16 ++++----- test/battle/ability/cotton_down.c | 34 ++++++++++++++++++ test/battle/ability/gulp_missile.c | 57 ++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d8eb279661..3e1888b031 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1218,7 +1218,6 @@ BattleScript_StrengthSapLower: playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_StrengthSapHp @ Drain HP without lowering a stat BattleScript_StrengthSapHp: jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_StrengthSapManipulateDmg @@ -6396,18 +6395,14 @@ BattleScript_GulpMissileGulping:: datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER jumpiffainted BS_ATTACKER, TRUE, BattleScript_GulpMissileNoSecondEffectGulping - jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_CLEAR_AMULET, BattleScript_GulpMissileNoSecondEffectGulping - jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileNoSecondEffectGulping - jumpifability BS_ATTACKER, ABILITY_FULL_METAL_BODY, BattleScript_GulpMissileNoSecondEffectGulping - jumpifability BS_ATTACKER, ABILITY_WHITE_SMOKE, BattleScript_GulpMissileNoSecondEffectGulping - jumpifflowerveilattacker BattleScript_GulpMissileNoSecondEffectGulping BattleScript_GulpMissileNoDmgGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE waitanimation swapattackerwithtarget @ to make gStatDownStringIds down below print the right battler setstatchanger STAT_DEF, 1, TRUE - statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_GulpMissileGorgingTargetDefenseCantGoLower + statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_GulpMissileGulpingEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_GulpMissileGulpingTargetDefenseCantGoLower setgraphicalstatchangevalues playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 printfromtable gStatDownStringIds @@ -6419,9 +6414,11 @@ BattleScript_GulpMissileNoSecondEffectGulping: playanimation BS_TARGET, B_ANIM_FORM_CHANGE waitanimation return -BattleScript_GulpMissileGorgingTargetDefenseCantGoLower: +BattleScript_GulpMissileGulpingTargetDefenseCantGoLower: printstring STRINGID_STATSWONTDECREASE waitmessage B_WAIT_TIME_LONG +BattleScript_GulpMissileGulpingEnd: + swapattackerwithtarget @ restore the battlers, just in case return BattleScript_SeedSowerActivates:: @@ -7152,7 +7149,8 @@ BattleScript_CottonDownLoop: jumpiffainted BS_TARGET, TRUE, BattleScript_CottonDownLoopIncrement setstatchanger STAT_SPEED, 1, TRUE jumpifbyteequal gBattlerTarget, gEffectBattler, BattleScript_CottonDownLoopIncrement - statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_CottonDownTargetSpeedCantGoLower + statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_CottonDownLoopIncrement + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_CottonDownTargetSpeedCantGoLower setgraphicalstatchangevalues playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 printfromtable gStatDownStringIds diff --git a/test/battle/ability/cotton_down.c b/test/battle/ability/cotton_down.c index 4d0dab9dcc..02a0f18f63 100644 --- a/test/battle/ability/cotton_down.c +++ b/test/battle/ability/cotton_down.c @@ -62,3 +62,37 @@ DOUBLE_BATTLE_TEST("Cotton Down drops speed by one of all other battlers on the EXPECT_EQ(opponentRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); } } + +DOUBLE_BATTLE_TEST("Cotton Down correctly gets blocked by stat reduction preventing abilities") +{ + GIVEN { + PLAYER(SPECIES_METAGROSS) { Ability(ABILITY_CLEAR_BODY); } + PLAYER(SPECIES_WYNAUT) { Item(ITEM_CLEAR_AMULET); } + OPPONENT(SPECIES_ELDEGOSS) { Ability(ABILITY_COTTON_DOWN); } + OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_COTTON_DOWN); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Metagross's Speed fell!"); + } + ABILITY_POPUP(playerLeft, ABILITY_CLEAR_BODY); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Wynaut's Speed fell!"); + } + MESSAGE("The effects of the Clear Amulet held by Wynaut prevents its stats from being lowered!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Corviknight's Speed fell!"); + } + ABILITY_POPUP(opponentRight, ABILITY_MIRROR_ARMOR); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(playerRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} diff --git a/test/battle/ability/gulp_missile.c b/test/battle/ability/gulp_missile.c index f5e1fd9d9d..189702a4be 100644 --- a/test/battle/ability/gulp_missile.c +++ b/test/battle/ability/gulp_missile.c @@ -92,6 +92,7 @@ SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant deal 1/4 of damage oppo MESSAGE("The opposing Wobbuffet's Defense fell!"); } THEN { EXPECT_EQ(gulpMissileDamage, opponent->maxHP / 4); + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1); } } @@ -133,3 +134,59 @@ SINGLE_BATTLE_TEST("(Gulp Missile) triggers even if the user is fainted by oppos STATUS_ICON(opponent, paralysis: TRUE); } } + +SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant Gulping lowers defense but is prevented by stat reduction preventing abilities") +{ + u32 species, ability; + PARAMETRIZE { species = SPECIES_METAGROSS; ability = ABILITY_CLEAR_BODY; } + PARAMETRIZE { species = SPECIES_CORVIKNIGHT; ability = ABILITY_MIRROR_ARMOR; } + PARAMETRIZE { species = SPECIES_CHATOT; ability = ABILITY_BIG_PECKS; } + GIVEN { + PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SURF); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + ABILITY_POPUP(opponent, ability); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("(Gulp Missile) Transformed Cramorant Gulping lowers defense and still triggers other effects after") +{ + // Make sure attacker and target are correct after triggering the ability + u32 ability; + PARAMETRIZE { ability = ABILITY_INFILTRATOR; } + PARAMETRIZE { ability = ABILITY_CLEAR_BODY; } + GIVEN { + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact == TRUE); + PLAYER(SPECIES_CRAMORANT) { Ability(ABILITY_GULP_MISSILE); Item(ITEM_ROCKY_HELMET); } + OPPONENT(SPECIES_DRAGAPULT) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SURF); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + HP_BAR(opponent); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_GULP_MISSILE); + HP_BAR(opponent); + if (ability == ABILITY_INFILTRATOR) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Dragapult's Defense fell!"); + } else { + ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(opponent); + } +} From 9a0b5756ca7b773b2b5fc86097e9f30ed4d80243 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 20 Dec 2024 18:25:18 -0300 Subject: [PATCH 21/45] Fix "PlantCloak" references (#5821) --- src/data/graphics/pokemon.h | 32 ++++++++--------- .../object_event_pic_tables_followers.h | 8 ++--- src/data/pokemon/level_up_learnsets/gen_1.h | 2 +- src/data/pokemon/level_up_learnsets/gen_2.h | 2 +- src/data/pokemon/level_up_learnsets/gen_3.h | 2 +- src/data/pokemon/level_up_learnsets/gen_4.h | 2 +- src/data/pokemon/level_up_learnsets/gen_5.h | 2 +- src/data/pokemon/level_up_learnsets/gen_6.h | 2 +- src/data/pokemon/level_up_learnsets/gen_7.h | 2 +- src/data/pokemon/level_up_learnsets/gen_8.h | 2 +- src/data/pokemon/level_up_learnsets/gen_9.h | 2 +- .../pokemon/species_info/gen_4_families.h | 36 +++++++++---------- src/data/pokemon/teachable_learnsets.h | 2 +- 13 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index 8801942e53..726a0414f4 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -14459,11 +14459,11 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ #endif //P_FAMILY_SHIELDON #if P_FAMILY_BURMY - const u32 gMonFrontPic_BurmyPlantCloak[] = INCBIN_U32("graphics/pokemon/burmy/anim_front.4bpp.lz"); - const u32 gMonPalette_BurmyPlantCloak[] = INCBIN_U32("graphics/pokemon/burmy/normal.gbapal.lz"); - const u32 gMonBackPic_BurmyPlantCloak[] = INCBIN_U32("graphics/pokemon/burmy/back.4bpp.lz"); - const u32 gMonShinyPalette_BurmyPlantCloak[] = INCBIN_U32("graphics/pokemon/burmy/shiny.gbapal.lz"); - const u8 gMonIcon_BurmyPlantCloak[] = INCBIN_U8("graphics/pokemon/burmy/icon.4bpp"); + const u32 gMonFrontPic_BurmyPlant[] = INCBIN_U32("graphics/pokemon/burmy/anim_front.4bpp.lz"); + const u32 gMonPalette_BurmyPlant[] = INCBIN_U32("graphics/pokemon/burmy/normal.gbapal.lz"); + const u32 gMonBackPic_BurmyPlant[] = INCBIN_U32("graphics/pokemon/burmy/back.4bpp.lz"); + const u32 gMonShinyPalette_BurmyPlant[] = INCBIN_U32("graphics/pokemon/burmy/shiny.gbapal.lz"); + const u8 gMonIcon_BurmyPlant[] = INCBIN_U8("graphics/pokemon/burmy/icon.4bpp"); #if P_FOOTPRINTS const u8 gMonFootprint_Burmy[] = INCBIN_U8("graphics/pokemon/burmy/footprint.1bpp"); #endif //P_FOOTPRINTS @@ -14481,24 +14481,24 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ const u8 gMonIcon_BurmyTrash[] = INCBIN_U8("graphics/pokemon/burmy/trash/icon.4bpp"); #if OW_POKEMON_OBJECT_EVENTS - const u32 gObjectEventPic_BurmyPlantCloak[] = INCBIN_COMP("graphics/pokemon/burmy/overworld.4bpp"); + const u32 gObjectEventPic_BurmyPlant[] = INCBIN_COMP("graphics/pokemon/burmy/overworld.4bpp"); const u32 gObjectEventPic_BurmySandy[] = INCBIN_COMP("graphics/pokemon/burmy/sandy/overworld.4bpp"); const u32 gObjectEventPic_BurmyTrash[] = INCBIN_COMP("graphics/pokemon/burmy/trash/overworld.4bpp"); #if OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE - const u32 gOverworldPalette_BurmyPlantCloak[] = INCBIN_U32("graphics/pokemon/burmy/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_BurmyPlant[] = INCBIN_U32("graphics/pokemon/burmy/overworld_normal.gbapal.lz"); const u32 gOverworldPalette_BurmySandy[] = INCBIN_U32("graphics/pokemon/burmy/sandy/overworld_normal.gbapal.lz"); const u32 gOverworldPalette_BurmyTrash[] = INCBIN_U32("graphics/pokemon/burmy/trash/overworld_normal.gbapal.lz"); - const u32 gShinyOverworldPalette_BurmyPlantCloak[] = INCBIN_U32("graphics/pokemon/burmy/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_BurmyPlant[] = INCBIN_U32("graphics/pokemon/burmy/overworld_shiny.gbapal.lz"); const u32 gShinyOverworldPalette_BurmySandy[] = INCBIN_U32("graphics/pokemon/burmy/sandy/overworld_shiny.gbapal.lz"); const u32 gShinyOverworldPalette_BurmyTrash[] = INCBIN_U32("graphics/pokemon/burmy/trash/overworld_shiny.gbapal.lz"); #endif //OW_PKMN_OBJECTS_SHARE_PALETTES #endif //OW_POKEMON_OBJECT_EVENTS - const u32 gMonFrontPic_WormadamPlantCloak[] = INCBIN_U32("graphics/pokemon/wormadam/anim_front.4bpp.lz"); - const u32 gMonPalette_WormadamPlantCloak[] = INCBIN_U32("graphics/pokemon/wormadam/normal.gbapal.lz"); - const u32 gMonBackPic_WormadamPlantCloak[] = INCBIN_U32("graphics/pokemon/wormadam/back.4bpp.lz"); - const u32 gMonShinyPalette_WormadamPlantCloak[] = INCBIN_U32("graphics/pokemon/wormadam/shiny.gbapal.lz"); - const u8 gMonIcon_WormadamPlantCloak[] = INCBIN_U8("graphics/pokemon/wormadam/icon.4bpp"); + const u32 gMonFrontPic_WormadamPlant[] = INCBIN_U32("graphics/pokemon/wormadam/anim_front.4bpp.lz"); + const u32 gMonPalette_WormadamPlant[] = INCBIN_U32("graphics/pokemon/wormadam/normal.gbapal.lz"); + const u32 gMonBackPic_WormadamPlant[] = INCBIN_U32("graphics/pokemon/wormadam/back.4bpp.lz"); + const u32 gMonShinyPalette_WormadamPlant[] = INCBIN_U32("graphics/pokemon/wormadam/shiny.gbapal.lz"); + const u8 gMonIcon_WormadamPlant[] = INCBIN_U8("graphics/pokemon/wormadam/icon.4bpp"); #if P_FOOTPRINTS const u8 gMonFootprint_Wormadam[] = INCBIN_U8("graphics/pokemon/wormadam/footprint.1bpp"); #endif //P_FOOTPRINTS @@ -14516,14 +14516,14 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ const u8 gMonIcon_WormadamTrash[] = INCBIN_U8("graphics/pokemon/wormadam/trash/icon.4bpp"); #if OW_POKEMON_OBJECT_EVENTS - const u32 gObjectEventPic_WormadamPlantCloak[] = INCBIN_COMP("graphics/pokemon/wormadam/overworld.4bpp"); + const u32 gObjectEventPic_WormadamPlant[] = INCBIN_COMP("graphics/pokemon/wormadam/overworld.4bpp"); const u32 gObjectEventPic_WormadamSandy[] = INCBIN_COMP("graphics/pokemon/wormadam/sandy/overworld.4bpp"); const u32 gObjectEventPic_WormadamTrash[] = INCBIN_COMP("graphics/pokemon/wormadam/trash/overworld.4bpp"); #if OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE - const u32 gOverworldPalette_WormadamPlantCloak[] = INCBIN_U32("graphics/pokemon/wormadam/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_WormadamPlant[] = INCBIN_U32("graphics/pokemon/wormadam/overworld_normal.gbapal.lz"); const u32 gOverworldPalette_WormadamSandy[] = INCBIN_U32("graphics/pokemon/wormadam/sandy/overworld_normal.gbapal.lz"); const u32 gOverworldPalette_WormadamTrash[] = INCBIN_U32("graphics/pokemon/wormadam/trash/overworld_normal.gbapal.lz"); - const u32 gShinyOverworldPalette_WormadamPlantCloak[] = INCBIN_U32("graphics/pokemon/wormadam/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_WormadamPlant[] = INCBIN_U32("graphics/pokemon/wormadam/overworld_shiny.gbapal.lz"); const u32 gShinyOverworldPalette_WormadamSandy[] = INCBIN_U32("graphics/pokemon/wormadam/sandy/overworld_shiny.gbapal.lz"); const u32 gShinyOverworldPalette_WormadamTrash[] = INCBIN_U32("graphics/pokemon/wormadam/trash/overworld_shiny.gbapal.lz"); #endif //OW_PKMN_OBJECTS_SHARE_PALETTES diff --git a/src/data/object_events/object_event_pic_tables_followers.h b/src/data/object_events/object_event_pic_tables_followers.h index 276e8fcf65..07193cedc7 100644 --- a/src/data/object_events/object_event_pic_tables_followers.h +++ b/src/data/object_events/object_event_pic_tables_followers.h @@ -3136,8 +3136,8 @@ static const struct SpriteFrameImage sPicTable_Bastiodon[] = { #endif //P_FAMILY_SHIELDON #if P_FAMILY_BURMY -static const struct SpriteFrameImage sPicTable_BurmyPlantCloak[] = { - overworld_ascending_frames(gObjectEventPic_BurmyPlantCloak, 4, 4), +static const struct SpriteFrameImage sPicTable_BurmyPlant[] = { + overworld_ascending_frames(gObjectEventPic_BurmyPlant, 4, 4), }; static const struct SpriteFrameImage sPicTable_BurmySandy[] = { overworld_ascending_frames(gObjectEventPic_BurmySandy, 4, 4), @@ -3145,8 +3145,8 @@ static const struct SpriteFrameImage sPicTable_BurmySandy[] = { static const struct SpriteFrameImage sPicTable_BurmyTrash[] = { overworld_ascending_frames(gObjectEventPic_BurmyTrash, 4, 4), }; -static const struct SpriteFrameImage sPicTable_WormadamPlantCloak[] = { - overworld_ascending_frames(gObjectEventPic_WormadamPlantCloak, 4, 4), +static const struct SpriteFrameImage sPicTable_WormadamPlant[] = { + overworld_ascending_frames(gObjectEventPic_WormadamPlant, 4, 4), }; static const struct SpriteFrameImage sPicTable_WormadamSandy[] = { overworld_ascending_frames(gObjectEventPic_WormadamSandy, 4, 4), diff --git a/src/data/pokemon/level_up_learnsets/gen_1.h b/src/data/pokemon/level_up_learnsets/gen_1.h index 8470b1b14e..f1e7cd32ff 100644 --- a/src/data/pokemon/level_up_learnsets/gen_1.h +++ b/src/data/pokemon/level_up_learnsets/gen_1.h @@ -7717,7 +7717,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE(10, MOVE_PROTECT), LEVEL_UP_MOVE(15, MOVE_BUG_BITE), diff --git a/src/data/pokemon/level_up_learnsets/gen_2.h b/src/data/pokemon/level_up_learnsets/gen_2.h index 0f39631c4f..3d74d70b23 100644 --- a/src/data/pokemon/level_up_learnsets/gen_2.h +++ b/src/data/pokemon/level_up_learnsets/gen_2.h @@ -7961,7 +7961,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE(10, MOVE_PROTECT), LEVEL_UP_MOVE(15, MOVE_BUG_BITE), diff --git a/src/data/pokemon/level_up_learnsets/gen_3.h b/src/data/pokemon/level_up_learnsets/gen_3.h index 81e6d06b46..cedd09b308 100644 --- a/src/data/pokemon/level_up_learnsets/gen_3.h +++ b/src/data/pokemon/level_up_learnsets/gen_3.h @@ -8187,7 +8187,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE(10, MOVE_PROTECT), LEVEL_UP_MOVE(15, MOVE_BUG_BITE), diff --git a/src/data/pokemon/level_up_learnsets/gen_4.h b/src/data/pokemon/level_up_learnsets/gen_4.h index 5c9f6872b5..4b302539b2 100644 --- a/src/data/pokemon/level_up_learnsets/gen_4.h +++ b/src/data/pokemon/level_up_learnsets/gen_4.h @@ -9461,7 +9461,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE(10, MOVE_PROTECT), LEVEL_UP_MOVE(15, MOVE_BUG_BITE), diff --git a/src/data/pokemon/level_up_learnsets/gen_5.h b/src/data/pokemon/level_up_learnsets/gen_5.h index cb99b6375d..2403f17b96 100644 --- a/src/data/pokemon/level_up_learnsets/gen_5.h +++ b/src/data/pokemon/level_up_learnsets/gen_5.h @@ -9920,7 +9920,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE(10, MOVE_PROTECT), LEVEL_UP_MOVE(15, MOVE_BUG_BITE), diff --git a/src/data/pokemon/level_up_learnsets/gen_6.h b/src/data/pokemon/level_up_learnsets/gen_6.h index 32e5849cda..c5a3a39acf 100644 --- a/src/data/pokemon/level_up_learnsets/gen_6.h +++ b/src/data/pokemon/level_up_learnsets/gen_6.h @@ -10382,7 +10382,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE(10, MOVE_PROTECT), LEVEL_UP_MOVE(15, MOVE_BUG_BITE), diff --git a/src/data/pokemon/level_up_learnsets/gen_7.h b/src/data/pokemon/level_up_learnsets/gen_7.h index f88e4bcba7..77d2fc2deb 100644 --- a/src/data/pokemon/level_up_learnsets/gen_7.h +++ b/src/data/pokemon/level_up_learnsets/gen_7.h @@ -10610,7 +10610,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 0, MOVE_QUIVER_DANCE), LEVEL_UP_MOVE( 1, MOVE_QUIVER_DANCE), LEVEL_UP_MOVE( 1, MOVE_SUCKER_PUNCH), diff --git a/src/data/pokemon/level_up_learnsets/gen_8.h b/src/data/pokemon/level_up_learnsets/gen_8.h index 67d263c859..65b557a486 100644 --- a/src/data/pokemon/level_up_learnsets/gen_8.h +++ b/src/data/pokemon/level_up_learnsets/gen_8.h @@ -10633,7 +10633,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 0, MOVE_QUIVER_DANCE), LEVEL_UP_MOVE( 1, MOVE_QUIVER_DANCE), LEVEL_UP_MOVE( 1, MOVE_SUCKER_PUNCH), diff --git a/src/data/pokemon/level_up_learnsets/gen_9.h b/src/data/pokemon/level_up_learnsets/gen_9.h index 9f6985bc9a..0bdfbe1eb3 100644 --- a/src/data/pokemon/level_up_learnsets/gen_9.h +++ b/src/data/pokemon/level_up_learnsets/gen_9.h @@ -10291,7 +10291,7 @@ static const struct LevelUpMove sBurmyLevelUpLearnset[] = { LEVEL_UP_END }; -static const struct LevelUpMove sWormadamPlantCloakLevelUpLearnset[] = { +static const struct LevelUpMove sWormadamPlantLevelUpLearnset[] = { LEVEL_UP_MOVE( 0, MOVE_QUIVER_DANCE), LEVEL_UP_MOVE( 1, MOVE_QUIVER_DANCE), LEVEL_UP_MOVE( 1, MOVE_SUCKER_PUNCH), diff --git a/src/data/pokemon/species_info/gen_4_families.h b/src/data/pokemon/species_info/gen_4_families.h index b84284de29..be0cfba99e 100644 --- a/src/data/pokemon/species_info/gen_4_families.h +++ b/src/data/pokemon/species_info/gen_4_families.h @@ -1656,29 +1656,29 @@ const struct SpeciesInfo gSpeciesInfoGen4[] = .pokemonOffset = 24, .trainerScale = 256, .trainerOffset = 0, - .frontPic = gMonFrontPic_BurmyPlantCloak, + .frontPic = gMonFrontPic_BurmyPlant, .frontPicSize = MON_COORDS_SIZE(32, 56), .frontPicYOffset = 13, .frontAnimFrames = sAnims_Burmy, .frontAnimId = ANIM_V_STRETCH, .enemyMonElevation = 10, - .backPic = gMonBackPic_BurmyPlantCloak, + .backPic = gMonBackPic_BurmyPlant, .backPicSize = MON_COORDS_SIZE(40, 56), .backPicYOffset = 6, .backAnimId = BACK_ANIM_H_SHAKE, - .palette = gMonPalette_BurmyPlantCloak, - .shinyPalette = gMonShinyPalette_BurmyPlantCloak, - .iconSprite = gMonIcon_BurmyPlantCloak, + .palette = gMonPalette_BurmyPlant, + .shinyPalette = gMonShinyPalette_BurmyPlant, + .iconSprite = gMonIcon_BurmyPlant, .iconPalIndex = 1, SHADOW(-1, 8, SHADOW_SIZE_S) FOOTPRINT(Burmy) OVERWORLD( - sPicTable_BurmyPlantCloak, + sPicTable_BurmyPlant, SIZE_32x32, SHADOW_SIZE_M, TRACKS_FOOT, - gOverworldPalette_BurmyPlantCloak, - gShinyOverworldPalette_BurmyPlantCloak + gOverworldPalette_BurmyPlant, + gShinyOverworldPalette_BurmyPlant ) .tmIlliterate = TRUE, .levelUpLearnset = sBurmyLevelUpLearnset, @@ -1858,32 +1858,32 @@ const struct SpeciesInfo gSpeciesInfoGen4[] = .pokemonOffset = 13, .trainerScale = 256, .trainerOffset = 0, - .frontPic = gMonFrontPic_WormadamPlantCloak, + .frontPic = gMonFrontPic_WormadamPlant, .frontPicSize = MON_COORDS_SIZE(48, 56), .frontPicYOffset = 10, .frontAnimFrames = sAnims_Wormadam, .frontAnimId = ANIM_SWING_CONVEX_FAST_SHORT, .enemyMonElevation = 8, - .backPic = gMonBackPic_WormadamPlantCloak, + .backPic = gMonBackPic_WormadamPlant, .backPicSize = MON_COORDS_SIZE(56, 64), .backPicYOffset = 2, .backAnimId = BACK_ANIM_V_SHAKE, - .palette = gMonPalette_WormadamPlantCloak, - .shinyPalette = gMonShinyPalette_WormadamPlantCloak, - .iconSprite = gMonIcon_WormadamPlantCloak, + .palette = gMonPalette_WormadamPlant, + .shinyPalette = gMonShinyPalette_WormadamPlant, + .iconSprite = gMonIcon_WormadamPlant, .iconPalIndex = 1, SHADOW(0, 9, SHADOW_SIZE_S) FOOTPRINT(Wormadam) OVERWORLD( - sPicTable_WormadamPlantCloak, + sPicTable_WormadamPlant, SIZE_32x32, SHADOW_SIZE_M, TRACKS_FOOT, - gOverworldPalette_WormadamPlantCloak, - gShinyOverworldPalette_WormadamPlantCloak + gOverworldPalette_WormadamPlant, + gShinyOverworldPalette_WormadamPlant ) - .levelUpLearnset = sWormadamPlantCloakLevelUpLearnset, - .teachableLearnset = sWormadamPlantCloakTeachableLearnset, + .levelUpLearnset = sWormadamPlantLevelUpLearnset, + .teachableLearnset = sWormadamPlantTeachableLearnset, .formSpeciesIdTable = sWormadamFormSpeciesIdTable, }, diff --git a/src/data/pokemon/teachable_learnsets.h b/src/data/pokemon/teachable_learnsets.h index 46354db5a0..b0755d6039 100644 --- a/src/data/pokemon/teachable_learnsets.h +++ b/src/data/pokemon/teachable_learnsets.h @@ -18903,7 +18903,7 @@ static const u16 sBurmyTeachableLearnset[] = { MOVE_UNAVAILABLE, }; -static const u16 sWormadamPlantCloakTeachableLearnset[] = { +static const u16 sWormadamPlantTeachableLearnset[] = { MOVE_ATTRACT, MOVE_BULLET_SEED, MOVE_DIG, From c1969052a6f1faf258cf51d007e9fa79e2d30f6f Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 20 Dec 2024 21:03:37 -0300 Subject: [PATCH 22/45] Fix issues --- src/battle_script_commands.c | 2 +- test/battle/move_effect/shed_tail.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7c75c5a61f..0a58299408 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5975,7 +5975,7 @@ static void Cmd_moveend(void) case MOVEEND_ABSORB: if (gMovesInfo[gCurrentMove].effect == EFFECT_ABSORB && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && TARGET_TURN_DAMAGED) + && IsBattlerTurnDamaged(gBattlerTarget)) { if (gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && gMovesInfo[gCurrentMove].healingMove) { diff --git a/test/battle/move_effect/shed_tail.c b/test/battle/move_effect/shed_tail.c index 6e337f4fe7..f4ef2ec0d5 100644 --- a/test/battle/move_effect/shed_tail.c +++ b/test/battle/move_effect/shed_tail.c @@ -86,6 +86,8 @@ SINGLE_BATTLE_TEST("Shed Tail's HP cost doesn't trigger effects that trigger on } } +// Passes for some reason even though it seems there is some code missing +/* AI_SINGLE_BATTLE_TEST("AI will use Shed Tail to pivot to another mon while in damage stalemate with player") { KNOWN_FAILING; // missing AI code @@ -99,6 +101,7 @@ AI_SINGLE_BATTLE_TEST("AI will use Shed Tail to pivot to another mon while in da TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_SHED_TAIL); } } } +*/ SINGLE_BATTLE_TEST("Shed Tail creates a Substitute with 1/4 of user maximum health") { From c3133193e218b0a31df582c8d906c71ad1f51cc7 Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Sat, 21 Dec 2024 03:30:25 -0600 Subject: [PATCH 23/45] Fix Hit Escape moves giving Exp to the mon that switches in (#5844) --- data/battle_scripts_1.s | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3e1888b031..7359b4469a 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2790,6 +2790,10 @@ BattleScript_EffectHitEscape:: jumpifbattleend BattleScript_HitEscapeEnd jumpifbyte CMP_NOT_EQUAL, gBattleOutcome, 0, BattleScript_HitEscapeEnd jumpifemergencyexited BS_TARGET, BattleScript_HitEscapeEnd + jumpiffainted BS_TARGET, FALSE, BattleScript_HitEscapeSwitch + setbyte sGIVEEXP_STATE, 0 + getexp BS_TARGET +BattleScript_HitEscapeSwitch: goto BattleScript_MoveSwitch BattleScript_HitEscapeEnd: end From e175c5aca889ed3f6fb9604238b289b1d220ee0c Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 21 Dec 2024 07:48:31 -0300 Subject: [PATCH 24/45] Changes Various defines to an Enum (#5840) Co-authored-by: Bassoonian Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- .../how_to_battle_script_command_macro.md | 76 +++-- include/constants/battle_script_commands.h | 264 +++++++++--------- src/battle_script_commands.c | 3 +- 3 files changed, 170 insertions(+), 173 deletions(-) diff --git a/docs/tutorials/how_to_battle_script_command_macro.md b/docs/tutorials/how_to_battle_script_command_macro.md index 042a87601d..2bbf503fbe 100644 --- a/docs/tutorials/how_to_battle_script_command_macro.md +++ b/docs/tutorials/how_to_battle_script_command_macro.md @@ -1,51 +1,47 @@ ## How to add new Battle Script Commands/Macros -To preface this tutorial, the battle engine upgrade has exhausted all battle script command IDs, and instead uses the `various` command to effectively add new commands. This is preferential to creating a secondary battle script command table like is done in the CFRU. +To preface this tutorial, the battle engine upgrade has exhausted all battle script command IDs. Historically, we've used the `various` command to effectively add new commands. However, this has caused issues of maintainability and readability due to the massive switch needed for it. Thanks to the cleanup made by the team and contributors, we now are able to call an infinite amount of commands by using `callnative`. This is preferential to creating a secondary battle script command table like is done in the CFRU. -In general, `gBattlescriptCurrInstr` tracks the current battle script position as a ROM address. Fortunately, we don't need to worry about ROM addresses when using the decomps, but it is important to understand because of how the `various` command is set up. +In general, `gBattlescriptCurrInstr` tracks the current battle script position as a ROM address. Fortunately, we don't need to worry about ROM addresses when using the decomps, but it is important to understand because of how the `callnative` command is set up. ``` -.macro various battler:req, param1:req - .byte 0x76 - .byte \battler - .byte \param1 - .endm + .macro callnative func:req + .byte 0xff + .4byte \func + .endm ``` +`callnative` uses the last battle script command ID in order to pass a native function as an argument. Additional optional arguments are added recursively via a macro, so no need to worry about how they need to align to the amount of instructions to skip. -`various` is 3 bytes in size, so if we wanted to advance to the next battle script command, we would write `gBattlescriptCurrInstr += 3`. Coincidentally, this is found at the end of `Cmd_Various` in `src/battle_script_commands.c`. - -Now, how might we add a custom various command case? Here are the steps. We will use `VARIOUS_SET_SIMPLE_BEAM` as an example. -### 1. Add a definition to `include/constants/battle_script_commands.h`. - -For example, `#define VARIOUS_SET_SIMPLE_BEAM 39` - -### 2. Create a macro in `asm/macros/battle_script.inc`. For example: +Now, how might we add a custom `callnative` command? Here are the steps. We will use `BS_TrySetOctolock` as an example. +### 1. Create a macro in `asm/macros/battle_script.inc`. For example: ```c -.macro setabilitysimple battler:req, ptr:req - various \battler VARIOUS_SET_SIMPLE_BEAM - .4byte \ptr - .endm + .macro trysetoctolock battler:req, failInstr:req + callnative BS_TrySetOctolock + .byte \battler + .4byte \failInstr + .endm ``` - -### 3. Add your new various command ID to `Cmd_Various`. For example: +### 2. Add your new callnative command ID to `src/battle_script_commands.c`. For example: ```c - case VARIOUS_SET_SIMPLE_BEAM: - if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gBattlerTarget].ability) - || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) - { - gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); - } - else - { - gBattleMons[gBattlerTarget].ability = ABILITY_SIMPLE; - RecordAbilityBattle(gActiveBattler, ABILITY_SIMPLE); - gBattlescriptCurrInstr += 7; - } - return; +void BS_TrySetOctolock(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gDisableStructs[battler].octolock) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gDisableStructs[battler].octolock = TRUE; + gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; + gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} ``` - -The macros' `battler` argument is the battler who will be affected/considered by your command. In our case, which battler we will try to give `ABILITY_SIMPLE`. Note that `gActiveBattler` is always set to this battler at the beginning of `Cmd_Various`. - -The `ptr` argument is an extra argument that, in this case, provides a battle script to jump to in the event that we fail to set `ABILITY_SIMPLE`. We must add the `.4byte \ptr` inside our macro. So now when we want to advance to the next battle script command in our script, we must increment `gBattlescriptCurrInstr` by `7` because our overall macro is 3 bytes for the various command, and 4 bytes for the pointer. *IMPORTANT* the `return` at the end of the switch case is required because remember that `various` always defaults to `gBattlescriptCurrInstr += 3` at the very end of the function, so if we included `gBattlescriptCurrInstr += 7` with a `break`, we would end up effectively doing `gBattlescriptCurrInstr += 10`. - -This behavior can be found under the `else` statement in the example above, corresponding to `ABILITY_SIMPLE` being correctly applied. If we are unable to set `ABILITY_SIMPLE`, however, notice the following `gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);`. This means we are jumping to the battle script provided by the pointer 3 bytes after our various command (which is the `ptr` argument described previously). We still must `return` or else we would actually jump to 3 bytes after the `ptr` battle script begins. +Each of the arguments defined in the macro (`battler`, `failInstr`) need to be called at the start of the command using `NATIVE_ARGS`. +The byte count in the macro should correspond to the type that will be used for the command (eg, `u8` is `byte`, while the pointer are `4byte`). +These arguments can then be accessed as `cmd->battler` and `cmd->battler`. +`gBattlescriptCurrInstr = cmd->nextInstr;` advances to the next instruction. diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 050a20d933..54052e5390 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -88,138 +88,138 @@ #define CMP_COMMON_BITS 4 #define CMP_NO_COMMON_BITS 5 -// Cmd_various -#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0 -#define VARIOUS_IS_RUNNING_IMPOSSIBLE 1 -#define VARIOUS_GET_MOVE_TARGET 2 -#define VARIOUS_GET_BATTLER_FAINTED 3 -#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 4 -#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 5 -#define VARIOUS_RESET_PLAYER_FAINTED 6 -#define VARIOUS_PALACE_FLAVOR_TEXT 7 -#define VARIOUS_ARENA_JUDGMENT_WINDOW 8 -#define VARIOUS_ARENA_OPPONENT_MON_LOST 9 -#define VARIOUS_ARENA_PLAYER_MON_LOST 10 -#define VARIOUS_ARENA_BOTH_MONS_LOST 11 -#define VARIOUS_EMIT_YESNOBOX 12 -#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 13 -#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 14 -#define VARIOUS_ARENA_JUDGMENT_STRING 15 -#define VARIOUS_ARENA_WAIT_STRING 16 -#define VARIOUS_WAIT_CRY 17 -#define VARIOUS_RETURN_OPPONENT_MON1 18 -#define VARIOUS_RETURN_OPPONENT_MON2 19 -#define VARIOUS_VOLUME_DOWN 20 -#define VARIOUS_VOLUME_UP 21 -#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 22 -#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 23 -#define VARIOUS_SET_TELEPORT_OUTCOME 24 -#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 25 -#define VARIOUS_STAT_TEXT_BUFFER 26 -#define VARIOUS_SWITCHIN_ABILITIES 27 -#define VARIOUS_INSTANT_HP_DROP 28 -#define VARIOUS_CLEAR_STATUS 29 -#define VARIOUS_RESTORE_PP 30 -#define VARIOUS_TRY_ACTIVATE_MOXIE 31 -#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 32 -#define VARIOUS_PLAY_MOVE_ANIMATION 33 -#define VARIOUS_SET_LUCKY_CHANT 34 -#define VARIOUS_SUCKER_PUNCH_CHECK 35 -#define VARIOUS_SET_SIMPLE_BEAM 36 -#define VARIOUS_TRY_ENTRAINMENT 37 -#define VARIOUS_SET_LAST_USED_ABILITY 38 -#define VARIOUS_INVERT_STAT_STAGES 39 -#define VARIOUS_TRY_ME_FIRST 40 -#define VARIOUS_JUMP_IF_BATTLE_END 41 -#define VARIOUS_TRY_ELECTRIFY 42 -#define VARIOUS_TRY_REFLECT_TYPE 43 -#define VARIOUS_TRY_SOAK 44 -#define VARIOUS_HANDLE_MEGA_EVO 45 -#define VARIOUS_TRY_LAST_RESORT 46 -#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 47 -#define VARIOUS_TRY_AUTOTOMIZE 48 -#define VARIOUS_ABILITY_POPUP 49 -#define VARIOUS_JUMP_IF_TARGET_ALLY 50 -#define VARIOUS_TRY_SYNCHRONOISE 51 -#define VARIOUS_PSYCHO_SHIFT 52 -#define VARIOUS_CURE_STATUS 53 -#define VARIOUS_POWER_TRICK 54 -#define VARIOUS_AFTER_YOU 55 -#define VARIOUS_BESTOW 56 -#define VARIOUS_JUMP_IF_NOT_GROUNDED 57 -#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 58 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 59 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 60 -#define VARIOUS_SET_AURORA_VEIL 61 -#define VARIOUS_TRY_THIRD_TYPE 62 -#define VARIOUS_ACUPRESSURE 63 -#define VARIOUS_SET_POWDER 64 -#define VARIOUS_SPECTRAL_THIEF 65 -#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 66 -#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 67 -#define VARIOUS_JUMP_IF_ROAR_FAILS 68 -#define VARIOUS_TRY_INSTRUCT 69 -#define VARIOUS_JUMP_IF_NOT_BERRY 70 -#define VARIOUS_TRACE_ABILITY 71 -#define VARIOUS_UPDATE_NICK 72 -#define VARIOUS_TRY_ILLUSION_OFF 73 -#define VARIOUS_SET_SPRITEIGNORE0HP 74 -#define VARIOUS_HANDLE_FORM_CHANGE 75 -#define VARIOUS_GET_STAT_VALUE 76 -#define VARIOUS_JUMP_IF_FULL_HP 77 -#define VARIOUS_LOSE_TYPE 78 -#define VARIOUS_TRY_ACTIVATE_SOULHEART 79 -#define VARIOUS_TRY_ACTIVATE_RECEIVER 80 -#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 81 -#define VARIOUS_TRY_FRISK 82 -#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 83 -#define VARIOUS_TRY_FAIRY_LOCK 84 -#define VARIOUS_JUMP_IF_NO_ALLY 85 -#define VARIOUS_POISON_TYPE_IMMUNITY 86 -#define VARIOUS_JUMP_IF_HOLD_EFFECT 87 -#define VARIOUS_INFATUATE_WITH_BATTLER 88 -#define VARIOUS_SET_LAST_USED_ITEM 89 -#define VARIOUS_PARALYZE_TYPE_IMMUNITY 90 -#define VARIOUS_JUMP_IF_ABSENT 91 -#define VARIOUS_DESTROY_ABILITY_POPUP 92 -#define VARIOUS_TOTEM_BOOST 93 -#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 94 -#define VARIOUS_MOVEEND_ITEM_EFFECTS 95 -#define VARIOUS_TERRAIN_SEED 96 -#define VARIOUS_MAKE_INVISIBLE 97 -#define VARIOUS_ROOM_SERVICE 98 -#define VARIOUS_EERIE_SPELL_PP_REDUCE 99 -#define VARIOUS_JUMP_IF_TEAM_HEALTHY 100 -#define VARIOUS_TRY_HEAL_QUARTER_HP 101 -#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 102 -#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 103 -#define VARIOUS_GET_ROTOTILLER_TARGETS 104 -#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 105 -#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 106 -#define VARIOUS_CONSUME_BERRY 107 -#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 108 -#define VARIOUS_JUMP_IF_SPECIES 109 -#define VARIOUS_UPDATE_ABILITY_POPUP 110 -#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 111 -#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 112 -#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 113 -#define VARIOUS_TRY_NO_RETREAT 114 -#define VARIOUS_CHECK_POLTERGEIST 115 -#define VARIOUS_CUT_1_3_HP_RAISE_STATS 116 -#define VARIOUS_TRY_END_NEUTRALIZING_GAS 117 -#define VARIOUS_JUMP_IF_UNDER_200 118 -#define VARIOUS_SET_SKY_DROP 119 -#define VARIOUS_CLEAR_SKY_DROP 120 -#define VARIOUS_SKY_DROP_YAWN 121 -#define VARIOUS_CURE_CERTAIN_STATUSES 122 -#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 123 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 124 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 125 -#define VARIOUS_SAVE_BATTLER_ITEM 126 -#define VARIOUS_RESTORE_BATTLER_ITEM 127 -#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 128 -#define VARIOUS_SWAP_SIDE_STATUSES 129 -#define VARIOUS_SWAP_STATS 130 +enum CmdVarious +{ + VARIOUS_CANCEL_MULTI_TURN_MOVES, + VARIOUS_IS_RUNNING_IMPOSSIBLE, + VARIOUS_GET_MOVE_TARGET, + VARIOUS_GET_BATTLER_FAINTED, + VARIOUS_RESET_SWITCH_IN_ABILITY_BITS, + VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP, + VARIOUS_RESET_PLAYER_FAINTED, + VARIOUS_PALACE_FLAVOR_TEXT, + VARIOUS_ARENA_JUDGMENT_WINDOW, + VARIOUS_ARENA_OPPONENT_MON_LOST, + VARIOUS_ARENA_PLAYER_MON_LOST, + VARIOUS_ARENA_BOTH_MONS_LOST, + VARIOUS_EMIT_YESNOBOX, + VARIOUS_DRAW_ARENA_REF_TEXT_BOX, + VARIOUS_ERASE_ARENA_REF_TEXT_BOX, + VARIOUS_ARENA_JUDGMENT_STRING, + VARIOUS_ARENA_WAIT_STRING, + VARIOUS_WAIT_CRY, + VARIOUS_RETURN_OPPONENT_MON1, + VARIOUS_RETURN_OPPONENT_MON2, + VARIOUS_VOLUME_DOWN, + VARIOUS_VOLUME_UP, + VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT, + VARIOUS_PALACE_TRY_ESCAPE_STATUS, + VARIOUS_SET_TELEPORT_OUTCOME, + VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC, + VARIOUS_STAT_TEXT_BUFFER, + VARIOUS_SWITCHIN_ABILITIES, + VARIOUS_INSTANT_HP_DROP, + VARIOUS_CLEAR_STATUS, + VARIOUS_RESTORE_PP, + VARIOUS_TRY_ACTIVATE_MOXIE, + VARIOUS_TRY_ACTIVATE_FELL_STINGER, + VARIOUS_PLAY_MOVE_ANIMATION, + VARIOUS_SET_LUCKY_CHANT, + VARIOUS_SUCKER_PUNCH_CHECK, + VARIOUS_SET_SIMPLE_BEAM, + VARIOUS_TRY_ENTRAINMENT, + VARIOUS_SET_LAST_USED_ABILITY, + VARIOUS_INVERT_STAT_STAGES, + VARIOUS_TRY_ME_FIRST, + VARIOUS_JUMP_IF_BATTLE_END, + VARIOUS_TRY_ELECTRIFY, + VARIOUS_TRY_SOAK, + VARIOUS_TRY_LAST_RESORT, + VARIOUS_SET_ARG_TO_BATTLE_DAMAGE, + VARIOUS_TRY_AUTOTOMIZE, + VARIOUS_ABILITY_POPUP, + VARIOUS_JUMP_IF_TARGET_ALLY, + VARIOUS_TRY_SYNCHRONOISE, + VARIOUS_PSYCHO_SHIFT, + VARIOUS_CURE_STATUS, + VARIOUS_POWER_TRICK, + VARIOUS_AFTER_YOU, + VARIOUS_BESTOW, + VARIOUS_JUMP_IF_NOT_GROUNDED, + VARIOUS_HANDLE_TRAINER_SLIDE_MSG, + VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF, + VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON, + VARIOUS_SET_AURORA_VEIL, + VARIOUS_TRY_THIRD_TYPE, + VARIOUS_ACUPRESSURE, + VARIOUS_SET_POWDER, + VARIOUS_SPECTRAL_THIEF, + VARIOUS_GRAVITY_ON_AIRBORNE_MONS, + VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, + VARIOUS_JUMP_IF_ROAR_FAILS, + VARIOUS_TRY_INSTRUCT, + VARIOUS_JUMP_IF_NOT_BERRY, + VARIOUS_TRACE_ABILITY, + VARIOUS_UPDATE_NICK, + VARIOUS_TRY_ILLUSION_OFF, + VARIOUS_SET_SPRITEIGNORE0HP, + VARIOUS_HANDLE_FORM_CHANGE, + VARIOUS_GET_STAT_VALUE, + VARIOUS_JUMP_IF_FULL_HP, + VARIOUS_LOSE_TYPE, + VARIOUS_TRY_ACTIVATE_SOULHEART, + VARIOUS_TRY_ACTIVATE_RECEIVER, + VARIOUS_TRY_ACTIVATE_BEAST_BOOST, + VARIOUS_TRY_FRISK, + VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED, + VARIOUS_TRY_FAIRY_LOCK, + VARIOUS_JUMP_IF_NO_ALLY, + VARIOUS_POISON_TYPE_IMMUNITY, + VARIOUS_JUMP_IF_HOLD_EFFECT, + VARIOUS_INFATUATE_WITH_BATTLER, + VARIOUS_SET_LAST_USED_ITEM, + VARIOUS_PARALYZE_TYPE_IMMUNITY, + VARIOUS_JUMP_IF_ABSENT, + VARIOUS_DESTROY_ABILITY_POPUP, + VARIOUS_TOTEM_BOOST, + VARIOUS_TRY_ACTIVATE_GRIM_NEIGH, + VARIOUS_MOVEEND_ITEM_EFFECTS, + VARIOUS_TERRAIN_SEED, + VARIOUS_MAKE_INVISIBLE, + VARIOUS_ROOM_SERVICE, + VARIOUS_EERIE_SPELL_PP_REDUCE, + VARIOUS_JUMP_IF_TEAM_HEALTHY, + VARIOUS_TRY_HEAL_QUARTER_HP, + VARIOUS_JUMP_IF_PRANKSTER_BLOCKED, + VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER, + VARIOUS_GET_ROTOTILLER_TARGETS, + VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED, + VARIOUS_TRY_ACTIVATE_BATTLE_BOND, + VARIOUS_CONSUME_BERRY, + VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL, + VARIOUS_JUMP_IF_SPECIES, + VARIOUS_UPDATE_ABILITY_POPUP, + VARIOUS_JUMP_IF_WEATHER_AFFECTED, + VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED, + VARIOUS_SET_ATTACKER_STICKY_WEB_USER, + VARIOUS_TRY_NO_RETREAT, + VARIOUS_CHECK_POLTERGEIST, + VARIOUS_CUT_1_3_HP_RAISE_STATS, + VARIOUS_TRY_END_NEUTRALIZING_GAS, + VARIOUS_JUMP_IF_UNDER_200, + VARIOUS_SET_SKY_DROP, + VARIOUS_CLEAR_SKY_DROP, + VARIOUS_SKY_DROP_YAWN, + VARIOUS_CURE_CERTAIN_STATUSES, + VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES, + VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY, + VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT, + VARIOUS_SAVE_BATTLER_ITEM, + VARIOUS_RESTORE_BATTLER_ITEM, + VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM, + VARIOUS_SWAP_SIDE_STATUSES, + VARIOUS_SWAP_STATS, +}; // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b2f46f124c..244aab3ed0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9146,13 +9146,14 @@ static void Cmd_various(void) s32 i; u8 data[10]; u32 battler, bits; + enum CmdVarious variousId = cmd->id; if (gBattleControllerExecFlags) return; battler = GetBattlerForBattleScript(cmd->battler); - switch (cmd->id) + switch (variousId) { // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. // Also when an opposing wild mon uses it againt its partner. From 6a2a3b254091a0766cce7432ad775ae372f5f9a5 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sat, 14 Dec 2024 17:23:00 +0100 Subject: [PATCH 25/45] remove fno-toplevel-reorder --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 71d2a48af9..3548aa8cc9 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ CPPFLAGS := $(INCLUDE_CPP_ARGS) -Wno-trigraphs -DMODERN=1 -DTESTING=$(TEST) ARMCC := $(PREFIX)gcc PATH_ARMCC := PATH="$(PATH)" $(ARMCC) CC1 := $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init +override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init ifeq ($(ANALYZE),1) override CFLAGS += -fanalyzer endif @@ -346,6 +346,7 @@ endif $(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast $(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member +$(C_BUILDDIR)/agb_flash.o: override CFLAGS += -fno-toplevel-reorder $(C_BUILDDIR)/pokedex_plus_hgss.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init # Annoyingly we can't turn this on just for src/data/trainers.h $(C_BUILDDIR)/data.o: CFLAGS += -fno-show-column -fno-diagnostics-show-caret From d16f6185f7701f70083e3c33f1646de810da30e3 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 21 Dec 2024 16:27:35 +0100 Subject: [PATCH 26/45] Fix IS_MOVE_STATUS regression (#5848) --- src/battle_ai_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 267fc476c2..b68112374d 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2393,7 +2393,7 @@ bool32 HasDamagingMoveOfType(u32 battlerId, u32 type) for (i = 0; i < MAX_MON_MOVES; i++) { if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && !IS_MOVE_STATUS(moves[i]].type == type && gMovesInfo[moves[i])) + && gMovesInfo[moves[i]].type == type && !IS_MOVE_STATUS(moves[i])) return TRUE; } From f61a0f6a30b667ceef00669f38a487edb8096779 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 21 Dec 2024 19:45:50 +0100 Subject: [PATCH 27/45] Sheer Force fix and move effect cleanup (#5812) --- asm/macros/battle_script.inc | 10 - data/battle_scripts_1.s | 56 +- include/battle_scripts.h | 14 +- include/constants/battle.h | 10 +- include/constants/battle_move_effects.h | 7 - include/pokemon.h | 10 +- src/battle_ai_main.c | 11 +- src/battle_script_commands.c | 170 ++-- src/battle_util.c | 5 + src/data/battle_move_effects.h | 42 - src/data/moves_info.h | 62 +- test/battle/ability/sheer_force.c | 949 +++++++++++++++++- test/battle/move_effect/salt_cure.c | 2 +- test/battle/move_effect_secondary/haze.c | 32 + .../ion_deluge.c} | 22 +- .../battle/move_effect_secondary/leech_seed.c | 37 + .../move_effect_secondary/light_screen.c | 32 + test/battle/move_effect_secondary/reflect.c | 32 + 18 files changed, 1266 insertions(+), 237 deletions(-) create mode 100644 test/battle/move_effect_secondary/haze.c rename test/battle/{move_effect/plasma_fists.c => move_effect_secondary/ion_deluge.c} (80%) create mode 100644 test/battle/move_effect_secondary/leech_seed.c create mode 100644 test/battle/move_effect_secondary/light_screen.c create mode 100644 test/battle/move_effect_secondary/reflect.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 7ae4403ff9..fbc724a81e 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1425,11 +1425,6 @@ callnative BS_TryRevertWeatherForm .endm - .macro applysaltcure battler:req - callnative BS_ApplySaltCure - .byte \battler - .endm - .macro trysetoctolock battler:req, failInstr:req callnative BS_TrySetOctolock .byte \battler @@ -2214,11 +2209,6 @@ .4byte \jumpInstr .endm - .macro eeriespellppreduce failInstr:req - various BS_TARGET, VARIOUS_EERIE_SPELL_PP_REDUCE - .4byte \failInstr - .endm - .macro jumpifteamhealthy battler:req, jumpInstr:req various \battler, VARIOUS_JUMP_IF_TEAM_HEALTHY .4byte \jumpInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 7359b4469a..d94ba2363b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -396,16 +396,10 @@ BattleScript_EffectHit_Pledge:: tryfaintmon BS_TARGET return -BattleScript_EffectSaltCure:: - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - jumpiffainted BS_TARGET, TRUE, BattleScript_EffectSaltCure_End - jumpifsubstituteblocks BattleScript_EffectSaltCure_End - applysaltcure BS_TARGET +BattleScript_MoveEffectSaltCure:: printstring STRINGID_TARGETISBEINGSALTCURED waitmessage B_WAIT_TIME_LONG -BattleScript_EffectSaltCure_End: - goto BattleScript_MoveEnd + return BattleScript_SaltCureExtraDamage:: playanimation BS_TARGET, B_ANIM_SALT_CURE_DAMAGE, NULL @@ -949,13 +943,10 @@ BattleScript_HyperspaceFuryRemoveProtect:: waitmessage B_WAIT_TIME_LONG return -BattleScript_EffectPlasmaFists:: - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - orword gFieldStatuses, STATUS_FIELD_ION_DELUGE +BattleScript_MoveEffectIonDeluge:: printstring STRINGID_IONDELUGEON waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_EffectSparklySwirl:: call BattleScript_EffectHit_Ret @@ -966,41 +957,25 @@ BattleScript_EffectSparklySwirl:: waitstate goto BattleScript_MoveEnd -BattleScript_EffectFreezyFrost:: - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - normalisebuffs +BattleScript_MoveEffectHaze:: printstring STRINGID_STATCHANGESGONE waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return -BattleScript_EffectSappySeed:: - jumpifstatus3 BS_TARGET, STATUS3_LEECHSEED, BattleScript_EffectHit - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - jumpifhasnohp BS_TARGET, BattleScript_MoveEnd - setseeded - printfromtable gLeechSeedStringIds +BattleScript_MoveEffectLeechSeed:: + printstring STRINGID_PKMNSEEDED waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectBaddyBad:: - jumpifsideaffecting BS_ATTACKER, SIDE_STATUS_REFLECT, BattleScript_EffectHit - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - setreflect +BattleScript_MoveEffectReflect:: printfromtable gReflectLightScreenSafeguardStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return -BattleScript_EffectGlitzyGlow:: - jumpifsideaffecting BS_ATTACKER, SIDE_STATUS_LIGHTSCREEN, BattleScript_EffectHit - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - setlightscreen +BattleScript_MoveEffectLightScreen:: printfromtable gReflectLightScreenSafeguardStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_EffectStuffCheeks:: attackcanceler @@ -4065,13 +4040,10 @@ BattleScript_EffectDestinyBond:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectEerieSpell:: - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - eeriespellppreduce BattleScript_MoveEnd +BattleScript_MoveEffectEerieSpell:: printstring STRINGID_PKMNREDUCEDPP waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_EffectSpite:: attackcanceler diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 3c58b28e1e..158dfb5dc3 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -804,18 +804,18 @@ extern const u8 BattleScript_EffectGeomancy[]; extern const u8 BattleScript_EffectFairyLock[]; extern const u8 BattleScript_EffectAllySwitch[]; extern const u8 BattleScript_EffectRelicSong[]; -extern const u8 BattleScript_EffectEerieSpell[]; +extern const u8 BattleScript_MoveEffectEerieSpell[]; extern const u8 BattleScript_EffectJungleHealing[]; extern const u8 BattleScript_EffectCoaching[]; extern const u8 BattleScript_EffectDecorate[]; extern const u8 BattleScript_EffectRecoilHP25[]; extern const u8 BattleScript_EffectStuffCheeks[]; -extern const u8 BattleScript_EffectGlitzyGlow[]; -extern const u8 BattleScript_EffectBaddyBad[]; -extern const u8 BattleScript_EffectSappySeed[]; -extern const u8 BattleScript_EffectFreezyFrost[]; +extern const u8 BattleScript_MoveEffectLightScreen[]; +extern const u8 BattleScript_MoveEffectReflect[]; +extern const u8 BattleScript_MoveEffectLeechSeed[]; +extern const u8 BattleScript_MoveEffectHaze[]; extern const u8 BattleScript_EffectSparklySwirl[]; -extern const u8 BattleScript_EffectPlasmaFists[]; +extern const u8 BattleScript_MoveEffectIonDeluge[]; extern const u8 BattleScript_EffectHyperspaceFury[]; extern const u8 BattleScript_EffectAuraWheel[]; extern const u8 BattleScript_EffectPhotonGeyser[]; @@ -838,7 +838,7 @@ extern const u8 BattleScript_EffectRevivalBlessing[]; extern const u8 BattleScript_EffectSnow[]; extern const u8 BattleScript_EffectTakeHeart[]; extern const u8 BattleScript_EffectCorrosiveGas[]; -extern const u8 BattleScript_EffectSaltCure[]; +extern const u8 BattleScript_MoveEffectSaltCure[]; extern const u8 BattleScript_EffectChillyReception[]; extern const u8 BattleScript_EffectMaxMove[]; extern const u8 BattleScript_EffectGlaiveRush[]; diff --git a/include/constants/battle.h b/include/constants/battle.h index ed19a72d9c..d9c4e1301c 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -405,8 +405,16 @@ #define MOVE_EFFECT_PSYCHIC_NOISE 78 #define MOVE_EFFECT_TERA_BLAST 79 #define MOVE_EFFECT_ORDER_UP 80 +#define MOVE_EFFECT_ION_DELUGE 81 +#define MOVE_EFFECT_AROMATHERAPY 82 // No functionality yet +#define MOVE_EFFECT_HAZE 83 +#define MOVE_EFFECT_LEECH_SEED 84 +#define MOVE_EFFECT_REFLECT 85 +#define MOVE_EFFECT_LIGHT_SCREEN 86 +#define MOVE_EFFECT_SALT_CURE 87 +#define MOVE_EFFECT_EERIE_SPELL 88 -#define NUM_MOVE_EFFECTS 81 +#define NUM_MOVE_EFFECTS 88 #define MOVE_EFFECT_AFFECTS_USER 0x2000 #define MOVE_EFFECT_CERTAIN 0x4000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index b1472d0280..d0e4839bce 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -282,7 +282,6 @@ enum { EFFECT_ALLY_SWITCH, EFFECT_RELIC_SONG, EFFECT_BODY_PRESS, - EFFECT_EERIE_SPELL, EFFECT_JUNGLE_HEALING, EFFECT_COACHING, EFFECT_LASH_OUT, @@ -293,12 +292,7 @@ enum { EFFECT_RECOIL_HP_25, EFFECT_STUFF_CHEEKS, EFFECT_GRAV_APPLE, - EFFECT_GLITZY_GLOW, - EFFECT_BADDY_BAD, - EFFECT_SAPPY_SEED, - EFFECT_FREEZY_FROST, EFFECT_SPARKLY_SWIRL, - EFFECT_PLASMA_FISTS, EFFECT_HYPERSPACE_FURY, EFFECT_AURA_WHEEL, EFFECT_PHOTON_GEYSER, @@ -331,7 +325,6 @@ enum { EFFECT_COLLISION_COURSE, EFFECT_CORROSIVE_GAS, EFFECT_POPULATION_BOMB, - EFFECT_SALT_CURE, EFFECT_CHILLY_RECEPTION, EFFECT_MAX_MOVE, EFFECT_GLAIVE_RUSH, diff --git a/include/pokemon.h b/include/pokemon.h index 8a618f5fe1..069290b363 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -564,8 +564,12 @@ struct MoveInfo #define EFFECTS_ARR(...) (const struct AdditionalEffect[]) {__VA_ARGS__} #define ADDITIONAL_EFFECTS(...) EFFECTS_ARR( __VA_ARGS__ ), .numAdditionalEffects = ARRAY_COUNT(EFFECTS_ARR( __VA_ARGS__ )) -// Just a hack to make a move boosted by Sheer Force despite having no secondary effects affected -#define SHEER_FORCE_HACK { .moveEffect = 0, .chance = 100, } +enum SheerForceBoost +{ + SHEER_FORCE_AUTO_BOOST, // This is the default state when a move has a move effect with a chance + SHEER_FORCE_BOOST, // If a move effect doesn't have an effect with a chance this can force a boost + SHEER_FORCE_NO_BOOST, // Prevents a Sheer Force boost +}; struct AdditionalEffect { @@ -573,6 +577,8 @@ struct AdditionalEffect u8 self:1; u8 onlyIfTargetRaisedStats:1; u8 onChargeTurnOnly:1; + u8 sheerForceBoost:2; // Handles edge cases for Sheer Force + u8 padding:3; u8 chance; // 0% = effect certain, primary effect }; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d245be8cd5..538b0e4732 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2511,8 +2511,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-4); break; //TODO - //case EFFECT_PLASMA_FISTS: - //break; //case EFFECT_SHELL_TRAP: //break; //case EFFECT_BEAK_BLAST: @@ -4416,10 +4414,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) || gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) ADJUST_SCORE(GOOD_EFFECT); break; - case EFFECT_SALT_CURE: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) - ADJUST_SCORE(DECENT_EFFECT); - break; } // move effect checks // check move additional effects that are likely to happen @@ -4664,6 +4658,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (!HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move)) ADJUST_SCORE(BEST_EFFECT); break; + case MOVE_EFFECT_SALT_CURE: + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) + ADJUST_SCORE(DECENT_EFFECT); + break; + } } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 244aab3ed0..40f9db64c6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2904,7 +2904,8 @@ void SetMoveEffect(bool32 primary, bool32 certain) bool32 statusChanged = FALSE; bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR); u32 flags = 0; - u16 battlerAbility; + u32 battlerAbility; + u32 side; bool8 activateAfterFaint = FALSE; // NULL move effect @@ -3992,6 +3993,117 @@ void SetMoveEffect(bool32 primary, bool32 certain) } } break; + case MOVE_EFFECT_ION_DELUGE: + if (!(gFieldStatuses & STATUS_FIELD_ION_DELUGE)) + { + gFieldStatuses |= STATUS_FIELD_ION_DELUGE; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectIonDeluge; + } + break; + // TODO: The moves aromatherapy and heal bell need a refactor first + // case MOVE_EFFECT_AROMATHERAPY: + // break; + case MOVE_EFFECT_HAZE: + for (i = 0; i < gBattlersCount; i++) + TryResetBattlerStatChanges(i); + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectHaze; + break; + case MOVE_EFFECT_LEECH_SEED: + if (!IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) && !(gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED)) + { + gStatuses3[gBattlerTarget] |= gBattlerAttacker; + gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectLeechSeed; + } + break; + case MOVE_EFFECT_REFLECT: + side = GetBattlerSide(gBattlerAttacker); + if (!(gSideStatuses[side] & SIDE_STATUS_REFLECT)) + { + gSideStatuses[side] |= SIDE_STATUS_REFLECT; + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[side].reflectTimer = 8; + else + gSideTimers[side].reflectTimer = 5; + gSideTimers[side].reflectBattlerId = gBattlerAttacker; + + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_REFLECT_DOUBLE; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_REFLECT_SINGLE; + + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectReflect; + } + break; + case MOVE_EFFECT_LIGHT_SCREEN: + side = GetBattlerSide(gBattlerAttacker); + if (!(gSideStatuses[side] & SIDE_STATUS_LIGHTSCREEN)) + { + gSideStatuses[side] |= SIDE_STATUS_LIGHTSCREEN; + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[side].lightscreenTimer = 8; + else + gSideTimers[side].lightscreenTimer = 5; + gSideTimers[side].lightscreenBattlerId = gBattlerAttacker; + + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_DOUBLE; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_LIGHTSCREEN_SINGLE; + + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectLightScreen; + } + break; + case MOVE_EFFECT_SALT_CURE: + if (!(gStatuses4[gBattlerTarget] & STATUS4_SALT_CURE)) + { + gStatuses4[gBattlerTarget] |= STATUS4_SALT_CURE; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectSaltCure; + } + break; + case MOVE_EFFECT_EERIE_SPELL: + if (gLastMoves[gBattlerTarget] != MOVE_NONE && gLastMoves[gBattlerTarget] != 0xFFFF) + { + u32 i; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gLastMoves[gBattlerTarget] == gBattleMons[gBattlerTarget].moves[i]) + break; + } + + if (i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) + { + u32 ppToDeduct = 3; + + if (gBattleMons[gBattlerTarget].pp[i] < ppToDeduct) + ppToDeduct = gBattleMons[gBattlerTarget].pp[i]; + + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gBattlerTarget]) + ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, STR_CONV_MODE_LEFT_ALIGN, 1); + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) + gBattleMons[gBattlerTarget].pp[i] -= ppToDeduct; + if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) + && !(gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED)) + { + BtlController_EmitSetMonData(gBattlerTarget, BUFFER_A, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); + MarkBattlerForControllerExec(gBattlerTarget); + } + + if (gBattleMons[gBattlerTarget].pp[i] == 0 && gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF) + CancelMultiTurnMoves(gBattlerTarget); + + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectEerieSpell; + } + } + break; } } } @@ -10459,53 +10571,6 @@ static void Cmd_various(void) MarkBattlerForControllerExec(battler); break; } - case VARIOUS_EERIE_SPELL_PP_REDUCE: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gLastMoves[battler] != 0 && gLastMoves[battler] != 0xFFFF) - { - s32 i; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gLastMoves[battler] == gBattleMons[battler].moves[i]) - break; - } - - if (i != MAX_MON_MOVES && gBattleMons[battler].pp[i] != 0) - { - s32 ppToDeduct = 3; - - if (gBattleMons[battler].pp[i] < ppToDeduct) - ppToDeduct = gBattleMons[battler].pp[i]; - - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[battler]) - ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, STR_CONV_MODE_LEFT_ALIGN, 1); - PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) - gBattleMons[battler].pp[i] -= ppToDeduct; - if (!(gDisableStructs[battler].mimickedMoves & (1u << i)) - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) - { - BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[battler].pp[i]), &gBattleMons[battler].pp[i]); - MarkBattlerForControllerExec(battler); - } - - if (gBattleMons[battler].pp[i] == 0 && gBattleStruct->skyDropTargets[battler] == 0xFF) - CancelMultiTurnMoves(battler); - - gBattlescriptCurrInstr = cmd->nextInstr; // continue - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; // cant reduce pp - } - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; // cant reduce pp - } - return; - } case VARIOUS_JUMP_IF_TEAM_HEALTHY: { VARIOUS_ARGS(const u8 *jumpInstr); @@ -16539,15 +16604,6 @@ void BS_JumpIfElectricAbilityAffected(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_ApplySaltCure(void) -{ - NATIVE_ARGS(u8 battler); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses4[battler] |= STATUS4_SALT_CURE; - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_JumpIfArgument(void) { NATIVE_ARGS(u8 argument, const u8 *jumpInstr); diff --git a/src/battle_util.c b/src/battle_util.c index 45be169dfd..1e0341f337 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11783,8 +11783,13 @@ bool32 MoveIsAffectedBySheerForce(u32 move) u32 i; for (i = 0; i < gMovesInfo[move].numAdditionalEffects; i++) { + if (gMovesInfo[move].additionalEffects[i].sheerForceBoost == SHEER_FORCE_NO_BOOST) + continue; + if (gMovesInfo[move].additionalEffects[i].chance > 0) return TRUE; + if (gMovesInfo[move].additionalEffects[i].sheerForceBoost == SHEER_FORCE_BOOST) + return TRUE; } return FALSE; } diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index b5b3e539c8..ae9e831e4a 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -1811,12 +1811,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_EERIE_SPELL] = - { - .battleScript = BattleScript_EffectEerieSpell, - .battleTvScore = 0, // TODO: Assign points - }, - [EFFECT_JUNGLE_HEALING] = { .battleScript = BattleScript_EffectJungleHealing, @@ -1880,42 +1874,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_GLITZY_GLOW] = - { - .battleScript = BattleScript_EffectGlitzyGlow, - .battleTvScore = 0, // TODO: Assign points - }, - - [EFFECT_BADDY_BAD] = - { - .battleScript = BattleScript_EffectBaddyBad, - .battleTvScore = 0, // TODO: Assign points - }, - - [EFFECT_SAPPY_SEED] = - { - .battleScript = BattleScript_EffectSappySeed, - .battleTvScore = 0, // TODO: Assign points - }, - - [EFFECT_FREEZY_FROST] = - { - .battleScript = BattleScript_EffectFreezyFrost, - .battleTvScore = 0, // TODO: Assign points - }, - [EFFECT_SPARKLY_SWIRL] = { .battleScript = BattleScript_EffectSparklySwirl, .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_PLASMA_FISTS] = - { - .battleScript = BattleScript_EffectPlasmaFists, - .battleTvScore = 0, // TODO: Assign points - }, - [EFFECT_HYPERSPACE_FURY] = { .battleScript = BattleScript_EffectHyperspaceFury, @@ -2113,12 +2077,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_SALT_CURE] = - { - .battleScript = BattleScript_EffectSaltCure, - .battleTvScore = 0, // TODO: Assign points - }, - [EFFECT_CHILLY_RECEPTION] = { .battleScript = BattleScript_EffectChillyReception, diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 180d0d74ac..4ff3b71f4c 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -16757,7 +16757,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Hits with electrical fists.\n" "Normal moves turn Electric."), - .effect = EFFECT_PLASMA_FISTS, + .effect = EFFECT_HIT, .power = 100, .type = TYPE_ELECTRIC, .accuracy = 100, @@ -16772,6 +16772,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, .contestComboMoves = {0}, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_ION_DELUGE, + .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, + }), .battleAnimScript = gBattleAnimMove_PlasmaFists, }, @@ -16820,6 +16825,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_EVS_PLUS_1, .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), #endif .battleAnimScript = gBattleAnimMove_ZippyZap, @@ -16869,6 +16875,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_FloatyFall, }, @@ -16936,6 +16943,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_BuzzyBuzz, }, @@ -16961,6 +16969,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BURN, .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SizzlySlide, }, @@ -16971,7 +16980,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Telekinetic force that sets\n" "wall, lowering Sp. Atk damage."), - .effect = EFFECT_GLITZY_GLOW, + .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 80 : 90, .type = TYPE_PSYCHIC, .accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 95 : 100, @@ -16981,6 +16990,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .category = DAMAGE_CATEGORY_SPECIAL, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_LIGHT_SCREEN, + .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, + }), .battleAnimScript = gBattleAnimMove_GlitzyGlow, }, @@ -16990,7 +17004,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Acting badly, attacks. Sets\n" "wall, lowering Attack damage."), - .effect = EFFECT_BADDY_BAD, + .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 80 : 90, .type = TYPE_DARK, .accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 95 : 100, @@ -17000,6 +17014,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .category = DAMAGE_CATEGORY_SPECIAL, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_REFLECT, + .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, + }), .battleAnimScript = gBattleAnimMove_BaddyBad, }, @@ -17009,7 +17028,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Giant stalk scatters seeds\n" "that drain HP every turn."), - .effect = EFFECT_SAPPY_SEED, + .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 100 : 90, .type = TYPE_GRASS, .accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 90 : 100, @@ -17020,6 +17039,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .magicCoatAffected = TRUE, .metronomeBanned = TRUE, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_LEECH_SEED, + .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, + }), .battleAnimScript = gBattleAnimMove_SappySeed, }, @@ -17029,7 +17053,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Crystal from cold haze hits.\n" "Eliminates all stat changes."), - .effect = EFFECT_FREEZY_FROST, + .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 100 : 90, .type = TYPE_ICE, .accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 90 : 100, @@ -17039,6 +17063,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .category = DAMAGE_CATEGORY_SPECIAL, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_HAZE, + .chance = 100, + .sheerForceBoost = SHEER_FORCE_NO_BOOST, + }), .battleAnimScript = gBattleAnimMove_FreezyFrost, }, @@ -17048,7 +17077,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Wrap foe with whirlwind of\n" "scent. Heals party's status."), - .effect = EFFECT_SPARKLY_SWIRL, + .effect = EFFECT_SPARKLY_SWIRL, // Temprorary .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 120 : 90, .type = TYPE_FAIRY, .accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 85 : 100, @@ -17058,6 +17087,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .category = DAMAGE_CATEGORY_SPECIAL, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, + // .additionalEffects = ADDITIONAL_EFFECTS({ + // .moveEffect = 0, // MOVE_EFFECT_AROMATHERAPY, Added 0 for Sheer Force boost + // .chance = 100, + // .sheerForceBoost = SHEER_FORCE_NO_BOOST, + // }), .battleAnimScript = gBattleAnimMove_SparklySwirl, }, @@ -18682,7 +18716,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Attacks with psychic power.\n" "Foe's last move has 3 PP cut."), - .effect = EFFECT_EERIE_SPELL, + .effect = EFFECT_HIT, .power = 80, .type = TYPE_PSYCHIC, .accuracy = 100, @@ -18696,6 +18730,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, .contestComboMoves = {0}, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_EERIE_SPELL, + .chance = 100, + }), .battleAnimScript = gBattleAnimMove_EerieSpell, }, @@ -19497,7 +19535,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Hurts foe every turn. Double\n" "damage to Steel and Water."), - .effect = EFFECT_SALT_CURE, + .effect = EFFECT_HIT, .power = 40, .type = TYPE_ROCK, .accuracy = 100, @@ -19506,6 +19544,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .metronomeBanned = TRUE, + .additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_SALT_CURE, + .chance = 100, + }), .battleAnimScript = gBattleAnimMove_SaltCure, }, @@ -20402,7 +20444,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1, .self = TRUE, .onChargeTurnOnly = TRUE, - }, SHEER_FORCE_HACK), + .sheerForceBoost = SHEER_FORCE_BOOST, + }), .battleAnimScript = gBattleAnimMove_ElectroShot, }, @@ -20676,6 +20719,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_TOXIC, .chance = 50, + .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_MalignantChain, }, diff --git a/test/battle/ability/sheer_force.c b/test/battle/ability/sheer_force.c index 97dee48a31..e06e56c2c5 100644 --- a/test/battle/ability/sheer_force.c +++ b/test/battle/ability/sheer_force.c @@ -7,64 +7,909 @@ ASSUMPTIONS ASSUME(MoveIsAffectedBySheerForce(MOVE_ELECTRO_SHOT) == TRUE); } -SINGLE_BATTLE_TEST("Sheer Force boosts power, but removes secondary effects of moves", s16 damage) +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Magnitude", s16 damage) { - s32 j; - u32 ability = 0, move = 0; - - for (j = 1; j < MOVES_COUNT; j++) - { - if (MoveIsAffectedBySheerForce(j) - //&& gMovesInfo[j].effect != EFFECT_ORDER_UP - && gMovesInfo[j].effect != EFFECT_AURA_WHEEL - && gMovesInfo[j].effect != EFFECT_PLACEHOLDER) - { - PARAMETRIZE { ability = ABILITY_ANGER_POINT; move = j; } - PARAMETRIZE { ability = ABILITY_SHEER_FORCE; move = j; } - } - } - + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } GIVEN { - PLAYER(SPECIES_TAUROS) { Ability(ability); Status1(move == MOVE_SNORE ? STATUS1_SLEEP : STATUS1_NONE); } + PLAYER(SPECIES_TAUROS) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect - TURN { MOVE(opponent, MOVE_AGILITY); MOVE(player, move); } - else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move - TURN { MOVE(opponent, MOVE_QUICK_ATTACK); MOVE(player, move); } - else - TURN { MOVE(player, move); } - if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE) { - TURN { SKIP_TURN(player); } - TURN { ; } - } + TURN { MOVE(player, MOVE_MAGNITUDE); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, move, player); HP_BAR(opponent, captureDamage: &results[i].damage); - if (ability == ABILITY_SHEER_FORCE) { - NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - STATUS_ICON(opponent, STATUS1_FREEZE); - STATUS_ICON(opponent, STATUS1_POISON); - STATUS_ICON(opponent, STATUS1_BURN); - STATUS_ICON(opponent, STATUS1_TOXIC_POISON); - STATUS_ICON(opponent, STATUS1_PARALYSIS); - MESSAGE("Wobbuffet is confused!"); - MESSAGE("Wobbuffet flinched and couldn't move!"); - } - // Volt Tackle/Flare Blitz edge case: recoil happens, but target isn't statused - if (gMovesInfo[move].recoil > 0) - { - HP_BAR(player); - MESSAGE("Tauros was damaged by the recoil!"); - } - } } FINALLY { - s32 j; - for (j = 0; j < gBattleTestRunnerState->parametersCount; j+=2) - { - EXPECT_GT(results[j+1].damage, results[j].damage); - } + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Eruption", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PRESENT); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Water Spout", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PRESENT); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Present", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PRESENT); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Psywave", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYWAVE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Round", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ROUND); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Gyro Ball", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_GYRO_BALL); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Electro Ball", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ELECTRO_BALL); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Dragon Energy", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DRAGON_ENERGY); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Belch", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); HP(1); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BELCH); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Shell Trap", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SHELL_TRAP); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Burn Up", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ZEN_MODE; } + GIVEN { + PLAYER(SPECIES_DARMANITAN) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Double Shock", s16 damage) +{ + u16 move = 0; + PARAMETRIZE { move = MOVE_SKILL_SWAP; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + GIVEN { + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }; + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Steel Roller", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GRASSY_TERRAIN); MOVE(player, MOVE_STEEL_ROLLER); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Synchronoise", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); HP(1); Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_CHANSEY); + } WHEN { + TURN { MOVE(player, MOVE_SYNCHRONOISE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Aura Wheel", s16 damage) +{ + u16 move = 0; + PARAMETRIZE { move = MOVE_SKILL_SWAP; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + GIVEN { + PLAYER(SPECIES_MORPEKO); + OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }; + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_AURA_WHEEL); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Hyperspace Fury", s16 damage) +{ + u16 move = 0; + PARAMETRIZE { move = MOVE_SKILL_SWAP; } + PARAMETRIZE { move = MOVE_CELEBRATE; } + GIVEN { + PLAYER(SPECIES_HOOPA_UNBOUND); + OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }; + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_HYPERSPACE_FURY); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Bolt Beak", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BOLT_BEAK); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Fishious Rend", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FISHIOUS_REND); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Comeuppance", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_COMEUPPANCE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} +SINGLE_BATTLE_TEST("Sheer Force doesn't boost Comeuppance", s16 damage) +{ + u16 ability = 0; + PARAMETRIZE { ability = ABILITY_SHEER_FORCE; } + PARAMETRIZE { ability = ABILITY_ANGER_POINT; } + GIVEN { + PLAYER(SPECIES_TAUROS) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PAYBACK); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + EXPECT_NE(results[0].damage, 0); + } +} + +static inline bool32 IgnoreMoveForSheerForceBoost(u32 move) +{ + switch (move) { + case MOVE_PSYWAVE: // Just skip Psywve + case MOVE_PRESENT: // And Present... + case MOVE_MAGNITUDE: // And Magnitude... + case MOVE_ERUPTION: // And Eruption... + case MOVE_WATER_SPOUT: + case MOVE_GYRO_BALL: + case MOVE_SYNCHRONOISE: + case MOVE_ELECTRO_BALL: + case MOVE_ROUND: + case MOVE_BELCH: + case MOVE_HYPERSPACE_FURY: + case MOVE_BURN_UP: + case MOVE_SHELL_TRAP: + case MOVE_BOLT_BEAK: + case MOVE_FISHIOUS_REND: + case MOVE_AURA_WHEEL: + case MOVE_STEEL_ROLLER: + case MOVE_DRAGON_ENERGY: + case MOVE_DOUBLE_SHOCK: + case MOVE_COMEUPPANCE: + case MOVE_UPPER_HAND: // Bugged? + case MOVE_GLITZY_GLOW: // Light Screen Move Effect seems to be bugged + case MOVE_PAYBACK: + return TRUE; + } + return FALSE; +} + +static inline bool32 IsMoveSheerForceBoosted(u32 move) +{ + switch (move) { + case MOVE_AIR_SLASH: + case MOVE_ANCIENT_POWER: + case MOVE_ASTONISH: + case MOVE_BITE: + case MOVE_BLIZZARD: + case MOVE_BODY_SLAM: + case MOVE_BOUNCE: + case MOVE_BREAKING_SWIPE: + case MOVE_BUBBLE: + case MOVE_BUBBLE_BEAM: + case MOVE_BUG_BUZZ: + case MOVE_BULLDOZE: + case MOVE_BURNING_JEALOUSY: + case MOVE_CHARGE_BEAM: + case MOVE_CHILLING_WATER: + case MOVE_CONFUSION: + case MOVE_CRUNCH: + case MOVE_CRUSH_CLAW: + case MOVE_DARK_PULSE: + case MOVE_DRAGON_RUSH: + case MOVE_DRAGON_BREATH: + case MOVE_DYNAMIC_PUNCH: + case MOVE_EARTH_POWER: + case MOVE_EMBER: + case MOVE_ESPER_WING: + case MOVE_EXTRASENSORY: + case MOVE_FAKE_OUT: + case MOVE_FIRE_BLAST: + case MOVE_FIRE_FANG: + case MOVE_FIRE_PUNCH: + case MOVE_FLAME_CHARGE: + case MOVE_FLAME_WHEEL: + case MOVE_FLAMETHROWER: + case MOVE_FLARE_BLITZ: + case MOVE_FLASH_CANNON: + case MOVE_FOCUS_BLAST: + case MOVE_FORCE_PALM: + case MOVE_GUNK_SHOT: + case MOVE_HEADBUTT: + case MOVE_HEAT_WAVE: + case MOVE_HURRICANE: + case MOVE_ICE_BEAM: + case MOVE_ICE_FANG: + case MOVE_ICE_PUNCH: + case MOVE_ICICLE_CRASH: + case MOVE_ICY_WIND: + case MOVE_IRON_HEAD: + case MOVE_IRON_TAIL: + case MOVE_LAVA_PLUME: + case MOVE_LIQUIDATION: + case MOVE_LOW_SWEEP: + case MOVE_METAL_CLAW: + case MOVE_MUD_BOMB: + case MOVE_MUDDY_WATER: + case MOVE_MUD_SHOT: + case MOVE_MUD_SLAP: + case MOVE_MYSTICAL_FIRE: + case MOVE_PLAY_ROUGH: + case MOVE_POISON_FANG: + case MOVE_POISON_JAB: + case MOVE_POISON_STING: + case MOVE_POISON_TAIL: + case MOVE_POUNCE: + case MOVE_POWER_UP_PUNCH: + case MOVE_PSYBEAM: + case MOVE_PSYCHIC: + case MOVE_RAZOR_SHELL: + case MOVE_ROCK_CLIMB: + case MOVE_ROCK_SLIDE: + case MOVE_ROCK_SMASH: + case MOVE_ROCK_TOMB: + case MOVE_SANDSEAR_STORM: + case MOVE_SCALD: + case MOVE_SCORCHING_SANDS: + case MOVE_SECRET_POWER: + case MOVE_SHADOW_BALL: + case MOVE_SIGNAL_BEAM: + case MOVE_SKY_ATTACK: + case MOVE_SLUDGE_BOMB: + case MOVE_SLUDGE_WAVE: + case MOVE_SNARL: + case MOVE_SNORE: + case MOVE_STEEL_WING: + case MOVE_STOMP: + case MOVE_STONE_AXE: + case MOVE_STRUGGLE_BUG: + case MOVE_THROAT_CHOP: + case MOVE_THUNDER: + case MOVE_THUNDER_FANG: + case MOVE_THUNDERBOLT: + case MOVE_THUNDER_PUNCH: + case MOVE_TRAILBLAZE: + case MOVE_TWISTER: + case MOVE_UPPER_HAND: + case MOVE_WATER_PULSE: + case MOVE_WATERFALL: + case MOVE_ZAP_CANNON: + case MOVE_ZEN_HEADBUTT: + case MOVE_ACID: + case MOVE_ACID_SPRAY: + case MOVE_ALLURING_VOICE: + case MOVE_ANCHOR_SHOT: + case MOVE_APPLE_ACID: + case MOVE_AQUA_STEP: + case MOVE_AURA_WHEEL: + case MOVE_AURORA_BEAM: + case MOVE_AXE_KICK: + case MOVE_BARB_BARRAGE: + case MOVE_BITTER_MALICE: + case MOVE_BLAZE_KICK: + case MOVE_BLAZING_TORQUE: + case MOVE_BLEAKWIND_STORM: + case MOVE_BLUE_FLARE: + case MOVE_BOLT_STRIKE: + case MOVE_BONE_CLUB: + case MOVE_CEASELESS_EDGE: + case MOVE_CHATTER: + case MOVE_CLANGOROUS_SOULBLAZE: + case MOVE_COMBAT_TORQUE: + case MOVE_CONSTRICT: + case MOVE_CROSS_POISON: + case MOVE_DIAMOND_STORM: + case MOVE_DIRE_CLAW: + case MOVE_DISCHARGE: + case MOVE_DIZZY_PUNCH: + case MOVE_DOUBLE_IRON_BASH: + case MOVE_DRUM_BEATING: + case MOVE_EERIE_SPELL: + case MOVE_ELECTROWEB: + case MOVE_ENERGY_BALL: + case MOVE_FIERY_DANCE: + case MOVE_FIERY_WRATH: + case MOVE_FREEZING_GLARE: + case MOVE_FIRE_LASH: + case MOVE_FREEZE_DRY: + case MOVE_FREEZE_SHOCK: + case MOVE_GENESIS_SUPERNOVA: + case MOVE_GLACIATE: + case MOVE_GRAV_APPLE: + case MOVE_HEART_STAMP: + case MOVE_HYPER_FANG: + case MOVE_ICE_BURN: + case MOVE_INFERNAL_PARADE: + case MOVE_INFERNO: + case MOVE_LEAF_TORNADO: + case MOVE_LICK: + case MOVE_LUMINA_CRASH: + case MOVE_LUNGE: + case MOVE_LUSTER_PURGE: + case MOVE_MAGICAL_TORQUE: + case MOVE_MALIGNANT_CHAIN: + case MOVE_MATCHA_GOTCHA: + case MOVE_METEOR_MASH: + case MOVE_MIRROR_SHOT: + case MOVE_MIST_BALL: + case MOVE_MOONBLAST: + case MOVE_MORTAL_SPIN: + case MOVE_MOUNTAIN_GALE: + case MOVE_MYSTICAL_POWER: + case MOVE_NEEDLE_ARM: + case MOVE_NIGHT_DAZE: + case MOVE_NOXIOUS_TORQUE: + case MOVE_NUZZLE: + case MOVE_OCTAZOOKA: + case MOVE_OMINOUS_WIND: + case MOVE_ORDER_UP: + case MOVE_POWDER_SNOW: + case MOVE_PSYSHIELD_BASH: + case MOVE_PYRO_BALL: + case MOVE_RAPID_SPIN: + case MOVE_RELIC_SONG: + case MOVE_ROLLING_KICK: + case MOVE_SACRED_FIRE: + case MOVE_SALT_CURE: + case MOVE_SEARING_SHOT: + case MOVE_SEED_FLARE: + case MOVE_SHADOW_BONE: + case MOVE_SHELL_SIDE_ARM: + case MOVE_SILVER_WIND: + case MOVE_SKITTER_SMACK: + case MOVE_SLUDGE: + case MOVE_SMOG: + case MOVE_SPARK: + case MOVE_SPARKLING_ARIA: + case MOVE_SPIRIT_BREAK: + case MOVE_SPIRIT_SHACKLE: + case MOVE_SPLISHY_SPLASH: + case MOVE_SPRINGTIDE_STORM: + case MOVE_STEAM_ERUPTION: + case MOVE_STEAMROLLER: + case MOVE_STOKED_SPARKSURFER: + case MOVE_STRANGE_STEAM: + case MOVE_SYRUP_BOMB: + case MOVE_THUNDER_SHOCK: + case MOVE_THUNDEROUS_KICK: + case MOVE_TORCH_SONG: + case MOVE_TRI_ATTACK: + case MOVE_TRIPLE_ARROWS: + case MOVE_TROP_KICK: + case MOVE_TWINEEDLE: + case MOVE_VOLT_TACKLE: + case MOVE_WICKED_TORQUE: + case MOVE_WILDBOLT_STORM: + case MOVE_ZING_ZAP: + case MOVE_ELECTRO_SHOT: + case MOVE_PSYCHIC_NOISE: + return TRUE; + } + return FALSE; +} + +// Test split into four parts that handles ~1/4 of all moves each +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 1") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = 1; j < MOVES_COUNT; j += 4) + if (gMovesInfo[j].category != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE || gMovesInfo[move].effect == EFFECT_SOLAR_BEAM || gMovesInfo[move].effect == EFFECT_SKY_DROP) + { + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_FUTURE_SIGHT) + { + TURN { ; } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_BIDE) + { + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + } + } SCENE { + if (gMovesInfo[move].effect != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 2") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = 2; j < MOVES_COUNT; j += 4) + if (gMovesInfo[j].category != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE || gMovesInfo[move].effect == EFFECT_SOLAR_BEAM || gMovesInfo[move].effect == EFFECT_SKY_DROP) + { + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_FUTURE_SIGHT) + { + TURN { ; } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_BIDE) + { + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + } + } SCENE { + if (gMovesInfo[move].effect != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 3") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = 3; j < MOVES_COUNT; j += 4) + if (gMovesInfo[j].category != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE || gMovesInfo[move].effect == EFFECT_SOLAR_BEAM || gMovesInfo[move].effect == EFFECT_SKY_DROP) + { + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_FUTURE_SIGHT) + { + TURN { ; } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_BIDE) + { + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + } + } SCENE { + if (gMovesInfo[move].effect != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 4") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = 4; j < MOVES_COUNT; j += 4) + { + if (gMovesInfo[j].category != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + if (gMovesInfo[move].effect == EFFECT_TWO_TURNS_ATTACK || gMovesInfo[move].effect == EFFECT_SEMI_INVULNERABLE || gMovesInfo[move].effect == EFFECT_SOLAR_BEAM || gMovesInfo[move].effect == EFFECT_SKY_DROP) + { + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_FUTURE_SIGHT) + { + TURN { ; } + TURN { ; } + } + if (gMovesInfo[move].effect == EFFECT_BIDE) + { + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + } + } SCENE { + if (gMovesInfo[move].effect != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); } } diff --git a/test/battle/move_effect/salt_cure.c b/test/battle/move_effect/salt_cure.c index 495a7e8c80..afe811da50 100644 --- a/test/battle/move_effect/salt_cure.c +++ b/test/battle/move_effect/salt_cure.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_SALT_CURE].effect == EFFECT_SALT_CURE); + ASSUME(MoveHasAdditionalEffect(MOVE_SALT_CURE, MOVE_EFFECT_SALT_CURE) == TRUE); } SINGLE_BATTLE_TEST("Salt Cure inflicts 1/8 of the target's maximum HP as damage per turn") diff --git a/test/battle/move_effect_secondary/haze.c b/test/battle/move_effect_secondary/haze.c new file mode 100644 index 0000000000..c3831f0768 --- /dev/null +++ b/test/battle/move_effect_secondary/haze.c @@ -0,0 +1,32 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffect(MOVE_FREEZY_FROST, MOVE_EFFECT_HAZE) == TRUE); +} + +SINGLE_BATTLE_TEST("Freeze Frost restores stat changes when it was succesful") +{ + bool32 moveSuccess; + PARAMETRIZE { moveSuccess = FALSE; } + PARAMETRIZE { moveSuccess = TRUE; } + + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FREEZY_FROST, hit: moveSuccess); } + } SCENE { + if (moveSuccess == TRUE) + { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FREEZY_FROST, player); + MESSAGE("All stat changes were eliminated!"); + } else { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FREEZY_FROST, player); + MESSAGE("All stat changes were eliminated!"); + } + } + } +} diff --git a/test/battle/move_effect/plasma_fists.c b/test/battle/move_effect_secondary/ion_deluge.c similarity index 80% rename from test/battle/move_effect/plasma_fists.c rename to test/battle/move_effect_secondary/ion_deluge.c index 93c8869026..efc66903bc 100644 --- a/test/battle/move_effect/plasma_fists.c +++ b/test/battle/move_effect_secondary/ion_deluge.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_PLASMA_FISTS].effect == EFFECT_PLASMA_FISTS); + ASSUME(MoveHasAdditionalEffect(MOVE_PLASMA_FISTS, MOVE_EFFECT_ION_DELUGE) == TRUE); } SINGLE_BATTLE_TEST("Ion Duldge turns normal moves into electric for the remainder of the current turn") @@ -47,6 +47,26 @@ SINGLE_BATTLE_TEST("Plasma Fists turns normal moves into electric for the remain } } +SINGLE_BATTLE_TEST("Plasma Fists does not set up Ion Deluge if it does not connect") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_PHANPY].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_PHANPY].types[1] == TYPE_GROUND); + PLAYER(SPECIES_KRABBY); + OPPONENT(SPECIES_PHANPY); + } WHEN { + TURN { MOVE(player, MOVE_PLASMA_FISTS); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Krabby used Plasma Fists!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLASMA_FISTS, player); + MESSAGE("A deluge of ions showers the battlefield!"); + } + MESSAGE("The opposing Phanpy used Tackle!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + NOT MESSAGE("It's super effective!"); + } +} + SINGLE_BATTLE_TEST("Plasma Fists type-changing effect does not override Pixilate") { GIVEN { diff --git a/test/battle/move_effect_secondary/leech_seed.c b/test/battle/move_effect_secondary/leech_seed.c new file mode 100644 index 0000000000..c5a8db57cc --- /dev/null +++ b/test/battle/move_effect_secondary/leech_seed.c @@ -0,0 +1,37 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffect(MOVE_SAPPY_SEED, MOVE_EFFECT_LEECH_SEED) == TRUE); +} + +SINGLE_BATTLE_TEST("Sappy Seed can seed the target") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SAPPY_SEED); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SAPPY_SEED, player); + MESSAGE("The opposing Wobbuffet was seeded!"); + MESSAGE("The opposing Wobbuffet's health is sapped by Leech Seed!"); + } +} + +SINGLE_BATTLE_TEST("Sappy Seed is not going to seed the target if it fails") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SAPPY_SEED, hit: FALSE); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SAPPY_SEED, player); + MESSAGE("The opposing Wobbuffet was seeded!"); + MESSAGE("The opposing Wobbuffet's health is sapped by Leech Seed!"); + } + } +} diff --git a/test/battle/move_effect_secondary/light_screen.c b/test/battle/move_effect_secondary/light_screen.c new file mode 100644 index 0000000000..244e469893 --- /dev/null +++ b/test/battle/move_effect_secondary/light_screen.c @@ -0,0 +1,32 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffect(MOVE_GLITZY_GLOW, MOVE_EFFECT_LIGHT_SCREEN) == TRUE); +} + +SINGLE_BATTLE_TEST("Glitzy Glow sets up Light Screen when it was succesful") +{ + bool32 moveSuccess; + PARAMETRIZE { moveSuccess = FALSE; } + PARAMETRIZE { moveSuccess = TRUE; } + + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_GLITZY_GLOW, hit: moveSuccess); } + } SCENE { + if (moveSuccess == TRUE) + { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GLITZY_GLOW, player); + MESSAGE("Light Screen made your team stronger against special moves!"); + } else { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GLITZY_GLOW, player); + MESSAGE("Light Screen made your team stronger against special moves!"); + } + } + } +} diff --git a/test/battle/move_effect_secondary/reflect.c b/test/battle/move_effect_secondary/reflect.c new file mode 100644 index 0000000000..6a0dda06d8 --- /dev/null +++ b/test/battle/move_effect_secondary/reflect.c @@ -0,0 +1,32 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffect(MOVE_BADDY_BAD, MOVE_EFFECT_REFLECT) == TRUE); +} + +SINGLE_BATTLE_TEST("Baddy Bad sets up Reflect when it was succesful") +{ + bool32 moveSuccess; + PARAMETRIZE { moveSuccess = FALSE; } + PARAMETRIZE { moveSuccess = TRUE; } + + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BADDY_BAD, hit: moveSuccess); } + } SCENE { + if (moveSuccess == TRUE) + { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BADDY_BAD, player); + MESSAGE("Reflect made your team stronger against physical moves!"); + } else { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BADDY_BAD, player); + MESSAGE("Reflect made your team stronger against physical moves!"); + } + } + } +} From 5560f339d03c4098dd4d361e16921a4079ad489c Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 22 Dec 2024 00:26:46 +0100 Subject: [PATCH 28/45] Remove unused various (#5851) --- include/constants/battle_script_commands.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 54052e5390..c4797e94ae 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -187,7 +187,6 @@ enum CmdVarious VARIOUS_TERRAIN_SEED, VARIOUS_MAKE_INVISIBLE, VARIOUS_ROOM_SERVICE, - VARIOUS_EERIE_SPELL_PP_REDUCE, VARIOUS_JUMP_IF_TEAM_HEALTHY, VARIOUS_TRY_HEAL_QUARTER_HP, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED, From 570c6521d9d16c34ad00309e1002ebc5b214d944 Mon Sep 17 00:00:00 2001 From: Cafe <46283144+Cafeei@users.noreply.github.com> Date: Sun, 22 Dec 2024 21:43:24 +0400 Subject: [PATCH 29/45] Misc pokemon sprite fixes (#5846) --- graphics/pokemon/ariados/anim_front.png | Bin 1397 -> 1289 bytes graphics/pokemon/diggersby/anim_front.png | Bin 1436 -> 1417 bytes graphics/pokemon/diggersby/back.png | Bin 830 -> 757 bytes graphics/pokemon/diggersby/shiny.pal | 2 +- graphics/pokemon/duraludon/overworld.png | Bin 1141 -> 796 bytes graphics/pokemon/honedge/anim_front.png | Bin 1102 -> 1066 bytes graphics/pokemon/honedge/back.png | Bin 548 -> 485 bytes graphics/pokemon/honedge/normal.pal | 14 +++++++------- graphics/pokemon/maractus/back.png | Bin 880 -> 794 bytes graphics/pokemon/pichu/spiky_eared/front.png | Bin 481 -> 0 bytes .../pokemon/pichu/spiky_eared/overworld.png | Bin 472 -> 620 bytes graphics/pokemon/pincurchin/anim_front.png | Bin 1097 -> 1047 bytes .../pokemon/species_info/gen_1_families.h | 5 +++-- src/data/pokemon_graphics/front_pic_anims.h | 12 +++++++++++- 14 files changed, 22 insertions(+), 11 deletions(-) delete mode 100644 graphics/pokemon/pichu/spiky_eared/front.png diff --git a/graphics/pokemon/ariados/anim_front.png b/graphics/pokemon/ariados/anim_front.png index 945c4d188f301dfeeaca1073eaad560fa684855a..82d947054b8448b7206c6294c27f8ee71c0b8081 100644 GIT binary patch delta 1223 zcmV;&1UUQk3W*Ak7#0Wv0001tU!Pb20004VQb$4nuFf3kks&^R1cymPK~!jg?U>uv zvnmWlfkil|?fXCOKav2V6-&SFt38^#Rx=GD1Qy2p>}NM-zx8)t60F0wfE$9Hi0%$B z6`ge>g1rr{8Abpm`zZhsUA)KOsr-UM2(K^l_oo6d2v>l4e~p0R@y{5DoSy?|2uDB^ z=%hab=oEov|I5^WUIXZqZi#8yzpI3#WtKEJ)J?Y}OUPwrx=V1;9H3PyyaKXVo3vd-l%>@6vz} ztorZfWeI{akR^nhjsyzPTLozP`1|kzK+ZWQdg0trwcL@ay{6l~& zAe%MzTo5vF9vW!~Y3Lu|oi%8qPc?0sO93b$4E-emUK6+vJ?AXxVZ(EH;F zU3@%?r=sUtD1>9sM?fut$K$nJ_RxDL^e=ADClaUNaRHDS&`lr1a{`_)DVgp0*sflQ zRNCQxc$<}gIFRk~sh>MV1H%Ys&p1Q$w*WJY?Pvc(`{~A?Zv5%S2Kdi(W6^zo)Qz3) z`-^VOdF^%I$GWkTeML8Z;IGPaE4pt{-8V1#L^pP_Pj%mf={&p0($F?K&h2L?n2;0?o9ZBV%iIk)8;F|;bN~j`Liq%@m=eG zM}(^_vI`;J6S(bon^Kj|yK;p{cDZ7?LqsAjfhxXh_3h^!xj(oGfW<1Bd@tqOD=cp9 zH-xC}s@_}q9we3$28b9@t`Ca8s&AvGniva!q`h5_pcb$C7xgWVT&#MJq(NR?A;9S+ z%2|Dvr=d)MN@(Ze*J97XhBzgb<002ovPDHLkV1fj4Qy~BV delta 1332 zcmV-414zIR?c*gj1LR0g#AWh2{j z69FY-Z#W$Ml&kEVcau!8UyB47UK&~N92QM53Y)#-dD>Tu9nXc%A_q?;NqjyW>bw9w z1ntGbIXufqdslWWAE#FKvma@Hmr zJYphk)>-8dK-UuspkO!9H6nB~bxXjeK;LSr`57pY zn^P`Uh$(yDp5{QLtAAgh^Ctm_ z2m<6K#j=kl0P}?Ys=Ix3ZX2#R>5iiF3|+*@JuBB`A8>(fXgCZ&mK1-3jBZTJOFVnH_hJ9J8&u#{DkBAk300&Zx3Bv0!@ zm{;Vm-f3OmcHK`#vmRyDLqPcEcIEW?_t~2kl`NYpe2`Yhd$UI+p>Z>aK2(=9?xg?; z9(40TH~%ZTxk9>lpKgDm=$7~BCi;p{ey?r@vPilqzvn!KEME0XMz)(QtR-I-he`z? zQCI_69D-4et6~7~W$_*7pn;a;V{b?ylCW~}puI>a;a7eRo=`;%U*=VNu*i2=EMv@^E*M3S%>A*^iI*_Q*v{iXo0P5VS*2In752MGSD%xZ%k?r&=Cu+=E~ z<52#AQ@0=h9rC6o`||*=NK7#&0QMC(DD|yA0cwGGi}8OzsPEGt1-mE!mlx=YEd6i9 zgh4ifaZhd5*M#yCOYY>(iU>2J9b|&;__g?VM>Ed%zlCR~KNjYdfq|6_EdwCTPcZ)qz+~xvv;G0QM)wUUk<}Rh0000 z<0=eAEul+r`v1RoN&?K)X`HI_a%OnwOijF(g#ZCN$ML^!VC`F-H4GsH>b}|1hO1!@ zpb$P1I&EpK-T?Q6l{#Ptz<_u|V3811anM5>0%7`kL11At{Rrr?NQgPci6E>RLSP>B zMD)S}sQQT@I=?%A>5rol2(dl`lYW87FMg#wwgL2nqF3+6JbadVB7!!6meA;10M^l? zBy0n)XyF3@ks3WULz=(WN}x%Po%|rz*(CFSxRm|j8K5Ta<;Ou00${Yi32+TKa;r~0 zY30nC^bimLGXR;dM09{ep!V&`e28eofH6kkajB?62O#QyV>d*aVi=;Tvb0IGRA2|t zQGGCrDyzO;E>|hSYu-WXgDe4@yCtcys$de9Hzq;_=uHneLOi)9x;Df<1Xbzv7Pk?Y z+mULUvIm_7lf4(tHV2riGOMes=Ph3JgFj$@2QpkXk70f=BY;~8xt z+J_PN(#x*^vB85F&kQ(iB#H85u)oWZ>j0{6fD?XBIN>}`e=`;RdgKSd`=@ES<38nR|Dv}@L&Qgd(d>@OTfc_KBPf>|NOkI4FPN?;oY>S`U&tb z1?klDUK4l=U?Hpln|fP~A||{(__lQ3G(t?ZG=1d4iW~E|0#@8r6PyzYI-U4V|W?N4(5+Nc2v$DttV7UR9|CCbZlOCeF2f@ihXkIU}0_23@>xI4)A+mCQ zVLq$)2r@G-&njuqO-*E_1f%-tl5@tz?=kFvdwtq{$?PL!Ho)~hSMn_&bpY~tCRz%A zUlLCbAfFBsL1YOix9oDDVda;277Wl3n9h6|paYcZ-hcJqMfs&-@EOEl%&X=={k||3X6GMF#f$3t5iA2mfN+QT*VL z7iEkH(HO1Cpl%6N><7PzuMLFH zPOaGwB{xL8G7v_yxdTYIkCKnV6aq1?^tQ#Py|n&Xmn#wGjSdW8n`N-%m4BP{Ahv0000< KMNUMnLSTZN!hn(h delta 1371 zcmV-h1*H0k3!Dp(7zqRe0000r9~PbbnU_00X4Rxo*8Y1@U5H18W_d>T8OTo5E&p)DM(1^u=3BMJqrvYm1ES$ z&t-@i(5J^H0DBqj$N;h=8=?nge7cj6cbJ2O>KhXxgNnfXFQY_fupux2S~WxxZL;-H zKd;#U28dOUM)*N>WiJ{wfsm;l9;ko8q7CLU1X2DAd`tVieM)@<_U1H&3V=8?e(zPV zz6cOdWBM3GE1%j$ly}HpC5_uqOTW^?bN}V2F_Vxx`x5R zXON$%A|Z+maA~{FvmAbeJUc_@9wx>r3C1sh6d!~TGnk@NzKNYs0GJVYk1~JAuWwRW zwz7F2t5grC8h{A^PoV^$ki*DIpnIfi0>~bvqcYz&S*f!K83DNde#2Qv4lo*9u&H`n+7;e{M_BgR7;q zk8MR-VA%?!22dd;tALl)fPA$C3?aT<{vno2k>dVw`0;ev64OwKEnI)Ln{FU1%?%Lr z_+Kb2aRMF-!>vSOn=JqmS>hc|!At3^I?^AWeI8F!> zZmWA=1CBFB0rK8=UndCkrP@O+0xdcAsVqW{!JPx;OCWDG>(5UrUk7(H8`0r4-93w4 zfKM5tG2I9sr<1Am&uTzG52V=aZxoPDguc4DsDKWZw*8LL{`-F%OFP1224Kb~NgdeU zWcz;n(+qN~y~i;DZ)AvZH?!-Q&p^J|!>`LvEr%)=(2S7LP zr6|I*d>z(-z^Z@MROD=4Y3Ee{a;BC8?bEun?^wP2=p;81Ca}K|nn0Ia7zslgfEJhX z20DLjBn+jyr!F8XCCqMCTd+Y?0;Pn>YAd=UH;U>Ew&7k$nBN*#duL#Q76H;3yp}s5 zX%!%6PszzFnUe>OTrm?$XJ})8gP#50M;j89dlmpopD-D4Pl2|kC^d_ z7|YJ5sx3!j{Q02)GRE`65JV1oqP`yErZ-z!N{m@zLvRyViUJdtyr=+z2~X^xN@EpV d>5l)%{sK3xp0s_iF6jUO002ovPDHLkV1l+Fc?|#n diff --git a/graphics/pokemon/diggersby/back.png b/graphics/pokemon/diggersby/back.png index 36a4373816244f47b4aff340d91a6009b4dfd1a0..a1cc29260da624ce9402617900bedbd8e662e64c 100644 GIT binary patch delta 700 zcmV;t0z>`22K5Dy7#0Wv0001;w}I>c0004VQb$4nuFf3kkvG{00C5{SN@-Y?ITzyVsue$pO^B4}cs2a@xN;2&mowRG(`bJ|cjea?WeVY611t zkDb)=eP(L%fCobF z{{ldN{;1evt0~!ML zSCnB00U))L90Qe-158Kps_%QfTJQkXUx_sp>4gvgc9-gsrXt*$+wFhdLR3LS@D@73 ztwc=?EaYDRM3K`@_zEDD?JPV3B$#ZG*g^vwtNsBX!9pK05tDAc5{XcjXA80-+)kQ6 z61A%Vbc0&PQ6EK&1pq=@7JsMmzPHOtYT=L?hdGC&7Xv^gcnjzyNSA8>tA%!}(NZk| zT|djCNzmH~okuZe<^X@d^_J)&!FV`CP+K?yqCvboLAN_vziPh)ivgkseIuy5Ha2p# zZ32)^TeV-9IUo>ef3Y-t0cb6SIdeJBley&FK}1Ble@ikwn;i(Nmd_T2^_gnxY8yy% zWJ?oCE@>&{95FI8p}RDII){_K)HwC$te`tLFra{q6hXwdyc2&~&>KMCswx5`TyFUs z({8?m`(rgYR8Iy%3)AQFC%}?!EqtM;6|h>M&j2=#7XoPd7tb6cOxJKvA}!xbR2?Ji zxq<3PW7&Q~Hyj|u2I-Aj)Hfg?xY-r=jjDB^#0Yl!7_eb@IPExo3n*h0Ey316w*0FJ ij1mMtPyc@te*hFVwL{ENcu?Q~00006*4dY delta 773 zcmV+g1N!{+1-=H57$yV*00013M{Ml?0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuDblczAG;NFIOL^9R%b000SaNLh0L01m?d01m?e$8V@)0007)Nkl*zRy&{en3keU4} z%YwianZhhPzxlpzSCXBN)XhKoqj>x=fa!%d47i}Tz4?D2aHD}yJPafj@Mi-A0}Xg{ zKfWezLkMQt0fKnePdEXHW%yAHfW){TfB-S(5db|27sM2ek;AnF3WNms%Aqeo0-^Ho z<`TG&pahUe4-IrB=m-SRIYxo%Lookx5s^G#?vLa`NQ^HWgai<9d*z{kFpBV%l zD-sBVdcc237yyZo!P0DK2@6c(m@aEH(ExNKV1R%C9P4=`RzN+nyGsuPczV~EN)HYA zdT#7ax*i7C0L;vc@GyW4YeK*<5UtG~y{7}f&YuhbQv;+sdoltxa>+Zu{-G1XypA|WN>1Gb3-;;Ncr3`G z=2T3Dh~qhP+*%tt?o_lnvlkJ=os+7=HFye9O~SyIzf=-=gBc|d+BSWOF5g7F1>Rr; zsw_z?5aQdpOl$Pc6;QVr;al}=B(jF3tyC5Ou8+^>^63l+McF1ydDbXvClNq(cq+^C zRF!|fvakCcq+B`^Kq1?A>J|t5E%#Va+U5puahd-q%c3Ywr?NQw-t)J8stgElwt4$Q z^ozp*e;#r7%>o&|w%gS^byWSN?FVDA6d&K&_6yNzbjVr&P8X1mCe2I)tk0ePqipC9 z+biHjO-heuErIGvfv-rSl?gCH)z84&Rl-fTEA^XDLgkkc&K=@q z0B{&x^QmXi1@6CNqwLc2 z00NpxL_t(oh3%Hza_b-rgwYB_L)!HH-}a1zHckKLu8R)}-`~cf8{^ z@Spjsfr~%G-}3X>{d34uI)7chyrjS7=kJTFFygvExWHSYKjnmrcmgA?DZ<1;FYqSq zSx(GNoa!U40oGV2h1>)_$BBPgys;yGpFp3ZnZUM6@Hpwn!o1qPi1!J^1TL2_<|gnd zt_%F(7vSq|1ZWdF7h@{Mo z#^c0HWF}*$1UeBtz*DUvV6Z++-Qf8V*LPf`h(?jZhx%Nu9w*xY-=2J{Fyg6-2t;&! znPG1C%dH~bT?)HE9Gb=FkPUQ!J?&=vh$oa%t8NRM->W|QH9){^iRyJ8fi}!|1Y8b? z0L9jsx%8h8@PyiRsZ)P4x29f&M>rR*RBUHO3RN!r2v>>8x`VY-gbr6WfMn;CMqYEa z@<3wh#sVXbT%@9G+fz`bWIVuam#_=O#Og_I_|ZX3AJpjNDDNJgt1wzWUJ$BzC?Hpo zowE#l6KD#H_S@lmL;Q33Iv-Z|HF`j=Awf~)~6^sH^A!$rJ zAm#}w(QaCcuMl#-&@H$*oht15W&(PJ&E}sA?AuF|gg*QYpM1@0aM|@aIP1FSoNXhg z1^nRY`@Gj7dRukq0VB?bl zds1d`ZaWd)TVp#W@LJ%IItomk%o28zW(8VQUtxf!wL~xP#`h&xxWfea9q)K5{sFU+ V9N8^vPb~ld002ovPDHLkV1lq0X3YQq delta 1087 zcmV-F1i<^82K5M#7zqRe0002CwraMKE*b;9w7ro_8-It?YC8Y`1OQ1yK~#9!?Uqe! z8&wd;=j}RKmymkBaorF#%6g5J8W1*e2*|XORkaroA_C>cg)1Lw)k}J;5aLz|sp5nL zLgIh`p&aO`ZsLTN?=&t+Rivit4NYn{O4bW;6Q|w}-hO#^U*pmWj(u{x@27b?|DD;H zaR45z|9@#w|Mf=dUmQNeKa60{4#r(w^Y$&x8b0v)J3l8F@*M0?T;e(TC-1xOH86o>A>J0KW^N+HxyPR}=h zV!a~U>6yEUh(5S}DE@`N4E>CvO*EoY>O9`KagT~C+I;);ZyQ5=)w`WZtu1kk0?}~O zO@EQ_V)>^dzMKSEh#th>;RMG!f^B7Ib6n9Uxi&M$K}#u^(yzPkfMV}lTU9vk#RQmx z@q&3hHb$|#3BrT|zrO|$!+%WM8khTutwkAl=jIK?ihxU6jkh2;@0H-C zl3My1cFIL4N+$Q^poK3jpmWxNR(;>syaCZNW4H5-1GBuI1ZLvWHgb=KMu5bE=4~<#b>&_E4d-;!&y4-F=%&|h~yl?(|^i~=1J_RWY7Xrg>a81-% zt!>7P z1^v^tD>zmOgsk3%=ymu>(6002ovPDHLk FV1jdb6j}fP diff --git a/graphics/pokemon/honedge/anim_front.png b/graphics/pokemon/honedge/anim_front.png index 9a5dc7507809643b91813b1243b272fcc0da2d32..6376e2d1e2cd5341e14d258126bfcc07f5f67603 100644 GIT binary patch delta 1057 zcmV++1m6432&xE>7=H)@0001tU!Pb20004VQb$4nuFf3k0000mP)t-sn9!gIFgPS< zl@JgRP(UdE*Mzm6T8L;kX5sx{z}Qe&Sg5F|*x1-(R8YyegQtsbd`OVh000B1Nkl zwTOTT@PIME27eBM4;B$~J1m@lK7tQE1Z!>Zb_%drHy@<55yS;>o4^GiD}fmpN(&DoH88-fzUiT+3JN%~+LRRF zM&AG+1Aw5ajdmdlqR}@!gj@n;K!P9wYy6r)J+7=PW|dj-TKO`u!^AZGO+PqYB)9wb0L2@IdqEkLAYBbo1? zzP5?iQzQ*2C!zB@LB5pEQvgs;LXTVt&8tA$*gavjuM*8;V8k0)`;Bk>r!n?W-00^l z>_u;;jd=3nuyPk*%WcGL0_w%r0M4!G)rc9UVy1Kk(gdyrlbt&)K{0e6On%@fP8@4>H1IoUWP6mD$bWK80K`!MU58Lp$c-%eI0g_xlIQiQg6;Chez5_^^epz9t|kNGWWg5zn!|Jp z^mV=f$nV2RK)I`dc>qM&L^+Og0Eh~p0q^}25%YD`?1-i*++4T~5$>-1#t4gc{u+B7 b&=davmHRj;z3%8T00000NkvXXu0mjfXvx&! delta 1093 zcmV-L1iJgG2+jzQ7=Hu<0000QD42jyh*&ri^S8kO000SaNLh0L01m_e01m_fl`9S# z000BTNklD(*6ox5KlK=sg(m@(SE%s30V8Ver+6A@X0R!sfmeg?bQG;fk`goG1bHt;vWeGR?eSZIYzj=HQ zp|8hqYTxXLlZRHKL@0S^1L`ewKpY$3K$4b4;em!MDSptgx+O(WbC6XdU>Q)X5gen> z04zn6*-pS&0)IssE1;-|vhV+B1N?yf@w>kQ3`O{iJ>f5zUj&pHV=qE}#vT^~r!RWl zGj@^zh9ZJf|EFGb#!j6A03Q$DMXv+ad6of&D(Urm|L1p|VgL=UM#I4)0JN0_z~C+I zWLL&$l?EI{(GCEufNhP+`>Ww!R^WOx{D{`Tw#MfGSAQE||8h%X0Kn?6N@Sn&3qund zpwBsnAF4M+01x*xAZPc0;b;R80vbY%>AF^J!>Yy%2=^|8O52Os9g*u&16sqIr|x1g z`xK~(8&u!pWRJTd79tNUZIDSq55OpBRBGT(;?9PuqRKnc@y3OsVzTbzuFGmHJnx9} zbKc;tqJQfI>nbj%y)fVdMy^EPB9V32SD0HoVfO0BzG*-(|9ip4BbXhxLMoDEqM zGKr}-SsZ~vx7o`XU0F6!RX5(4x|1W`cop@Wdq7rWH9?*PjqfAKfA7jvt}_JyTx~=g z^(eY`Dj!BGn__K5Oh3JGl@H7RluW2L!thnBE`JNA+6dDNw2|~=Y>4L$HVJ$^U+z$9 zk7LVd%+5j0HsWE;px6qO>n-~hQU3M84uBooODHpY0u5MgzyY({M1y0i04B>dqVV{> z|I89D`|PRs=W%g7U<@9JlR^UGPZO#RPb|Q1G4T#rL5kA1?D;Qo7XWjer8+qj<1t8_ zc7Kdkz%=_#DOU>7F#7;JR|1?))2Ru7J{x-Lz;cl$2A~u{nR=&a7XYXUWomocYGIUsGNWv*X{)&zKs3sJ z?M;Q8n7_Qtf1D&jE-as>2GUt^9O3D7q71hsmqDh9ZR+8agi>|@Zlp~D=036* zTY-2k#;FZx&xJ7D`5ZBa-OBa|;>BirGoRdoSd?Pdag@ diff --git a/graphics/pokemon/honedge/back.png b/graphics/pokemon/honedge/back.png index d9092fa13a9e1c27158ebbca4e775be35a96b629..b1bc8634b008040a9f88b58110ae3254d552fd38 100644 GIT binary patch delta 412 zcmV;N0b~B81my#e7#0Wv0001;w}I>c0004VQb$4nuFf3kkv=|u0b@x-K~z|U?Uu`O z!ypVr%~Lk?|G&2*0SOME2$-~sR*Q_YILB9#@%T9Y>!YQVQd_vzS}!XIHwJ&!c%4wS zC@B1@f%pwU#nbhyA@K!Uh|mZo4R;>@T5ER%);i}V44E$i0Oz&@czf@?d0JlZ~!Xv<(02KiE z2!!{7iocyD+*rvVoniAiP)Ar297fQCOu+Q;SwY>y?+ZqTTCg+(UQi6%0%izG>+3wv z^I8|2xp={_2Xz&})%`YpI|N0nAOa`A{znn29>(vKzgpktk{WGq-HoyU0000VGd00DhTL_t(Y$Ia9|Zi6rs0AM4KvZlU4Nr#M7 zmRhM|_1Ta#CiY{<(0X8bAMeiy^8Ze7H^$>M zz8~Xp7EcgBAxaSt#Bl~Lg0YpLL|NlgCOZZ>Z#CzN{AH-A~&FyU_BoIt}f3*kkPvfm=?Nw&WAw? z2LWj+Hk|he{RL6Bgf=zt43UZUa6Wf}E)M(LEL(PK*oJIBO0Br)syuc)X zV6|eRsH(&RR<%-!+2FJWU7?skyitrX;s&MCVE^S@Bvhz$0#zRe!1sZ8Kv6cPf(L|8 zMX6wj=4gXfP_g1Df%TY0Fb)AYSIE^rhz@?HK=a_p&8?LaJUAif3N|2 z1n4dYL2pw*ypvlLOr?|`7O)o)>;P;l&p>zC15yG(77@VfQ~7Cu-dFpFhmapmY2jkR S8MWI00000p diff --git a/graphics/pokemon/honedge/normal.pal b/graphics/pokemon/honedge/normal.pal index 51f60119df..d6a8a50995 100644 --- a/graphics/pokemon/honedge/normal.pal +++ b/graphics/pokemon/honedge/normal.pal @@ -3,17 +3,17 @@ JASC-PAL 16 152 208 160 8 48 56 -0 128 160 +36 103 149 16 16 16 80 64 40 -248 208 128 -176 152 88 +255 215 132 +181 158 90 136 104 56 -152 232 248 +102 225 253 96 192 216 80 88 88 168 168 168 216 216 216 -48 56 40 -152 128 80 -136 88 56 +99 84 80 +201 185 131 +167 139 110 diff --git a/graphics/pokemon/maractus/back.png b/graphics/pokemon/maractus/back.png index bc83adca5ccf5e6a8a9173e177bfb49087baf7bf..66a652084021503e0b559f98905f10b185ec28bb 100644 GIT binary patch delta 724 zcmV;_0xSLS2AT$t7#0Wv0001;w}I>c0004VQb$4nuFf3kkv=|u0+>leK~z|U?Uu_D zq#z7M#eliI{{MHU5*|dQO31mnV9XEcz=6ogIhQ4%-K!bXkEy_^rS-50Li^eQ=m{8TTjrZd2u@N_ zoWiBv7}Woq@c~$WQ%W_Jw;3>5bVaX(8pEE5b={#?1mvpAb@IrqZO~cOEx7SIhUpYEqokFOUc>=Naz87*4hDpI{yEnf0YLA8X7UrDS#`G?8LbA)9A$w8h^HI^wLfn2(1M78A~OQK5@IZX zhc+w#NnHhmNE8G>%&}me^^!-MI)E6F_mL_35Y>M_!~mghv5CA3q;p|HW8w3 z^50$P^#d2K2r{sAYe#DZU}Jo8;(V$RfIwxN$6%d*^rtiv delta 810 zcmV+_1J(SR2Ji-u7$yV*00013M{Ml?0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuE-e010qNS#tmY4#NNd4#NS*Z>VGd00PNLL_t(Y$JLa-Yui8+$IoOD%@TQOmJB&4 zWN5&kP&v+$!D%R^n*}K}lR++YDJb{^rXZRodKLB57Akuwc#&^1WH6DpLbeWVNWjbe zFMTJ8)+bphbnABzr+Xj0AKyDf3aaQjDG`Q$)(Fw*_F4(>mQp0Dl!|hIZmwP9qXf_p zpt_)R`-h%XD+na9ab;cWRhesPmy|xRtQQhoQm9gu`v_Rye|7IWNDbU={0e%9^iIyzb$!%)^K$9WacOmfs z^~SOmQvjqHm{ZFD*RqaOA8-iPGnof}({xGzAW9c=Owk)n-Dt?z41t>B69RqgzQ->b z(a`K6qxy)4eDf>;I5)!S-eAgR6BW=v8e#CU(b*kd@{5>zxfGhGF&2*v+ujXBKH?E6 z%6H?BUE6Ml1I|b1wIZ+@^G7zyz_{OSFN=@tM23N8bzbKI4JSzAoz$sf4M;10bXXZc z0uy^=nU*v`G`67s79jp2AbnV!`~|q=4_?aAk#X@U^styiu27I4P?E z#4z@nVfZvw2}r|r7~#>!2Twk=2D2Pt%5Y2y}MB{QV~Z_gxcte;}QJzk6&qmH?y7jT!g59cMVnR|q0>Nir_?PY#_z z3w|Kos>>8Xbk=eT3D{|Blmz$(>wO;ZnUh)RBM<>EdY!fCXb|Av;0{0zTm*hsV5~-# ol)wawK;#j)3xI-&|0Y6y0a*>lqc@&Zy8r+H07*qoM6N<$g2IekVgLXD diff --git a/graphics/pokemon/pichu/spiky_eared/front.png b/graphics/pokemon/pichu/spiky_eared/front.png deleted file mode 100644 index 15b9201a2701daab43812595a4a6b1d14e2690cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmV<70UrK|P)tPlVI0AflIgIX!}?v#{^d+z4V=6jTjARxUdDF6Tf_I0wH00009 za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2MjX?!4P%g0003*Nkl*%9r)81<}Hhy{pc*g{o2M>Kr{1|A?nG9yB~0lY!CBJluy1RjE` z#OQNoP;c?@{q)^;XUmMO>wi}kRC&ttAh3~(FuG*CWPaatdwiBseDyxT&g+FUqce>AzY( XOsY)IQbIt300000NkvXXu0mjfro+1G diff --git a/graphics/pokemon/pichu/spiky_eared/overworld.png b/graphics/pokemon/pichu/spiky_eared/overworld.png index 7208db51085002bc11051917cabc0defcd65b66d..36c10400037084e2af39461b6998976580236f0e 100644 GIT binary patch delta 593 zcmcb?{D#G-Gr-TCmrII^fq{Y7)59f*fq@aoWKiH>29l@B!>$1-#^NA%Cx&(BWL^R} z1`|~^>VY&I{BJKX2C8}G>EalY(fD@y#VlP#9@o2uo#knAfBx^^dt~F%fXO_}y0rz( z1qH6Yi=J65&B;Xuyo~xkRy)>v99Z72Q1jjFAp^&KU-{26wvTQ7iVrxN*lvmcV%s#M z{$-1~&7;e!u1UF0s4rj;{j16@=-)b$CnSQFdAz=X1hcz{nc*s_^yhUQoe=9%&G2|pYo;6vD;bRq!ib+f%7!imzL>yp6}AO zoO3wTSk0PNxa!aOPesPDVGGpnFr}cn+I8C2cC&E&vE!=SInJKh$!vJMut%v>#*abry5#(Qj}|R<>xxzquDg9h zYVK9dX3pa$@67Q3K6O%|q^n1QyPgxC z5R_GWcx`xT ze?$Fmr$j=(x7RE5a9_`FVdQ&MBb@0Gr4OrvLx| delta 444 zcmV;t0Ym=m1lR*5iBL{Q4GJ0x0000DNk~Le0002M0000W1Oos70JgSjwg3PCB#|;G ze;7yD*Z=?lZ%IT!RCt{2)WJ%_KoADtSxWBRH7kgx1i@=Vo}gt+>rJJt;LVcc9u<56 zU%;csf_U%QmvdLKnVs!Mq&;Q|ft^3hx6QTz=&P^3`s(YTC4-3=?mODf76}u!OCgi* z>z3I8%JB9~sdQ*BNdOe-PyRdB1I;4Of4V?*rWcENJHP`~YH|WF(6)|TfPo6f<}+yr zx}X_o@(JC50|G?zDs#5XKvfo4;Hn+qfi@3=Fh`X12stP;B3`r|4tlu@0+@8wK2aaE z4aBP;_*WhwmQ#8p9E5m=GbA^#fe_nuIFIlJk<9ZzIC;hK8)K33r2qqY?t!LJj|ANT1A)J+ m`N03?9Nbae>Hhh_>I(@PV*$uc4mxuH00002$u+u7#Roy0001tU!Pb2000DMK}|sb0I`mI`%#mTdp>^yl1W5CRA_p0Gm6?|`{#^ig0{!T?zOIs*W|G(e1?`4uo*O;|f2#<&46geu^y z68ahVN`M$KHUNeYpu8N+^U8p!o_|t|qehfUt&uIw;0yfQT3n5gekwEaVab zXcnT4-U;4={pY$7*a)GArh70}oM;3VKquI^9!$wh{yV|m2GH!ueCMzL;x>uzj6V=U zl@P0z`Fw=hz|w;Hb~Ya|V!%N{p9dn&W+|55MfSg_aWx`(+T$N;hy@)W2oQ?UOzsck-L7`GU zl=B&Eilq(9g~U$8sTjUiqm$&Wn){0|UyR-fI!sltm4pup`gtCPunb}9N_cKnccE26 zrg1V;2(e$;15D6N5xC~pYl)f0VXwDV>r<^FrA$3X>}P))>azfQX16z^e?ZC{Bpec& z0H#E5{sEP0bP0zAWugvHLI<#;oJc##!y4~-(v&l`u2I_i2b9YvZNoCZ&B6Aa4%`Xd zKj1Q#RN7%0kJJmRezB2s&9$%p%5@kd>Sl06+LaHz6iOtNa<&FkfK>lLccP|eQqYGL zDU50Ibf53me6JjVp!3n_N9}Jx=Er=26bRF5< zXYU_KUkuDTu{@klM*uC7ocRYtX9DbIz~}yf@Tap`Dthz}x|vk|WO7pOIv-T9+xrJ0 z#?e2>In(Y?I?NyagP3>zK~h6vyiFa)=pV$re?S@+&p7A)!Q{>P*guf(`UmV}^AGG< zX+AH#1T(9DVCTOV1ZP1_ zK>z@;j|==^1(7j6e*ghuOGiWihy@);000ARNklBjE6vs~(Lx(#^Jao%o zw{$C*D2XWXl$36T&|rIMmYO_4u%}?((yk%-0wpGMTjEcU(&f^Sw8IIm4J3>7U3yQF zZAo{HDBaq;$@cr}z5jbU$v;Bw;~x&EOi*k7rNC*F2{!H$f4GEH0R_&2U9i$5omgNo z5?`~jnFyT6rl3+s0bd0a)E=4DD;v5*g%43sg-yf8B3Z7Zpo@Zz-y}}KMr~oGv5*R? zz?)97i}Pgr#V)CKIl!>f-mbnfY(DIbpxp(31b(}*+C>-nsDcN(fYEL|;^3Qec07QN z&UayB4g7s`f6l7zp-cDxJ>cASL$*hl)nPB7OL%d5q<3X;prh?^6bwhYi8Vjm9YGqs z_LkXzcVHIW8!j3OcP`lNdi=R*{x z^&1B{5^Y{!VAHnDQp7mb1 z>tEb8-GIBzig|rp!zC45fi*deHS2xKRw)yZyBplcef)XIGJz<`vl0Q7B?4JyfzCdu z{O{qcMfxEm`JhQ_7Rg8vTVP(%*o0uZkzz%2S`kI)K@btqAT;VQL8HW^AWRmo$A|(J zrHdBSe>N-)0!CzTj#VhNMLlLAL319te!8RAmIn9`9a`n)5F2g@asy#Dji7I=7*4YOU-xe_3s5rLh$A!;R*LAk_R2itILjAU{Nx zUEW82c#Zs!KT_|-c0Y)i5C>dsJ(3Bs5&-sC71tR4K|3j7^@`EP)z~}r>e8BVkP}ou&8Gg9_9Y2U` zT!DU1S@SrIT Date: Sun, 22 Dec 2024 22:39:07 +0000 Subject: [PATCH 30/45] Fixes Regenerator healing past maxHP (#5861) --- src/battle_script_commands.c | 6 ++-- test/battle/ability/regenerator.c | 50 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 test/battle/ability/regenerator.c diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 25d1f78996..21ed966dd1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -15121,10 +15121,10 @@ static void Cmd_switchoutabilities(void) break; case ABILITY_REGENERATOR: { - u32 regenerate = GetNonDynamaxMaxHP(gBattlerAttacker) / 3; + u32 regenerate = GetNonDynamaxMaxHP(battler) / 3; regenerate += gBattleMons[battler].hp; - if (gBattleStruct->moveDamage[gBattlerAttacker] > gBattleMons[battler].maxHP) - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[battler].maxHP; + if (regenerate > gBattleMons[battler].maxHP) + regenerate = gBattleMons[battler].maxHP; BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_HP_BATTLE, 1u << *(gBattleStruct->battlerPartyIndexes + battler), sizeof(regenerate), diff --git a/test/battle/ability/regenerator.c b/test/battle/ability/regenerator.c new file mode 100644 index 0000000000..0f1b432772 --- /dev/null +++ b/test/battle/ability/regenerator.c @@ -0,0 +1,50 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Regenerator heals 1/3 of max HP upon switching out") +{ + u32 currHP; + PARAMETRIZE { currHP = 1; } + PARAMETRIZE { currHP = 2; } + PARAMETRIZE { currHP = 3; } + GIVEN { + PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_REGENERATOR); HP(currHP); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + } SCENE { + SWITCH_OUT_MESSAGE("Slowbro"); + SEND_IN_MESSAGE("Wobbuffet"); + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Slowbro"); + } THEN { + EXPECT_EQ(player->hp, player->maxHP / 3 + currHP); + } +} + +SINGLE_BATTLE_TEST("Regenerator heals 1/3 of max HP upon switching out but doesn't surpass max HP") +{ + u32 currHP; + PARAMETRIZE { currHP = 5; } + PARAMETRIZE { currHP = 4; } + PARAMETRIZE { currHP = 3; } + PARAMETRIZE { currHP = 2; } + PARAMETRIZE { currHP = 1; } + GIVEN { + PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_REGENERATOR); HP(currHP); MaxHP(5); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + } SCENE { + SWITCH_OUT_MESSAGE("Slowbro"); + SEND_IN_MESSAGE("Wobbuffet"); + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Slowbro"); + } THEN { + EXPECT_LE(player->hp, player->maxHP); + } +} From e883b7c2512540ff5df71abf867a7571ed45ae8f Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 22 Dec 2024 19:39:17 -0300 Subject: [PATCH 31/45] Fixed Wish triggering Disguise (#5860) --- data/battle_scripts_1.s | 2 +- test/battle/ability/disguise.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d94ba2363b..752c352022 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6738,7 +6738,7 @@ BattleScript_WishComesTrue:: playanimation BS_TARGET, B_ANIM_WISH_HEAL printstring STRINGID_PKMNWISHCAMETRUE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE healthbarupdate BS_TARGET datahpupdate BS_TARGET printstring STRINGID_PKMNREGAINEDHEALTH diff --git a/test/battle/ability/disguise.c b/test/battle/ability/disguise.c index 3a8df70be5..9c5f917e9d 100644 --- a/test/battle/ability/disguise.c +++ b/test/battle/ability/disguise.c @@ -173,3 +173,19 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu blocks a move after getting Gastro Acid Ba ABILITY_POPUP(player, ABILITY_DISGUISE); } } + +SINGLE_BATTLE_TEST("Disguise does not break from a teammate's Wish") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_WISH].effect == EFFECT_WISH); + PLAYER(SPECIES_JIRACHI); + PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); HP(219); MaxHP(220); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WISH); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WISH, player); + NOT ABILITY_POPUP(player, ABILITY_DISGUISE); + } +} From f9fed98665607626866ecd88458734c224ae288e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 22 Dec 2024 19:39:48 -0300 Subject: [PATCH 32/45] Fixed MOVE_EFFECT_FREEZE_OR_FROSTBITE not being usable in battle scripts (#5859) --- include/constants/battle.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index d9c4e1301c..a7300e6517 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -331,7 +331,11 @@ #define MOVE_EFFECT_TOXIC 6 #define MOVE_EFFECT_FROSTBITE 7 #define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_FROSTBITE // All above move effects apply primary status -#define MOVE_EFFECT_FREEZE_OR_FROSTBITE (B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE) +#if B_USE_FROSTBITE == TRUE +#define MOVE_EFFECT_FREEZE_OR_FROSTBITE MOVE_EFFECT_FROSTBITE +#else +#define MOVE_EFFECT_FREEZE_OR_FROSTBITE MOVE_EFFECT_FREEZE +#endif #define MOVE_EFFECT_CONFUSION 8 #define MOVE_EFFECT_FLINCH 9 #define MOVE_EFFECT_TRI_ATTACK 10 From caa35be7e78583c897c34aedbce7fdd93f94bdad Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Sun, 22 Dec 2024 22:41:13 +0000 Subject: [PATCH 33/45] Fixes Pursuit + Emergency Exit causing double switches and Pursuit user fainting causing target to not finish switch (#5849) --- src/battle_main.c | 17 +++++++-- test/battle/move_effect/pursuit.c | 63 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index a324ec9173..cfd630a1f6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3230,6 +3230,13 @@ void SwitchInClearSetData(u32 battler) gBattleStruct->boosterEnergyActivates &= ~(1u << battler); gBattleStruct->canPickupItem &= ~(1u << battler); + if (gBattleStruct->pursuitTarget & (1u << battler)) + { + gBattleStruct->pursuitTarget = 0; + gBattleStruct->pursuitSwitchByMove = FALSE; + gBattleStruct->pursuitStoredSwitch = 0; + } + for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) { // Switched into sticky web user slot, so reset stored battler ID @@ -3360,9 +3367,13 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[battler][1] = 0; gBattleStruct->lastTakenMoveFrom[battler][2] = 0; gBattleStruct->lastTakenMoveFrom[battler][3] = 0; - gBattleStruct->pursuitTarget = 0; - gBattleStruct->pursuitSwitchByMove = FALSE; - gBattleStruct->pursuitStoredSwitch = 0; + + if (gBattleStruct->pursuitTarget & (1u << battler)) + { + gBattleStruct->pursuitTarget = 0; + gBattleStruct->pursuitSwitchByMove = FALSE; + gBattleStruct->pursuitStoredSwitch = 0; + } gBattleStruct->palaceFlags &= ~(1u << battler); gBattleStruct->boosterEnergyActivates &= ~(1u << battler); diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c index 5dfa3f8e33..a20b1ed1d1 100644 --- a/test/battle/move_effect/pursuit.c +++ b/test/battle/move_effect/pursuit.c @@ -610,4 +610,67 @@ SINGLE_BATTLE_TEST("Pursuit attacks a switching foe and switchin is correctly st } } +SINGLE_BATTLE_TEST("Pursuit doesn't cause mon with Emergency Exit to switch twice") +{ + GIVEN { + PLAYER(SPECIES_GOLISOPOD) { HP(101); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_VOLTORB); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); SEND_OUT(player, 2); } + } SCENE { + SWITCH_OUT_MESSAGE("Golisopod"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + ABILITY_POPUP(player, ABILITY_EMERGENCY_EXIT); + SEND_IN_MESSAGE("Voltorb"); + } THEN { + EXPECT_EQ(player->species, SPECIES_VOLTORB); + } +} + +SINGLE_BATTLE_TEST("Pursuit user gets forced out by Red Card and target still switches out") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_RED_CARD].holdEffect == HOLD_EFFECT_RED_CARD); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } + PLAYER(SPECIES_VOLTORB); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_VOLTORB); + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("The opposing Voltorb was dragged out!"); + SEND_IN_MESSAGE("Voltorb"); + } THEN { + EXPECT_EQ(player->species, SPECIES_VOLTORB); + EXPECT_EQ(opponent->species, SPECIES_VOLTORB); + } +} + +SINGLE_BATTLE_TEST("Pursuit user faints to Life Orb and target still switches out") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_VOLTORB); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); HP(1); } + OPPONENT(SPECIES_VOLTORB); + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); SEND_OUT(opponent, 1); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + HP_BAR(opponent); + MESSAGE("The opposing Wobbuffet fainted!"); + SEND_IN_MESSAGE("Voltorb"); + } THEN { + EXPECT_EQ(player->species, SPECIES_VOLTORB); + EXPECT_EQ(opponent->species, SPECIES_VOLTORB); + } +} + TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority"); From 8cb2f3196140968f850a1b23f9fd4cea56546c51 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 23 Dec 2024 09:51:19 -0300 Subject: [PATCH 34/45] Removed redundant call to FillPalBufferBlack in FRLG whiteout sequence (#5854) --- src/field_screen_effect.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 073c92f3e0..e07d067afc 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -1374,7 +1374,6 @@ static void Task_RushInjuredPokemonToCenter(u8 taskId) ClearWindowTilemap(windowId); CopyWindowToVram(windowId, COPYWIN_MAP); RemoveWindow(windowId); - FillPalBufferBlack(); FadeInFromBlack(); gTasks[taskId].tState = FRLG_WHITEOUT_HEAL_SCRIPT; break; From 8edf14423af21cec70a7b9978255080c1e5b6474 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 23 Dec 2024 19:51:35 +0100 Subject: [PATCH 35/45] Refactors argument into a union (#5853) Co-authored-by: Eduardo Quezada --- include/battle_ai_util.h | 2 +- include/battle_util.h | 2 +- include/pokemon.h | 20 +- src/battle_ai_main.c | 2 +- src/battle_ai_util.c | 30 +-- src/battle_anim_new.c | 2 +- src/battle_dynamax.c | 12 +- src/battle_main.c | 2 +- src/battle_script_commands.c | 44 ++-- src/battle_util.c | 16 +- src/data/moves_info.h | 229 +++++++++--------- test/battle/ability/cud_chew.c | 2 +- test/battle/ai/ai_check_viability.c | 4 +- test/battle/gimmick/dynamax.c | 64 ++--- test/battle/hold_effect/attack_up.c | 2 +- test/battle/hold_effect/critical_hit_up.c | 2 +- test/battle/hold_effect/defense_up.c | 2 +- test/battle/hold_effect/micle_berry.c | 2 +- test/battle/hold_effect/special_attack_up.c | 2 +- test/battle/hold_effect/special_defense_up.c | 2 +- test/battle/hold_effect/speed_up.c | 2 +- test/battle/move_effect/change_type_on_item.c | 2 +- .../battle/move_effect/fail_if_not_arg_type.c | 12 +- test/battle/move_effect/fixed_damage_arg.c | 4 +- test/battle/move_effect/heal_pulse.c | 2 +- test/battle/move_effect/powder.c | 2 +- test/battle/move_effect/revelation_dance.c | 4 +- test/battle/move_effect/semi_invulnerable.c | 12 +- test/battle/move_effect/shed_tail.c | 2 +- test/battle/move_effect/smelling_salts.c | 2 +- test/battle/move_effect/sparkling_aria.c | 2 +- test/battle/move_effect/two_turns_attack.c | 6 +- test/battle/move_effect/wake_up_slap.c | 2 +- .../double_power_on_arg_status.c | 4 +- .../move_effects_combined/barb_barrage.c | 2 +- test/battle/move_effects_combined/hurricane.c | 6 +- .../move_effects_combined/infernal_parade.c | 2 +- test/battle/sleep_clause.c | 20 +- 38 files changed, 271 insertions(+), 260 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 729d173933..7cfc28e5d6 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -116,7 +116,7 @@ bool32 HasOnlyMovesWithCategory(u32 battlerId, u32 category, bool32 onlyOffensiv bool32 HasMoveWithCategory(u32 battler, u32 category); bool32 HasMoveWithType(u32 battler, u32 type); bool32 HasMoveEffect(u32 battlerId, u32 moveEffect); -bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument); +bool32 IsPowerBasedOnStatus(u32 battlerId, u32 effect, u32 argument); bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect); bool32 HasMoveWithCriticalHitChance(u32 battlerId); bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception); diff --git a/include/battle_util.h b/include/battle_util.h index 20a228eef6..adeb850061 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -297,7 +297,7 @@ bool32 IsGen6ExpShareEnabled(void); bool32 MoveHasAdditionalEffect(u32 move, u32 moveEffect); bool32 MoveHasAdditionalEffectWithChance(u32 move, u32 moveEffect, u32 chance); bool32 MoveHasAdditionalEffectSelf(u32 move, u32 moveEffect); -bool32 MoveHasAdditionalEffectSelfArg(u32 move, u32 moveEffect, u32 argument); +bool32 IsMoveEffectRemoveSpeciesType(u32 move, u32 moveEffect, u32 argument); bool32 MoveHasChargeTurnAdditionalEffect(u32 move); bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef); bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef); diff --git a/include/pokemon.h b/include/pokemon.h index 8a618f5fe1..f05332163e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -495,6 +495,24 @@ struct MoveInfo u8 powerOverride; } zMove; + union { + struct { + u16 stringId; + u16 status; + } twoTurnAttack; + struct { + u16 side; + u16 property; // can be used to remove the hardcoded values + } protect; + u32 status; + u16 moveProperty; + u16 holdEffect; + u16 type; + u16 fixedDamage; + u16 absorbPercentage; + u16 maxEffect; + } argument; + s32 priority:4; u32 recoil:7; u32 strikeCount:4; // Max 15 hits. Defaults to 1 if not set. May apply its effect on each hit. @@ -548,8 +566,6 @@ struct MoveInfo u32 sketchBanned:1; u32 padding:5; // end of word - u32 argument; - // primary/secondary effects const struct AdditionalEffect *additionalEffects; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 99706f4d73..ce3d71ca95 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4327,7 +4327,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_SOAK: - if (HasMoveWithType(battlerAtk, TYPE_ELECTRIC) || HasMoveWithType(battlerAtk, TYPE_GRASS) || (HasMoveEffect(battlerAtk, EFFECT_SUPER_EFFECTIVE_ON_ARG) && gMovesInfo[move].argument == TYPE_WATER) ) + if (HasMoveWithType(battlerAtk, TYPE_ELECTRIC) || HasMoveWithType(battlerAtk, TYPE_GRASS) || (HasMoveEffect(battlerAtk, EFFECT_SUPER_EFFECTIVE_ON_ARG) && gMovesInfo[move].argument.type == TYPE_WATER) ) ADJUST_SCORE(DECENT_EFFECT); // Get some super effective moves break; case EFFECT_THIRD_TYPE: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 95d3adafc8..dc51b5ae15 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -470,11 +470,11 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy return TRUE; break; case EFFECT_FAIL_IF_NOT_ARG_TYPE: - if (!IS_BATTLER_OF_TYPE(battlerAtk, gMovesInfo[move].argument)) + if (!IS_BATTLER_OF_TYPE(battlerAtk, gMovesInfo[move].argument.type)) return TRUE; break; case EFFECT_HIT_SET_REMOVE_TERRAIN: - if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) && gMovesInfo[move].argument == ARG_TRY_REMOVE_TERRAIN_FAIL) + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) && gMovesInfo[move].argument.moveProperty == ARG_TRY_REMOVE_TERRAIN_FAIL) return TRUE; break; case EFFECT_POLTERGEIST: @@ -566,7 +566,7 @@ static inline void CalcDynamicMoveDamage(struct DamageCalculationData *damageCal expected = minimum = gBattleMons[damageCalcData->battlerAtk].level * (abilityAtk == ABILITY_PARENTAL_BOND ? 2 : 1); break; case EFFECT_FIXED_DAMAGE_ARG: - expected = minimum = gMovesInfo[move].argument * (abilityAtk == ABILITY_PARENTAL_BOND ? 2 : 1); + expected = minimum = gMovesInfo[move].argument.fixedDamage * (abilityAtk == ABILITY_PARENTAL_BOND ? 2 : 1); break; case EFFECT_MULTI_HIT: if (move == MOVE_WATER_SHURIKEN && gBattleMons[damageCalcData->battlerAtk].species == SPECIES_GRENINJA_ASH) @@ -2027,7 +2027,7 @@ bool32 HasMoveEffect(u32 battlerId, u32 effect) return FALSE; } -bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument) +bool32 IsPowerBasedOnStatus(u32 battlerId, u32 effect, u32 argument) { s32 i; u16 *moves = GetMovesArray(battlerId); @@ -2036,7 +2036,7 @@ bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument) { if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && gMovesInfo[moves[i]].effect == effect - && (gMovesInfo[moves[i]].argument & argument)) + && (gMovesInfo[moves[i]].argument.status & argument)) return TRUE; } @@ -2477,7 +2477,7 @@ bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move) case EFFECT_SOLAR_BEAM: case EFFECT_TWO_TURNS_ATTACK: return !(AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_POWER_HERB - || (AI_GetWeather(AI_DATA) & gMovesInfo[move].argument)); + || (AI_GetWeather(AI_DATA) & gMovesInfo[move].argument.twoTurnAttack.status)); default: return FALSE; } @@ -3229,7 +3229,7 @@ bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move)) { // using item or user goes first - u32 healPercent = (gMovesInfo[move].argument == 0) ? 50 : gMovesInfo[move].argument; + u32 healPercent = (gMovesInfo[move].argument.absorbPercentage == 0) ? 50 : gMovesInfo[move].argument.absorbPercentage; s32 healDmg = (healPercent * damage) / 100; if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) @@ -3847,7 +3847,7 @@ void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT)) ADJUST_SCORE_PTR(WEAK_EFFECT); // stall tactic - if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PSN_ANY) + if (IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PSN_ANY) || HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH) || AI_DATA->abilities[battlerAtk] == ABILITY_MERCILESS) ADJUST_SCORE_PTR(DECENT_EFFECT); @@ -3874,8 +3874,8 @@ void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) ADJUST_SCORE_PTR(WEAK_EFFECT); } - if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN) - || HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN)) + if (IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN) + || IsPowerBasedOnStatus(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN)) ADJUST_SCORE_PTR(WEAK_EFFECT); } } @@ -3892,7 +3892,7 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) u32 defSpeed = AI_DATA->speedStats[battlerDef]; if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe - || HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PARALYSIS) + || IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PARALYSIS) || (HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FIRST_TURN_ONLY)) // filter out Fake Out || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION || gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) @@ -3917,8 +3917,8 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) && !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK))) ADJUST_SCORE_PTR(WEAK_EFFECT); - if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP) - || HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP)) + if (IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP) + || IsPowerBasedOnStatus(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP)) ADJUST_SCORE_PTR(WEAK_EFFECT); } @@ -3958,8 +3958,8 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score ADJUST_SCORE_PTR(WEAK_EFFECT); } - if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE) - || HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE)) + if (IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE) + || IsPowerBasedOnStatus(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE)) ADJUST_SCORE_PTR(WEAK_EFFECT); } } diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 50bb83305f..38597b19b3 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -9244,7 +9244,7 @@ void AnimTask_DynamaxGrowth(u8 taskId) // from CFRU void AnimTask_GetWeatherToSet(u8 taskId) { - switch (gMovesInfo[gCurrentMove].argument) + switch (gMovesInfo[gCurrentMove].argument.maxEffect) { case MAX_EFFECT_SUN: gBattleAnimArgs[ARG_RET_ID] = 1; diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 98ee89af9b..876f1e532b 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -320,7 +320,7 @@ u8 GetMaxMovePower(u32 move) { u8 tier; // G-Max Drum Solo, G-Max Hydrosnipe, and G-Max Fireball always have 160 base power. - if (gMovesInfo[GetMaxMove(gBattlerAttacker, move)].argument == MAX_EFFECT_FIXED_POWER) + if (gMovesInfo[GetMaxMove(gBattlerAttacker, move)].argument.maxEffect == MAX_EFFECT_FIXED_POWER) return 160; // Exceptions to all other rules below: @@ -470,7 +470,7 @@ void ChooseDamageNonTypesString(u8 type) // Returns the status effect that should be applied by a G-Max Move. static u32 GetMaxMoveStatusEffect(u32 move) { - u8 maxEffect = gMovesInfo[move].argument; + u8 maxEffect = gMovesInfo[move].argument.maxEffect; switch (maxEffect) { // Status 1 @@ -522,7 +522,7 @@ void BS_SetMaxMoveEffect(void) { NATIVE_ARGS(); u16 effect = 0; - u8 maxEffect = gMovesInfo[gCurrentMove].argument; + u8 maxEffect = gMovesInfo[gCurrentMove].argument.maxEffect; // Don't continue if the move didn't land. if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) @@ -541,7 +541,7 @@ void BS_SetMaxMoveEffect(void) if (!NoAliveMonsForEitherParty()) { // Max Effects are ordered by stat ID. - SET_STATCHANGER(gMovesInfo[gCurrentMove].argument, 1, FALSE); + SET_STATCHANGER(gMovesInfo[gCurrentMove].argument.maxEffect, 1, FALSE); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies; effect++; @@ -569,7 +569,7 @@ void BS_SetMaxMoveEffect(void) break; default: // Max Effects are ordered by stat ID. - statId = gMovesInfo[gCurrentMove].argument - MAX_EFFECT_LOWER_ATTACK + 1; + statId = gMovesInfo[gCurrentMove].argument.maxEffect - MAX_EFFECT_LOWER_ATTACK + 1; break; } SET_STATCHANGER(statId, stage, TRUE); @@ -618,7 +618,7 @@ void BS_SetMaxMoveEffect(void) case MAX_EFFECT_PSYCHIC_TERRAIN: { u32 statusFlag = 0; - switch (gMovesInfo[gCurrentMove].argument) + switch (gMovesInfo[gCurrentMove].argument.moveProperty) { case MAX_EFFECT_MISTY_TERRAIN: statusFlag = STATUS_FIELD_MISTY_TERRAIN; diff --git a/src/battle_main.c b/src/battle_main.c index cfd630a1f6..c23fc30040 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5957,7 +5957,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost) } break; case EFFECT_CHANGE_TYPE_ON_ITEM: - if (holdEffect == gMovesInfo[move].argument) + if (holdEffect == gMovesInfo[move].argument.holdEffect) return ItemId_GetSecondaryId(heldItem); break; case EFFECT_REVELATION_DANCE: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 21ed966dd1..ac29c893e4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4070,7 +4070,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) case MOVE_EFFECT_REMOVE_ARG_TYPE: // This seems unnecessary but is done to make it work properly with Parental Bond BattleScriptPush(gBattlescriptCurrInstr + 1); - switch (gMovesInfo[gCurrentMove].argument) + switch (gMovesInfo[gCurrentMove].argument.type) { case TYPE_FIRE: // Burn Up gBattlescriptCurrInstr = BattleScript_RemoveFireType; @@ -4082,7 +4082,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) gBattlescriptCurrInstr = BattleScript_RemoveGenericType; break; } - RemoveBattlerType(gEffectBattler, gMovesInfo[gCurrentMove].argument); + RemoveBattlerType(gEffectBattler, gMovesInfo[gCurrentMove].argument.type); break; case MOVE_EFFECT_ROUND: TryUpdateRoundTurnOrder(); // If another Pokémon uses Round before the user this turn, the user will use Round directly after it @@ -5987,7 +5987,7 @@ static void Cmd_moveend(void) } else if (IsBattlerAlive(gBattlerAttacker) && MoveResultHasEffect(gBattlerTarget)) { - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * gMovesInfo[gCurrentMove].argument / 100)); + gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * gMovesInfo[gCurrentMove].argument.absorbPercentage / 100)); gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE; effect = TRUE; @@ -6205,18 +6205,18 @@ static void Cmd_moveend(void) } break; case MOVE_EFFECT_REMOVE_STATUS: // Smelling salts, Wake-Up Slap, Sparkling Aria - if ((gBattleMons[gBattlerTarget].status1 & gMovesInfo[gCurrentMove].argument) + if ((gBattleMons[gBattlerTarget].status1 & gMovesInfo[gCurrentMove].argument.status) && IsBattlerAlive(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { - gBattleMons[gBattlerTarget].status1 &= ~(gMovesInfo[gCurrentMove].argument); + gBattleMons[gBattlerTarget].status1 &= ~(gMovesInfo[gCurrentMove].argument.status); BtlController_EmitSetMonData(gBattlerTarget, 0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerTarget].status1); MarkBattlerForControllerExec(gBattlerTarget); effect = TRUE; BattleScriptPush(gBattlescriptCurrInstr); - switch (gMovesInfo[gCurrentMove].argument) + switch (gMovesInfo[gCurrentMove].argument.status) { case STATUS1_PARALYSIS: gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal; @@ -6520,7 +6520,7 @@ static void Cmd_moveend(void) if (gMultiHitCounter == 0) { BattleScriptPushCursor(); - if (gMovesInfo[gCurrentMove].argument == MOVE_EFFECT_SCALE_SHOT && !NoAliveMonsForEitherParty()) + if (gMovesInfo[gCurrentMove].argument.moveProperty == MOVE_EFFECT_SCALE_SHOT && !NoAliveMonsForEitherParty()) gBattlescriptCurrInstr = BattleScript_ScaleShot; else gBattlescriptCurrInstr = BattleScript_MultiHitPrintStrings; @@ -10419,7 +10419,7 @@ static void Cmd_various(void) case VARIOUS_SET_ARG_TO_BATTLE_DAMAGE: { VARIOUS_ARGS(); - gBattleStruct->moveDamage[gBattlerTarget] = gMovesInfo[gCurrentMove].argument; + gBattleStruct->moveDamage[gBattlerTarget] = gMovesInfo[gCurrentMove].argument.fixedDamage; break; } case VARIOUS_TRY_AUTOTOMIZE: @@ -10691,14 +10691,14 @@ static void Cmd_various(void) case VARIOUS_TRY_THIRD_TYPE: { VARIOUS_ARGS(const u8 *failInstr); - if (IS_BATTLER_OF_TYPE(battler, gMovesInfo[gCurrentMove].argument) || GetActiveGimmick(battler) == GIMMICK_TERA) + if (IS_BATTLER_OF_TYPE(battler, gMovesInfo[gCurrentMove].argument.type) || GetActiveGimmick(battler) == GIMMICK_TERA) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[battler].types[2] = gMovesInfo[gCurrentMove].argument; - PREPARE_TYPE_BUFFER(gBattleTextBuff1, gMovesInfo[gCurrentMove].argument); + gBattleMons[battler].types[2] = gMovesInfo[gCurrentMove].argument.type; + PREPARE_TYPE_BUFFER(gBattleTextBuff1, gMovesInfo[gCurrentMove].argument.type); gBattlescriptCurrInstr = cmd->nextInstr; } return; @@ -11365,7 +11365,7 @@ static void Cmd_setprotectlike(void) || (gCurrentMove == MOVE_WIDE_GUARD && B_WIDE_GUARD != GEN_5) || (gCurrentMove == MOVE_QUICK_GUARD && B_QUICK_GUARD != GEN_5)) { - if (!gMovesInfo[gCurrentMove].argument) // Protects one mon only. + if (!gMovesInfo[gCurrentMove].argument.protect.side) // Protects one mon only. { if (gMovesInfo[gCurrentMove].effect == EFFECT_ENDURE) { @@ -11922,8 +11922,8 @@ static void Cmd_setdrainedhp(void) { CMD_ARGS(); - if (gMovesInfo[gCurrentMove].argument != 0) - gBattleStruct->moveDamage[gBattlerAttacker] = (gHpDealt * gMovesInfo[gCurrentMove].argument / 100); + if (gMovesInfo[gCurrentMove].argument.absorbPercentage != 0) + gBattleStruct->moveDamage[gBattlerAttacker] = (gHpDealt * gMovesInfo[gCurrentMove].argument.absorbPercentage / 100); else gBattleStruct->moveDamage[gBattlerAttacker] = (gHpDealt / 2); @@ -12343,7 +12343,7 @@ static void Cmd_twoturnmoveschargestringandanimation(void) { CMD_ARGS(const u8 *animationThenStringPtr); - gBattleScripting.savedStringId = LOHALF(gMovesInfo[gCurrentMove].argument); + gBattleScripting.savedStringId = gMovesInfo[gCurrentMove].argument.twoTurnAttack.stringId; if (B_UPDATED_MOVE_DATA < GEN_5 || MoveHasChargeTurnAdditionalEffect(gCurrentMove)) gBattlescriptCurrInstr = cmd->animationThenStringPtr; else @@ -13586,7 +13586,7 @@ static void Cmd_tryspiteppreduce(void) { s32 ppToDeduct = B_PP_REDUCED_BY_SPITE >= GEN_4 ? 4 : (Random() & 3) + 2; // G-Max Depletion only deducts 2 PP. - if (IsMaxMove(gCurrentMove) && gMovesInfo[gCurrentMove].argument == MAX_EFFECT_SPITE) + if (IsMaxMove(gCurrentMove) && gMovesInfo[gCurrentMove].argument.maxEffect == MAX_EFFECT_SPITE) ppToDeduct = 2; if (gBattleMons[gBattlerTarget].pp[i] < ppToDeduct) @@ -14338,7 +14338,7 @@ static void Cmd_setsemiinvulnerablebit(void) if (gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].semiInvulnerableEffect == TRUE) { - u32 semiInvulnerableEffect = UNCOMPRESS_BITS(HIHALF(gMovesInfo[gCurrentMove].argument)); + u32 semiInvulnerableEffect = UNCOMPRESS_BITS(gMovesInfo[gCurrentMove].argument.twoTurnAttack.status); if (cmd->clear) gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect; else @@ -14362,7 +14362,7 @@ static bool32 CheckIfCanFireTwoTurnMoveNow(u8 battler, bool8 checkChargeTurnEffe // Certain two-turn moves may fire on the first turn in the right weather (Solar Beam, Electro Shot) // By default, all two-turn moves have the option of adding weather to their argument - if (IsBattlerWeatherAffected(battler, HIHALF(gMovesInfo[gCurrentMove].argument))) + if (IsBattlerWeatherAffected(battler, gMovesInfo[gCurrentMove].argument.status)) // TODO: Two Turn Moves affected by weather need a better rewrite return TRUE; return FALSE; @@ -15157,7 +15157,7 @@ static void Cmd_jumpifnotcurrentmoveargtype(void) u8 battler = GetBattlerForBattleScript(cmd->battler); const u8 *failInstr = cmd->failInstr; - if (!IS_BATTLER_OF_TYPE(battler, gMovesInfo[gCurrentMove].argument)) + if (!IS_BATTLER_OF_TYPE(battler, gMovesInfo[gCurrentMove].argument.type)) gBattlescriptCurrInstr = failInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -16929,7 +16929,7 @@ void BS_JumpIfArgument(void) { NATIVE_ARGS(u8 argument, const u8 *jumpInstr); - if (gMovesInfo[gCurrentMove].argument == cmd->argument) + if (gMovesInfo[gCurrentMove].argument.moveProperty == cmd->argument) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -16959,7 +16959,7 @@ void BS_SetRemoveTerrain(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; case EFFECT_HIT_SET_REMOVE_TERRAIN: - switch (gMovesInfo[gCurrentMove].argument) + switch (gMovesInfo[gCurrentMove].argument.moveProperty) { case ARG_SET_PSYCHIC_TERRAIN: // Genesis Supernova statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; @@ -17276,7 +17276,7 @@ void BS_TryHealPulse(void) { if (GetBattlerAbility(gBattlerAttacker) == ABILITY_MEGA_LAUNCHER && gMovesInfo[gCurrentMove].pulseMove) gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 75 / 100); - else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && gMovesInfo[gCurrentMove].argument == MOVE_EFFECT_FLORAL_HEALING) + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && gMovesInfo[gCurrentMove].argument.moveProperty == MOVE_EFFECT_FLORAL_HEALING) gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 2 / 3); else gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) / 2); diff --git a/src/battle_util.c b/src/battle_util.c index f43f285e93..900ebf2d6e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3464,7 +3464,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) case CANCELLER_THAW: // move thawing if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) { - if (!(MoveHasAdditionalEffectSelfArg(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) { gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; BattleScriptPushCursor(); @@ -3475,7 +3475,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && gMovesInfo[gCurrentMove].thawsUser) { - if (!(MoveHasAdditionalEffectSelfArg(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) { gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FROSTBITE; BattleScriptPushCursor(); @@ -8599,7 +8599,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) bool32 isProtected = FALSE; if ((IsZMove(move) || IsMaxMove(move)) - && (!gProtectStructs[battlerDef].maxGuarded || gMovesInfo[move].argument == MAX_EFFECT_BYPASS_PROTECT)) + && (!gProtectStructs[battlerDef].maxGuarded || gMovesInfo[move].argument.maxEffect == MAX_EFFECT_BYPASS_PROTECT)) isProtected = FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). else if (gProtectStructs[battlerDef].maxGuarded && IsMoveBlockedByMaxGuard(move)) isProtected = TRUE; @@ -8972,7 +8972,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData break; case EFFECT_DOUBLE_POWER_ON_ARG_STATUS: // Comatose targets treated as if asleep - if ((gBattleMons[battlerDef].status1 | (STATUS1_SLEEP * (abilityDef == ABILITY_COMATOSE))) & gMovesInfo[move].argument + if ((gBattleMons[battlerDef].status1 | (STATUS1_SLEEP * (abilityDef == ABILITY_COMATOSE))) & gMovesInfo[move].argument.status && !((gMovesInfo[move].additionalEffects->moveEffect == MOVE_EFFECT_REMOVE_STATUS) && DoesSubstituteBlockMove(battlerAtk, battlerDef, move))) { basePower *= 2; @@ -10435,7 +10435,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move if (moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED && mod == UQ_4_12(0.0)) mod = UQ_4_12(1.0); - if (gMovesInfo[move].effect == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == gMovesInfo[move].argument) + if (gMovesInfo[move].effect == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == gMovesInfo[move].argument.type) mod = UQ_4_12(2.0); if (moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(battlerDef) && mod == UQ_4_12(0.0)) mod = UQ_4_12(1.0); @@ -10573,7 +10573,7 @@ uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, { modifier = CalcTypeEffectivenessMultiplierInternal(move, moveType, battlerAtk, battlerDef, recordAbilities, modifier, defAbility); if (gMovesInfo[move].effect == EFFECT_TWO_TYPED_MOVE) - modifier = CalcTypeEffectivenessMultiplierInternal(move, gMovesInfo[move].argument, battlerAtk, battlerDef, recordAbilities, modifier, defAbility); + modifier = CalcTypeEffectivenessMultiplierInternal(move, gMovesInfo[move].argument.type, battlerAtk, battlerDef, recordAbilities, modifier, defAbility); } if (recordAbilities) @@ -11748,9 +11748,9 @@ bool32 MoveHasAdditionalEffectSelf(u32 move, u32 moveEffect) return FALSE; } -bool32 MoveHasAdditionalEffectSelfArg(u32 move, u32 moveEffect, u32 argument) +bool32 IsMoveEffectRemoveSpeciesType(u32 move, u32 moveEffect, u32 argument) { - return (gMovesInfo[move].argument == argument) && MoveHasAdditionalEffectSelf(move, moveEffect); + return (gMovesInfo[move].argument.type == argument) && MoveHasAdditionalEffectSelf(move, moveEffect); } bool32 MoveHasChargeTurnAdditionalEffect(u32 move) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 49d35c0897..1b845368ab 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -17,11 +17,6 @@ #define BINDING_TURNS "2 to 5" #endif -/* First arg is the charge turn string id, second arg depends on effect -EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP: semi-invulnerable STATUS3 to apply to battler -EFFECT_TWO_TURNS_ATTACK/EFFECT_SOLAR_BEAM: weather in which to skip charge turn */ -#define TWO_TURN_ARG(stringid, ...) (stringid) __VA_OPT__(| ((__VA_ARGS__) << 16)) - // Shared Move Description entries const u8 gNotDoneYetDescription[] = _( @@ -438,7 +433,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .windMove = B_EXTRAPOLATED_MOVE_FLAGS, - .argument = TWO_TURN_ARG(STRINGID_PKMNWHIPPEDWHIRLWIND), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNWHIPPEDWHIRLWIND }, .contestEffect = CONTEST_EFFECT_AFFECTED_BY_PREV_APPEAL, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, @@ -586,7 +581,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNFLEWHIGH, COMPRESS_BITS(STATUS3_ON_AIR)), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -1332,7 +1327,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 20, + .argument = { .fixedDamage = 20 }, .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, @@ -1874,7 +1869,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, .contestEffect = CONTEST_EFFECT_STARTLE_PREV_MON, @@ -1896,7 +1891,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .zMove = { .powerOverride = 120 }, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, @@ -1999,7 +1994,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .category = DAMAGE_CATEGORY_SPECIAL, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNTOOKSUNLIGHT, B_WEATHER_SUN), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKSUNLIGHT, .status = B_WEATHER_SUN }, .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, @@ -2151,7 +2146,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_4) || (B_UPDATED_MOVE_FLAGS < GEN_3), - .argument = 40, + .argument = { .fixedDamage = 40 }, .contestEffect = CONTEST_EFFECT_BETTER_WHEN_LATER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = COMBO_STARTER_DRAGON_RAGE, @@ -2370,7 +2365,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNDUGHOLE, COMPRESS_BITS(STATUS3_UNDERGROUND)), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = COMPRESS_BITS(STATUS3_UNDERGROUND) }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -2986,7 +2981,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ACC_UP_1 }, - .argument = STATUS2_FOCUS_ENERGY, + .argument = { .status = STATUS2_FOCUS_ENERGY }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, @@ -3343,7 +3338,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .makesContact = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNLOWEREDHEAD), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNLOWEREDHEAD }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_DEF_PLUS_1, .self = TRUE, @@ -3622,7 +3617,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .makesContact = TRUE, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, @@ -3673,7 +3668,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .criticalHitStage = B_UPDATED_MOVE_DATA >= GEN_3, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(B_UPDATED_MOVE_DATA >= GEN_4 ? STRINGID_CLOAKEDINAHARSHLIGHT : STRINGID_PKMNISGLOWING), + .argument.twoTurnAttack = { .stringId = B_UPDATED_MOVE_DATA >= GEN_4 ? STRINGID_CLOAKEDINAHARSHLIGHT : STRINGID_PKMNISGLOWING }, #if B_UPDATED_MOVE_DATA >= GEN_3 .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, @@ -5155,7 +5150,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .healingMove = B_HEAL_BLOCKING >= GEN_6, .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, @@ -6735,7 +6730,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = STATUS1_PARALYSIS, + .argument = { .status = STATUS1_PARALYSIS }, .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_STATUS, @@ -7391,7 +7386,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNHIDUNDERWATER, COMPRESS_BITS(STATUS3_UNDERWATER)), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = COMPRESS_BITS(STATUS3_UNDERWATER) }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_DIVE, @@ -8599,7 +8594,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNSPRANGUP, COMPRESS_BITS(STATUS3_ON_AIR)), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, @@ -9048,7 +9043,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = STATUS1_SLEEP, + .argument = { .status = STATUS1_SLEEP }, .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_STATUS, @@ -10268,7 +10263,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .makesContact = TRUE, .punchingMove = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, @@ -11272,7 +11267,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = HOLD_EFFECT_PLATE, + .argument = { .holdEffect = HOLD_EFFECT_PLATE }, .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -11702,7 +11697,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_VANISHEDINSTANTLY, COMPRESS_BITS(STATUS3_PHANTOM_FORCE)), + .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), @@ -11752,7 +11747,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_USER, .priority = 3, .category = DAMAGE_CATEGORY_STATUS, - .argument = TRUE, // Protects the whole side. + .argument = { .protect.side = TRUE, }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .snatchAffected = TRUE, .ignoresProtect = TRUE, @@ -11867,7 +11862,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = STATUS1_PSN_ANY, + .argument = { .status = STATUS1_PSN_ANY }, .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, @@ -12513,7 +12508,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_USER, .priority = 3, .category = DAMAGE_CATEGORY_STATUS, - .argument = TRUE, // Protects the whole side. + .argument = { .protect.side = TRUE, }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .snatchAffected = TRUE, .ignoresProtect = TRUE, @@ -12642,7 +12637,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .zMove = { .powerOverride = 160 }, - .argument = STATUS1_ANY, + .argument = { .status = STATUS1_ANY }, .contestEffect = CONTEST_EFFECT_BETTER_IF_SAME_TYPE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -12669,7 +12664,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNTOOKTARGETHIGH, COMPRESS_BITS(STATUS3_ON_AIR)), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -13249,7 +13244,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .makesContact = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, @@ -13585,7 +13580,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = HOLD_EFFECT_DRIVE, + .argument = { .holdEffect = HOLD_EFFECT_DRIVE }, .metronomeBanned = TRUE, .contestEffect = CONTEST_EFFECT_EXCITE_AUDIENCE_IN_ANY_CONTEST, .contestCategory = CONTEST_CATEGORY_COOL, @@ -13608,7 +13603,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = STATUS1_SLEEP, + .argument = { .status = STATUS1_SLEEP }, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .soundMove = TRUE, .metronomeBanned = TRUE, @@ -13766,7 +13761,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .metronomeBanned = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_CLOAKEDINAFREEZINGLIGHT), + .argument.twoTurnAttack = { .stringId = STRINGID_CLOAKEDINAFREEZINGLIGHT }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, @@ -13795,7 +13790,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .metronomeBanned = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_CLOAKEDINAFREEZINGLIGHT), + .argument.twoTurnAttack = { .stringId = STRINGID_CLOAKEDINAFREEZINGLIGHT }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BURN, .chance = 30, @@ -13946,7 +13941,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .zMove = { .powerOverride = 170 }, - .argument = TYPE_FLYING, + .argument = { .type = TYPE_FLYING }, .makesContact = TRUE, .minimizeDoubleDamage = TRUE, .gravityBanned = TRUE, @@ -13972,7 +13967,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_USER, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, - .argument = TRUE, // Protects the whole side. + .argument = { .protect.side = TRUE }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .snatchAffected = TRUE, .ignoresProtect = TRUE, @@ -14108,7 +14103,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_VANISHEDINSTANTLY, COMPRESS_BITS(STATUS3_PHANTOM_FORCE)), + .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), @@ -14133,7 +14128,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, - .argument = TYPE_GHOST, + .argument = { .type = TYPE_GHOST }, .zMove = { .effect = Z_EFFECT_ALL_STATS_UP_1 }, .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, @@ -14206,7 +14201,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_FOES_AND_ALLY, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .healingMove = B_HEAL_BLOCKING >= GEN_6, .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -14229,7 +14224,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, - .argument = TYPE_GRASS, + .argument = { .type = TYPE_GRASS }, .zMove = { .effect = Z_EFFECT_ALL_STATS_UP_1 }, .magicCoatAffected = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, @@ -14279,7 +14274,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = TYPE_WATER, + .argument = { .type = TYPE_WATER }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE, .chance = 10, @@ -14374,7 +14369,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 75, // restores 75% HP instead of 50% HP + .argument = { .absorbPercentage = 75 }, .makesContact = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, @@ -14398,7 +14393,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_USER, .priority = 3, .category = DAMAGE_CATEGORY_STATUS, - .argument = TRUE, // Protects the whole side. + .argument = { .protect.side = TRUE, }, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -14970,7 +14965,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .skyBattleBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKNMABSORBINGPOWER), + .argument.twoTurnAttack = { .stringId = STRINGID_PKNMABSORBINGPOWER }, .contestEffect = CONTEST_EFFECT_IMPROVE_CONDITION_PREVENT_NERVOUSNESS, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, @@ -15268,7 +15263,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 75, // restores 75% HP instead of 50% HP + .argument = { .absorbPercentage = 75 }, .healingMove = B_HEAL_BLOCKING >= GEN_6, .contestEffect = CONTEST_EFFECT_STARTLE_MON_WITH_JUDGES_ATTENTION, .contestCategory = CONTEST_CATEGORY_COOL, @@ -15510,7 +15505,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 2, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MOVE_FIRST_IMPRESSION, + .argument = { .moveProperty = MOVE_FIRST_IMPRESSION }, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_BETTER_IF_FIRST, .contestCategory = CONTEST_CATEGORY_COOL, @@ -15608,7 +15603,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_FOES_AND_ALLY, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = STATUS1_BURN, + .argument = { .status = STATUS1_BURN }, .ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6, .soundMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ @@ -15664,7 +15659,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RESET_STATS }, - .argument = MOVE_EFFECT_FLORAL_HEALING, + .argument = { .moveProperty = MOVE_EFFECT_FLORAL_HEALING }, .mirrorMoveBanned = TRUE, .healingMove = TRUE, .magicCoatAffected = TRUE, @@ -15739,7 +15734,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .slicingMove = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_PKMNTOOKSUNLIGHT, B_WEATHER_SUN), + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKSUNLIGHT, .status = B_WEATHER_SUN }, .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_TOUGH, .contestComboStarterId = 0, @@ -16056,7 +16051,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .thawsUser = TRUE, - .argument = TYPE_FIRE, + .argument = { .type = TYPE_FIRE }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_ARG_TYPE, .self = TRUE, @@ -16720,7 +16715,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = HOLD_EFFECT_MEMORY, + .argument = { .holdEffect = HOLD_EFFECT_MEMORY }, .makesContact = TRUE, .contestEffect = CONTEST_EFFECT_SCRAMBLE_NEXT_TURN_ORDER, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -16910,7 +16905,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = B_UPDATED_MOVE_DATA >= GEN_8 ? 100 : 50, // restores 100% HP instead of 50% HP + .argument = { .absorbPercentage = B_UPDATED_MOVE_DATA >= GEN_8 ? 100 : 50 }, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, .healingMove = B_HEAL_BLOCKING >= GEN_6, @@ -17273,7 +17268,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, - .argument = TYPE_PSYCHIC, + .argument = { .type = TYPE_PSYCHIC }, .magicCoatAffected = TRUE, .powderMove = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, @@ -18019,7 +18014,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .argument = ARG_TRY_REMOVE_TERRAIN_FAIL, // Remove a field terrain if there is one and hit, otherwise fail. + .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_FAIL }, // Remove a field terrain if there is one and hit, otherwise fail. .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -18042,7 +18037,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MOVE_EFFECT_SCALE_SHOT, + .argument = { .moveProperty = MOVE_EFFECT_SCALE_SHOT }, .contestEffect = CONTEST_EFFECT_NEXT_APPEAL_EARLIER, .contestCategory = CONTEST_CATEGORY_COOL, .contestComboStarterId = 0, @@ -18065,7 +18060,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, .instructBanned = TRUE, - .argument = TWO_TURN_ARG(STRINGID_METEORBEAMCHARGING), + .argument.twoTurnAttack = { .stringId = STRINGID_METEORBEAMCHARGING }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1, .self = TRUE, @@ -18971,7 +18966,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = STATUS1_PSN_ANY, + .argument = { .status = STATUS1_PSN_ANY }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON, .chance = 50, @@ -19083,7 +19078,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = STATUS1_ANY, + .argument = { .status = STATUS1_ANY }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BURN, .chance = 30, @@ -19446,7 +19441,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .argument = ARG_TRY_REMOVE_TERRAIN_HIT, // Remove the active field terrain if there is one. + .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one. .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, .battleAnimScript = gBattleAnimMove_IceSpinner, }, @@ -20028,7 +20023,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .makesContact = TRUE, .slicingMove = TRUE, .healingMove = TRUE, @@ -20051,7 +20046,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, .metronomeBanned = TRUE, - .argument = TYPE_ELECTRIC, + .argument = { .type = TYPE_ELECTRIC }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_ARG_TYPE, .self = TRUE, @@ -20330,7 +20325,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_BOTH, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = 50, + .argument = { .absorbPercentage = 50 }, .thawsUser = TRUE, .metronomeBanned = TRUE, .healingMove = B_EXTRAPOLATED_MOVE_FLAGS, @@ -20397,7 +20392,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = TWO_TURN_ARG(STRINGID_ELECTROSHOTCHARGING, B_WEATHER_RAIN), + .argument.twoTurnAttack = { .stringId = STRINGID_ELECTROSHOTCHARGING, .status = B_WEATHER_RAIN }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1, .self = TRUE, @@ -21021,7 +21016,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = ARG_SET_PSYCHIC_TERRAIN, // Set Psychic Terrain. If there's a different field terrain active, overwrite it. + .argument = { .moveProperty = ARG_SET_PSYCHIC_TERRAIN }, // Set Psychic Terrain. If there's a different field terrain active, overwrite it. .battleAnimScript = gBattleAnimMove_GenesisSupernova, }, [MOVE_SINISTER_ARROW_RAID] = @@ -21078,7 +21073,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = ARG_TRY_REMOVE_TERRAIN_HIT, // Remove the active field terrain if there is one. + .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one. .battleAnimScript = gBattleAnimMove_SplinteredStormshards, }, [MOVE_LETS_SNUGGLE_FOREVER] = @@ -21217,7 +21212,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_SUN, + .argument = { .maxEffect = MAX_EFFECT_SUN }, .battleAnimScript = gBattleAnimMove_MaxFlare, }, @@ -21233,7 +21228,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_SP_ATK, + .argument = { .maxEffect = MAX_EFFECT_LOWER_SP_ATK }, .battleAnimScript = gBattleAnimMove_MaxFlutterby, }, @@ -21249,7 +21244,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_ELECTRIC_TERRAIN, + .argument = { .maxEffect = MAX_EFFECT_ELECTRIC_TERRAIN }, .battleAnimScript = gBattleAnimMove_MaxLightning, }, @@ -21265,7 +21260,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_SPEED, + .argument = { .maxEffect = MAX_EFFECT_LOWER_SPEED }, .battleAnimScript = gBattleAnimMove_MaxStrike, }, @@ -21281,7 +21276,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RAISE_TEAM_ATTACK, + .argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_ATTACK }, .battleAnimScript = gBattleAnimMove_MaxKnuckle, }, @@ -21297,7 +21292,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_DEFENSE, + .argument = { .maxEffect = MAX_EFFECT_LOWER_DEFENSE }, .battleAnimScript = gBattleAnimMove_MaxPhantasm, }, @@ -21313,7 +21308,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_HAIL, + .argument = { .maxEffect = MAX_EFFECT_HAIL }, .battleAnimScript = gBattleAnimMove_MaxHailstorm, }, @@ -21329,7 +21324,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RAISE_TEAM_SP_ATK, + .argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_SP_ATK }, .battleAnimScript = gBattleAnimMove_MaxOoze, }, @@ -21345,7 +21340,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RAIN, + .argument = { .maxEffect = MAX_EFFECT_RAIN }, .battleAnimScript = gBattleAnimMove_MaxGeyser, }, @@ -21361,7 +21356,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RAISE_TEAM_SPEED, + .argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_SPEED }, .battleAnimScript = gBattleAnimMove_MaxAirstream, }, @@ -21377,7 +21372,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_MISTY_TERRAIN, + .argument = { .maxEffect = MAX_EFFECT_MISTY_TERRAIN }, .battleAnimScript = gBattleAnimMove_MaxStarfall, }, @@ -21393,7 +21388,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_ATTACK, + .argument = { .maxEffect = MAX_EFFECT_LOWER_ATTACK }, .battleAnimScript = gBattleAnimMove_MaxWyrmwind, }, @@ -21409,7 +21404,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_PSYCHIC_TERRAIN, + .argument = { .maxEffect = MAX_EFFECT_PSYCHIC_TERRAIN }, .battleAnimScript = gBattleAnimMove_MaxMindstorm, }, @@ -21425,7 +21420,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_SANDSTORM, + .argument = { .maxEffect = MAX_EFFECT_SANDSTORM }, .battleAnimScript = gBattleAnimMove_MaxRockfall, }, @@ -21441,7 +21436,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RAISE_TEAM_SP_DEF, + .argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_SP_DEF }, .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, .battleAnimScript = gBattleAnimMove_MaxQuake, }, @@ -21458,7 +21453,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_SP_DEF, + .argument = { .maxEffect = MAX_EFFECT_LOWER_SP_DEF }, .battleAnimScript = gBattleAnimMove_MaxDarkness, }, @@ -21474,7 +21469,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_GRASSY_TERRAIN, + .argument = { .maxEffect = MAX_EFFECT_GRASSY_TERRAIN }, .battleAnimScript = gBattleAnimMove_MaxOvergrowth, }, @@ -21490,7 +21485,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RAISE_TEAM_DEFENSE, + .argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_DEFENSE }, .battleAnimScript = gBattleAnimMove_MaxSteelspike, }, @@ -21506,7 +21501,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_VINE_LASH, + .argument = { .maxEffect = MAX_EFFECT_VINE_LASH }, .battleAnimScript = gBattleAnimMove_GMaxVineLash, }, @@ -21522,7 +21517,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_WILDFIRE, + .argument = { .maxEffect = MAX_EFFECT_WILDFIRE }, .battleAnimScript = gBattleAnimMove_GMaxWildfire, }, @@ -21538,7 +21533,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_CANNONADE, + .argument = { .maxEffect = MAX_EFFECT_CANNONADE }, .battleAnimScript = gBattleAnimMove_GMaxCannonade, }, @@ -21554,7 +21549,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_EFFECT_SPORE_FOES, + .argument = { .maxEffect = MAX_EFFECT_EFFECT_SPORE_FOES }, .battleAnimScript = gBattleAnimMove_GMaxBefuddle, }, @@ -21570,7 +21565,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_PARALYZE_FOES, + .argument = { .maxEffect = MAX_EFFECT_PARALYZE_FOES }, .battleAnimScript = gBattleAnimMove_GMaxVoltCrash, }, @@ -21586,7 +21581,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_CONFUSE_FOES_PAY_DAY, + .argument = { .maxEffect = MAX_EFFECT_CONFUSE_FOES_PAY_DAY }, .battleAnimScript = gBattleAnimMove_GMaxGoldRush, }, @@ -21602,7 +21597,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_CRIT_PLUS, + .argument = { .maxEffect = MAX_EFFECT_CRIT_PLUS }, .battleAnimScript = gBattleAnimMove_GMaxChiStrike, }, @@ -21618,7 +21613,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_MEAN_LOOK, + .argument = { .maxEffect = MAX_EFFECT_MEAN_LOOK }, .battleAnimScript = gBattleAnimMove_GMaxTerror, }, @@ -21634,7 +21629,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_SPEED_2_FOES, + .argument = { .maxEffect = MAX_EFFECT_LOWER_SPEED_2_FOES }, .battleAnimScript = gBattleAnimMove_GMaxFoamBurst, }, @@ -21650,7 +21645,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_AURORA_VEIL, + .argument = { .maxEffect = MAX_EFFECT_AURORA_VEIL }, .battleAnimScript = gBattleAnimMove_GMaxResonance, }, @@ -21666,7 +21661,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_INFATUATE_FOES, + .argument = { .maxEffect = MAX_EFFECT_INFATUATE_FOES }, .battleAnimScript = gBattleAnimMove_GMaxCuddle, }, @@ -21682,7 +21677,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_RECYCLE_BERRIES, + .argument = { .maxEffect = MAX_EFFECT_RECYCLE_BERRIES }, .battleAnimScript = gBattleAnimMove_GMaxReplenish, }, @@ -21698,7 +21693,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_POISON_FOES, + .argument = { .maxEffect = MAX_EFFECT_POISON_FOES }, .battleAnimScript = gBattleAnimMove_GMaxMalodor, }, @@ -21714,7 +21709,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_TORMENT_FOES, + .argument = { .maxEffect = MAX_EFFECT_TORMENT_FOES }, .battleAnimScript = gBattleAnimMove_GMaxMeltdown, }, @@ -21730,7 +21725,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_FIXED_POWER, + .argument = { .maxEffect = MAX_EFFECT_FIXED_POWER }, .ignoresTargetAbility = TRUE, .battleAnimScript = gBattleAnimMove_GMaxDrumSolo, }, @@ -21747,7 +21742,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_FIXED_POWER, + .argument = { .maxEffect = MAX_EFFECT_FIXED_POWER }, .ignoresTargetAbility = TRUE, .battleAnimScript = gBattleAnimMove_GMaxFireball, }, @@ -21764,7 +21759,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_FIXED_POWER, + .argument = { .maxEffect = MAX_EFFECT_FIXED_POWER }, .ignoresTargetAbility = TRUE, .battleAnimScript = gBattleAnimMove_GMaxHydrosnipe, }, @@ -21781,7 +21776,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_DEFOG, + .argument = { .maxEffect = MAX_EFFECT_DEFOG }, .battleAnimScript = gBattleAnimMove_GMaxWindRage, }, @@ -21797,7 +21792,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_GRAVITY, + .argument = { .maxEffect = MAX_EFFECT_GRAVITY }, .battleAnimScript = gBattleAnimMove_GMaxGravitas, }, @@ -21813,7 +21808,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_STEALTH_ROCK, + .argument = { .maxEffect = MAX_EFFECT_STEALTH_ROCK }, .battleAnimScript = gBattleAnimMove_GMaxStonesurge, }, @@ -21829,7 +21824,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_VOLCALITH, + .argument = { .maxEffect = MAX_EFFECT_VOLCALITH }, .battleAnimScript = gBattleAnimMove_GMaxVolcalith, }, @@ -21845,7 +21840,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_LOWER_EVASIVENESS_FOES, + .argument = { .maxEffect = MAX_EFFECT_LOWER_EVASIVENESS_FOES }, .battleAnimScript = gBattleAnimMove_GMaxTartness, }, @@ -21861,7 +21856,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_AROMATHERAPY, + .argument = { .maxEffect = MAX_EFFECT_AROMATHERAPY }, .battleAnimScript = gBattleAnimMove_GMaxSweetness, }, @@ -21877,7 +21872,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_SANDBLAST_FOES, + .argument = { .maxEffect = MAX_EFFECT_SANDBLAST_FOES }, .battleAnimScript = gBattleAnimMove_GMaxSandblast, }, @@ -21893,7 +21888,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_POISON_PARALYZE_FOES, + .argument = { .maxEffect = MAX_EFFECT_POISON_PARALYZE_FOES }, .battleAnimScript = gBattleAnimMove_GMaxStunShock, }, @@ -21909,7 +21904,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_FIRE_SPIN_FOES, + .argument = { .maxEffect = MAX_EFFECT_FIRE_SPIN_FOES }, .battleAnimScript = gBattleAnimMove_GMaxCentiferno, }, @@ -21925,7 +21920,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_CONFUSE_FOES, + .argument = { .maxEffect = MAX_EFFECT_CONFUSE_FOES }, .battleAnimScript = gBattleAnimMove_GMaxSmite, }, @@ -21942,7 +21937,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_YAWN_FOE, + .argument = { .maxEffect = MAX_EFFECT_YAWN_FOE }, .battleAnimScript = gBattleAnimMove_GMaxSnooze, }, @@ -21958,7 +21953,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_HEAL_TEAM, + .argument = { .maxEffect = MAX_EFFECT_HEAL_TEAM }, .battleAnimScript = gBattleAnimMove_GMaxFinale, }, @@ -21974,7 +21969,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_STEELSURGE, + .argument = { .maxEffect = MAX_EFFECT_STEELSURGE }, .battleAnimScript = gBattleAnimMove_GMaxSteelsurge, }, @@ -21990,7 +21985,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_SPITE, + .argument = { .maxEffect = MAX_EFFECT_SPITE }, .battleAnimScript = gBattleAnimMove_GMaxDepletion, }, @@ -22006,7 +22001,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_BYPASS_PROTECT, + .argument = { .maxEffect = MAX_EFFECT_BYPASS_PROTECT }, .battleAnimScript = gBattleAnimMove_GMaxOneBlow, }, @@ -22022,7 +22017,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = MAX_EFFECT_BYPASS_PROTECT, + .argument = { .maxEffect = MAX_EFFECT_BYPASS_PROTECT }, .battleAnimScript = gBattleAnimMove_GMaxRapidFlow, }, diff --git a/test/battle/ability/cud_chew.c b/test/battle/ability/cud_chew.c index 297635c9f3..b3dd92ecd5 100644 --- a/test/battle/ability/cud_chew.c +++ b/test/battle/ability/cud_chew.c @@ -29,7 +29,7 @@ SINGLE_BATTLE_TEST("Cud Chew will activate Oran Berry effect again on the next t ASSUME(gItemsInfo[ITEM_ORAN_BERRY].holdEffect == HOLD_EFFECT_RESTORE_HP); ASSUME(gItemsInfo[ITEM_ORAN_BERRY].holdEffectParam == 10); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_TAUROS_PALDEA_COMBAT) { MaxHP(60); HP(60); Ability(ABILITY_CUD_CHEW); Item(ITEM_ORAN_BERRY); } } WHEN { diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index 37ad7edb15..7279085ff2 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -37,7 +37,7 @@ AI_SINGLE_BATTLE_TEST("AI sees increased base power of Smelling Salt") GIVEN { ASSUME(B_UPDATED_MOVE_DATA >= GEN_6); ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS); - ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].argument == STATUS1_PARALYSIS); + ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].argument.status == STATUS1_PARALYSIS); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { HP(60); Status1(status1); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_BODY_SLAM, MOVE_SMELLING_SALTS); } @@ -59,7 +59,7 @@ AI_SINGLE_BATTLE_TEST("AI sees increased base power of Wake Up Slap") GIVEN { ASSUME(B_UPDATED_MOVE_DATA >= GEN_6); ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS); - ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].argument == STATUS1_SLEEP); + ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].argument.status == STATUS1_SLEEP); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_MEGANIUM) { HP(35); Status1(status1); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_BODY_SLAM, MOVE_WAKE_UP_SLAP); } diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index abc9a11c4d..97b099d046 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -626,7 +626,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed") { GIVEN { // Fails?: ASSUME(GetMaxMove(B_POSITION_PLAYER_LEFT, MOVE_TACKLE) == MOVE_MAX_STRIKE); - ASSUME(gMovesInfo[MOVE_MAX_STRIKE].argument == MAX_EFFECT_LOWER_SPEED); + ASSUME(gMovesInfo[MOVE_MAX_STRIKE].argument.maxEffect == MAX_EFFECT_LOWER_SPEED); OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } PLAYER(SPECIES_WOBBUFFET) { Speed(80); } } WHEN { @@ -650,7 +650,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed") DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_STRIKE].argument == MAX_EFFECT_LOWER_SPEED); + ASSUME(gMovesInfo[MOVE_MAX_STRIKE].argument.maxEffect == MAX_EFFECT_LOWER_SPEED); PLAYER(SPECIES_WOBBUFFET) { Speed(80); } PLAYER(SPECIES_WOBBUFFET) { Speed(79); } OPPONENT(SPECIES_WOBBUFFET) {Speed(100); } @@ -687,7 +687,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack") { s16 damage[4]; GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_KNUCKLE].argument == MAX_EFFECT_RAISE_TEAM_ATTACK); + ASSUME(gMovesInfo[MOVE_MAX_KNUCKLE].argument.maxEffect == MAX_EFFECT_RAISE_TEAM_ATTACK); ASSUME(gMovesInfo[MOVE_CLOSE_COMBAT].category == DAMAGE_CATEGORY_PHYSICAL); ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WOBBUFFET); @@ -729,7 +729,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack") SINGLE_BATTLE_TEST("(DYNAMAX) Max Flare sets up sunlight") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_FLARE].argument == MAX_EFFECT_SUN); + ASSUME(gMovesInfo[MOVE_MAX_FLARE].argument.maxEffect == MAX_EFFECT_SUN); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -745,7 +745,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Flare sets up sunlight") SINGLE_BATTLE_TEST("(DYNAMAX) Max Geyser sets up heavy rain") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_GEYSER].argument == MAX_EFFECT_RAIN); + ASSUME(gMovesInfo[MOVE_MAX_GEYSER].argument.maxEffect == MAX_EFFECT_RAIN); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -761,7 +761,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Geyser sets up heavy rain") SINGLE_BATTLE_TEST("(DYNAMAX) Max Hailstorm sets up hail") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_HAILSTORM].argument == MAX_EFFECT_HAIL); + ASSUME(gMovesInfo[MOVE_MAX_HAILSTORM].argument.maxEffect == MAX_EFFECT_HAIL); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -777,7 +777,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Hailstorm sets up hail") SINGLE_BATTLE_TEST("(DYNAMAX) Max Rockfall sets up a sandstorm") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_ROCKFALL].argument == MAX_EFFECT_SANDSTORM); + ASSUME(gMovesInfo[MOVE_MAX_ROCKFALL].argument.maxEffect == MAX_EFFECT_SANDSTORM); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -794,7 +794,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Overgrowth sets up Grassy Terrain") { s32 maxHP = 490; // Because of recalculated stats upon Dynamaxing GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_OVERGROWTH].argument == MAX_EFFECT_GRASSY_TERRAIN); + ASSUME(gMovesInfo[MOVE_MAX_OVERGROWTH].argument.maxEffect == MAX_EFFECT_GRASSY_TERRAIN); ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseHP == 190); OPPONENT(SPECIES_WOBBUFFET) { MaxHP(maxHP); HP(maxHP / 2); }; PLAYER(SPECIES_WOBBUFFET) { MaxHP(maxHP); HP(maxHP / 2); }; @@ -814,7 +814,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Overgrowth sets up Grassy Terrain") SINGLE_BATTLE_TEST("(DYNAMAX) Max Mindstorm sets up Psychic Terrain") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_MINDSTORM].argument == MAX_EFFECT_PSYCHIC_TERRAIN); + ASSUME(gMovesInfo[MOVE_MAX_MINDSTORM].argument.maxEffect == MAX_EFFECT_PSYCHIC_TERRAIN); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -831,7 +831,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Mindstorm sets up Psychic Terrain") SINGLE_BATTLE_TEST("(DYNAMAX) Max Lightning sets up Electric Terrain") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_LIGHTNING].argument == MAX_EFFECT_ELECTRIC_TERRAIN); + ASSUME(gMovesInfo[MOVE_MAX_LIGHTNING].argument.maxEffect == MAX_EFFECT_ELECTRIC_TERRAIN); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -846,7 +846,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Lightning sets up Electric Terrain") SINGLE_BATTLE_TEST("(DYNAMAX) Max Starfall sets up Misty Terrain") { GIVEN { - ASSUME(gMovesInfo[MOVE_MAX_STARFALL].argument == MAX_EFFECT_MISTY_TERRAIN); + ASSUME(gMovesInfo[MOVE_MAX_STARFALL].argument.maxEffect == MAX_EFFECT_MISTY_TERRAIN); OPPONENT(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); } WHEN { @@ -861,7 +861,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Starfall sets up Misty Terrain") SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Stonesurge sets up Stealth Rocks") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_STONESURGE].argument == MAX_EFFECT_STEALTH_ROCK); + ASSUME(gMovesInfo[MOVE_G_MAX_STONESURGE].argument.maxEffect == MAX_EFFECT_STEALTH_ROCK); PLAYER(SPECIES_DREDNAW) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -881,7 +881,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Stonesurge sets up Stealth Rocks") SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Steelsurge sets up sharp steel") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_STEELSURGE].argument == MAX_EFFECT_STEELSURGE); + ASSUME(gMovesInfo[MOVE_G_MAX_STEELSURGE].argument.maxEffect == MAX_EFFECT_STEELSURGE); PLAYER(SPECIES_COPPERAJAH) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_HATTERENE); @@ -912,7 +912,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Hydrosnipe has fixed power and ignores abili PARAMETRIZE { move = MOVE_WATER_GUN; } PARAMETRIZE { move = MOVE_HYDRO_CANNON; } GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_HYDROSNIPE].argument == MAX_EFFECT_FIXED_POWER); + ASSUME(gMovesInfo[MOVE_G_MAX_HYDROSNIPE].argument.maxEffect == MAX_EFFECT_FIXED_POWER); PLAYER(SPECIES_INTELEON) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_ARCTOVISH) { Ability(ABILITY_WATER_ABSORB); } } WHEN { @@ -928,7 +928,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Hydrosnipe has fixed power and ignores abili DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Volt Crash paralyzes both opponents") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_VOLT_CRASH].argument == MAX_EFFECT_PARALYZE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_VOLT_CRASH].argument.maxEffect == MAX_EFFECT_PARALYZE_FOES); PLAYER(SPECIES_PIKACHU) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_PICHU); OPPONENT(SPECIES_WOBBUFFET); @@ -955,7 +955,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponen PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = STATUS1_PARALYSIS; } PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; } GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_STUN_SHOCK].argument.maxEffect == MAX_EFFECT_POISON_PARALYZE_FOES); PLAYER(SPECIES_TOXTRICITY) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_TOXEL); OPPONENT(SPECIES_WOBBUFFET); @@ -992,7 +992,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponen DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock chooses statuses before considering immunities") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_STUN_SHOCK].argument.maxEffect == MAX_EFFECT_POISON_PARALYZE_FOES); PLAYER(SPECIES_TOXTRICITY) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_TOXEL); OPPONENT(SPECIES_GARBODOR); @@ -1025,7 +1025,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; } PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = STATUS1_SLEEP; } GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_BEFUDDLE].argument == MAX_EFFECT_EFFECT_SPORE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_BEFUDDLE].argument.maxEffect == MAX_EFFECT_EFFECT_SPORE_FOES); PLAYER(SPECIES_BUTTERFREE) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_CATERPIE); OPPONENT(SPECIES_WOBBUFFET); @@ -1069,7 +1069,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Gold Rush confuses both opponents and generates money") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_GOLD_RUSH].argument == MAX_EFFECT_CONFUSE_FOES_PAY_DAY); + ASSUME(gMovesInfo[MOVE_G_MAX_GOLD_RUSH].argument.maxEffect == MAX_EFFECT_CONFUSE_FOES_PAY_DAY); PLAYER(SPECIES_MEOWTH) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_PERSIAN); OPPONENT(SPECIES_WOBBUFFET); @@ -1089,7 +1089,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Gold Rush confuses both opponents and genera DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Smite confuses both opponents") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_SMITE].argument == MAX_EFFECT_CONFUSE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_SMITE].argument.maxEffect == MAX_EFFECT_CONFUSE_FOES); PLAYER(SPECIES_HATTERENE) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_HATENNA); OPPONENT(SPECIES_WOBBUFFET); @@ -1108,7 +1108,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Smite confuses both opponents") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Cuddle infatuates both opponents, if possible") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_CUDDLE].argument == MAX_EFFECT_INFATUATE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_CUDDLE].argument.maxEffect == MAX_EFFECT_INFATUATE_FOES); PLAYER(SPECIES_EEVEE) { Gender(MON_MALE); GigantamaxFactor(TRUE); } PLAYER(SPECIES_EEVEE); OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); } @@ -1129,7 +1129,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Cuddle infatuates both opponents, if possibl DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Terror traps both opponents") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_TERROR].argument == MAX_EFFECT_MEAN_LOOK); + ASSUME(gMovesInfo[MOVE_G_MAX_TERROR].argument.maxEffect == MAX_EFFECT_MEAN_LOOK); PLAYER(SPECIES_GENGAR) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_GASTLY); OPPONENT(SPECIES_WOBBUFFET); @@ -1150,7 +1150,7 @@ TO_DO_BATTLE_TEST("(DYNAMAX) Baton Pass passes G-Max Terror's escape prevention DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Meltdown torments both opponents for 3 turns") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_MELTDOWN].argument == MAX_EFFECT_TORMENT_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_MELTDOWN].argument.maxEffect == MAX_EFFECT_TORMENT_FOES); PLAYER(SPECIES_MELMETAL) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_MELTAN); OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, MOVE_CELEBRATE); } @@ -1187,7 +1187,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Wildfire sets a field effect that damages no { s16 damage; GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_WILDFIRE].argument == MAX_EFFECT_WILDFIRE); + ASSUME(gMovesInfo[MOVE_G_MAX_WILDFIRE].argument.maxEffect == MAX_EFFECT_WILDFIRE); PLAYER(SPECIES_CHARIZARD) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_CHARMANDER); OPPONENT(SPECIES_WOBBUFFET) { HP(600); MaxHP(600); } @@ -1233,7 +1233,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries 50\% of t { PASSES_RANDOMLY(1, 2, RNG_G_MAX_REPLENISH); GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_REPLENISH].argument == MAX_EFFECT_RECYCLE_BERRIES); + ASSUME(gMovesInfo[MOVE_G_MAX_REPLENISH].argument.maxEffect == MAX_EFFECT_RECYCLE_BERRIES); PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); GigantamaxFactor(TRUE); } PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); Ability(ABILITY_THICK_FAT); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); } @@ -1261,7 +1261,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy") { PASSES_RANDOMLY(1, 2, RNG_G_MAX_SNOOZE); GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_SNOOZE].argument == MAX_EFFECT_YAWN_FOE); + ASSUME(gMovesInfo[MOVE_G_MAX_SNOOZE].argument.maxEffect == MAX_EFFECT_YAWN_FOE); ASSUME(gMovesInfo[MOVE_DARK_PULSE].category == DAMAGE_CATEGORY_SPECIAL); // Otherwise, Blissey faints. PLAYER(SPECIES_GRIMMSNARL) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_IMPIDIMP); @@ -1285,7 +1285,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health") { s16 damage1, damage2; GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_FINALE].argument == MAX_EFFECT_HEAL_TEAM); + ASSUME(gMovesInfo[MOVE_G_MAX_FINALE].argument.maxEffect == MAX_EFFECT_HEAL_TEAM); PLAYER(SPECIES_ALCREMIE) { HP(1); GigantamaxFactor(TRUE); } PLAYER(SPECIES_MILCERY) { HP(1); } OPPONENT(SPECIES_WOBBUFFET); @@ -1305,7 +1305,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_SWEETNESS].argument == MAX_EFFECT_AROMATHERAPY); + ASSUME(gMovesInfo[MOVE_G_MAX_SWEETNESS].argument.maxEffect == MAX_EFFECT_AROMATHERAPY); PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); GigantamaxFactor(TRUE); } PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); } OPPONENT(SPECIES_WOBBUFFET); @@ -1325,7 +1325,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin") { GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_CENTIFERNO].argument == MAX_EFFECT_FIRE_SPIN_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_CENTIFERNO].argument.maxEffect == MAX_EFFECT_FIRE_SPIN_FOES); PLAYER(SPECIES_CENTISKORCH) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_SIZZLIPEDE); PLAYER(SPECIES_SIZZLIPEDE); @@ -1354,7 +1354,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance") u32 j; GIVEN { ASSUME(B_CRIT_CHANCE >= GEN_6); - ASSUME(gMovesInfo[MOVE_G_MAX_CHI_STRIKE].argument == MAX_EFFECT_CRIT_PLUS); + ASSUME(gMovesInfo[MOVE_G_MAX_CHI_STRIKE].argument.maxEffect == MAX_EFFECT_CRIT_PLUS); PLAYER(SPECIES_MACHAMP) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_MACHOP); OPPONENT(SPECIES_WOBBUFFET); @@ -1386,7 +1386,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's { GIVEN { ASSUME(gMovesInfo[MOVE_DRAGON_CLAW].category == DAMAGE_CATEGORY_PHYSICAL); // Otherwise Sableye faints. - ASSUME(gMovesInfo[MOVE_G_MAX_DEPLETION].argument == MAX_EFFECT_SPITE); + ASSUME(gMovesInfo[MOVE_G_MAX_DEPLETION].argument.maxEffect == MAX_EFFECT_SPITE); PLAYER(SPECIES_DURALUDON) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_WYNAUT); // Dynamax behaves weird with test turn order because stats are recalculated. @@ -1408,7 +1408,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage" PARAMETRIZE { protect = TRUE; } PARAMETRIZE { protect = FALSE; } GIVEN { - ASSUME(gMovesInfo[MOVE_G_MAX_ONE_BLOW].argument == MAX_EFFECT_BYPASS_PROTECT); + ASSUME(gMovesInfo[MOVE_G_MAX_ONE_BLOW].argument.maxEffect == MAX_EFFECT_BYPASS_PROTECT); PLAYER(SPECIES_URSHIFU) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_KUBFU); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/hold_effect/attack_up.c b/test/battle/hold_effect/attack_up.c index 383e564ce6..d166d8ff2c 100644 --- a/test/battle/hold_effect/attack_up.c +++ b/test/battle/hold_effect/attack_up.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_LIECHI_BERRY].holdEffect == HOLD_EFFECT_ATTACK_UP); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Liechi Berry raises the holder's Attack by one stage when HP drops to 1/4 or below") diff --git a/test/battle/hold_effect/critical_hit_up.c b/test/battle/hold_effect/critical_hit_up.c index c23f29773a..7bfe4ed74f 100644 --- a/test/battle/hold_effect/critical_hit_up.c +++ b/test/battle/hold_effect/critical_hit_up.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_LANSAT_BERRY].holdEffect == HOLD_EFFECT_CRITICAL_UP); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/4 or below") diff --git a/test/battle/hold_effect/defense_up.c b/test/battle/hold_effect/defense_up.c index 46130b9fe7..87f41be7b3 100644 --- a/test/battle/hold_effect/defense_up.c +++ b/test/battle/hold_effect/defense_up.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_GANLON_BERRY].holdEffect == HOLD_EFFECT_DEFENSE_UP); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Ganlon Berry raises the holder's Defense by one stage when HP drops to 1/4 or below") diff --git a/test/battle/hold_effect/micle_berry.c b/test/battle/hold_effect/micle_berry.c index 87f6742609..f196c67c96 100644 --- a/test/battle/hold_effect/micle_berry.c +++ b/test/battle/hold_effect/micle_berry.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_MICLE_BERRY].holdEffect == HOLD_EFFECT_MICLE_BERRY); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2 when HP drops to 1/4 or below") diff --git a/test/battle/hold_effect/special_attack_up.c b/test/battle/hold_effect/special_attack_up.c index ef348024fc..9ae73340bf 100644 --- a/test/battle/hold_effect/special_attack_up.c +++ b/test/battle/hold_effect/special_attack_up.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_PETAYA_BERRY].holdEffect == HOLD_EFFECT_SP_ATTACK_UP); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Petaya Berry raises the holder's Sp. Atk by one stage when HP drops to 1/4 or below") diff --git a/test/battle/hold_effect/special_defense_up.c b/test/battle/hold_effect/special_defense_up.c index 9585e5b5a7..c96f1680b2 100644 --- a/test/battle/hold_effect/special_defense_up.c +++ b/test/battle/hold_effect/special_defense_up.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_APICOT_BERRY].holdEffect == HOLD_EFFECT_SP_DEFENSE_UP); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Apicot Berry raises the holder's Sp. Def by one stage when HP drops to 1/4 or below") diff --git a/test/battle/hold_effect/speed_up.c b/test/battle/hold_effect/speed_up.c index 4a8b28b6d9..a0e727fd44 100644 --- a/test/battle/hold_effect/speed_up.c +++ b/test/battle/hold_effect/speed_up.c @@ -5,7 +5,7 @@ ASSUMPTIONS { ASSUME(gItemsInfo[ITEM_SALAC_BERRY].holdEffect == HOLD_EFFECT_SPEED_UP); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); } SINGLE_BATTLE_TEST("Salac Berry raises the holder's Speed by one stage when HP drops to 1/4 or below") diff --git a/test/battle/move_effect/change_type_on_item.c b/test/battle/move_effect/change_type_on_item.c index 6365215a42..2824438634 100644 --- a/test/battle/move_effect/change_type_on_item.c +++ b/test/battle/move_effect/change_type_on_item.c @@ -4,7 +4,7 @@ ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_TECHNO_BLAST].effect == EFFECT_CHANGE_TYPE_ON_ITEM); - ASSUME(gMovesInfo[MOVE_TECHNO_BLAST].argument == HOLD_EFFECT_DRIVE); + ASSUME(gMovesInfo[MOVE_TECHNO_BLAST].argument.holdEffect == HOLD_EFFECT_DRIVE); } SINGLE_BATTLE_TEST("Techno Blast changes type depending on the drive the user holds") diff --git a/test/battle/move_effect/fail_if_not_arg_type.c b/test/battle/move_effect/fail_if_not_arg_type.c index 9e8d005d8b..4ded2d3a7f 100644 --- a/test/battle/move_effect/fail_if_not_arg_type.c +++ b/test/battle/move_effect/fail_if_not_arg_type.c @@ -5,7 +5,7 @@ SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type") { GIVEN { ASSUME(gMovesInfo[MOVE_BURN_UP].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE); 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); PLAYER(SPECIES_CYNDAQUIL); @@ -25,7 +25,7 @@ SINGLE_BATTLE_TEST("Burn Up fails if the user isn't a Fire-type") { GIVEN { ASSUME(gMovesInfo[MOVE_BURN_UP].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE); ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_FIRE || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_FIRE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -42,7 +42,7 @@ SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type if enemy faints") { GIVEN { ASSUME(gMovesInfo[MOVE_BURN_UP].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE); 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); PLAYER(SPECIES_CYNDAQUIL); @@ -60,7 +60,7 @@ SINGLE_BATTLE_TEST("Double Shock user loses its Electric-type") { GIVEN { ASSUME(gMovesInfo[MOVE_DOUBLE_SHOCK].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE); 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); PLAYER(SPECIES_PIKACHU); @@ -80,7 +80,7 @@ SINGLE_BATTLE_TEST("Double Shock fails if the user isn't an Electric-type") { GIVEN { ASSUME(gMovesInfo[MOVE_DOUBLE_SHOCK].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE); ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ELECTRIC || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ELECTRIC); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -97,7 +97,7 @@ SINGLE_BATTLE_TEST("Double Shock user loses its Electric-type if enemy faints") { GIVEN { ASSUME(gMovesInfo[MOVE_DOUBLE_SHOCK].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE); 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); PLAYER(SPECIES_PIKACHU); diff --git a/test/battle/move_effect/fixed_damage_arg.c b/test/battle/move_effect/fixed_damage_arg.c index 484601be05..1dae74e3f5 100644 --- a/test/battle/move_effect/fixed_damage_arg.c +++ b/test/battle/move_effect/fixed_damage_arg.c @@ -11,9 +11,9 @@ SINGLE_BATTLE_TEST("Sonic Boom deals fixed damage", s16 damage) u16 mon; PARAMETRIZE { mon = SPECIES_RATTATA; } PARAMETRIZE { mon = SPECIES_ARON; } - + GIVEN { - ASSUME(gMovesInfo[MOVE_SONIC_BOOM].argument == 20); + ASSUME(gMovesInfo[MOVE_SONIC_BOOM].argument.fixedDamage == 20); PLAYER(SPECIES_WOBBUFFET); OPPONENT(mon); } WHEN { diff --git a/test/battle/move_effect/heal_pulse.c b/test/battle/move_effect/heal_pulse.c index e252039982..95a2d75195 100644 --- a/test/battle/move_effect/heal_pulse.c +++ b/test/battle/move_effect/heal_pulse.c @@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Heal Pulse is blocked by Substitute") SINGLE_BATTLE_TEST("Floral Healing heals the target by 2/3rd of it's maxHP if Grassy Terrain is on the field") { GIVEN { - ASSUME(gMovesInfo[MOVE_FLORAL_HEALING].argument == MOVE_EFFECT_FLORAL_HEALING); + ASSUME(gMovesInfo[MOVE_FLORAL_HEALING].argument.moveProperty == MOVE_EFFECT_FLORAL_HEALING); ASSUME(gMovesInfo[MOVE_GRASSY_TERRAIN].effect == EFFECT_GRASSY_TERRAIN); PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); HP(1); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/powder.c b/test/battle/move_effect/powder.c index 85e486918b..7701f4d3a2 100644 --- a/test/battle/move_effect/powder.c +++ b/test/battle/move_effect/powder.c @@ -165,7 +165,7 @@ DOUBLE_BATTLE_TEST("Powder still blocks the target's Fire type moves even if it { GIVEN { ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].effect == EFFECT_THIRD_TYPE); - ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].argument == TYPE_GRASS); + ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].argument.type == TYPE_GRASS); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_TREVENANT); diff --git a/test/battle/move_effect/revelation_dance.c b/test/battle/move_effect/revelation_dance.c index 9ab5d4a8e2..0549abb7b7 100644 --- a/test/battle/move_effect/revelation_dance.c +++ b/test/battle/move_effect/revelation_dance.c @@ -5,9 +5,9 @@ ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].effect == EFFECT_REVELATION_DANCE); ASSUME(gMovesInfo[MOVE_REVELATION_DANCE].danceMove == TRUE); - ASSUME(MoveHasAdditionalEffectSelfArg(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE)); + ASSUME(IsMoveEffectRemoveSpeciesType(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE)); ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].effect == EFFECT_THIRD_TYPE); - ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].argument == TYPE_GRASS); + ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].argument.type == TYPE_GRASS); ASSUME(gMovesInfo[MOVE_ROOST].effect == EFFECT_ROOST); } diff --git a/test/battle/move_effect/semi_invulnerable.c b/test/battle/move_effect/semi_invulnerable.c index d3869bfe54..d5bf909488 100644 --- a/test/battle/move_effect/semi_invulnerable.c +++ b/test/battle/move_effect/semi_invulnerable.c @@ -4,17 +4,17 @@ ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_FLY].argument)) == STATUS3_ON_AIR); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_FLY].argument.twoTurnAttack.status) == STATUS3_ON_AIR); ASSUME(gMovesInfo[MOVE_DIG].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_DIG].argument)) == STATUS3_UNDERGROUND); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_DIG].argument.twoTurnAttack.status) == STATUS3_UNDERGROUND); ASSUME(gMovesInfo[MOVE_BOUNCE].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_BOUNCE].argument)) == STATUS3_ON_AIR); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_BOUNCE].argument.twoTurnAttack.status) == STATUS3_ON_AIR); ASSUME(gMovesInfo[MOVE_DIVE].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_DIVE].argument)) == STATUS3_UNDERWATER); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_DIVE].argument.twoTurnAttack.status) == STATUS3_UNDERWATER); ASSUME(gMovesInfo[MOVE_PHANTOM_FORCE].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_PHANTOM_FORCE].argument)) == STATUS3_PHANTOM_FORCE); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_PHANTOM_FORCE].argument.twoTurnAttack.status) == STATUS3_PHANTOM_FORCE); ASSUME(gMovesInfo[MOVE_SHADOW_FORCE].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_SHADOW_FORCE].argument)) == STATUS3_PHANTOM_FORCE); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_SHADOW_FORCE].argument.twoTurnAttack.status) == STATUS3_PHANTOM_FORCE); } SINGLE_BATTLE_TEST("Semi-invulnerable moves make the user semi-invulnerable turn 1, then strike turn 2") diff --git a/test/battle/move_effect/shed_tail.c b/test/battle/move_effect/shed_tail.c index f4ef2ec0d5..1cdf74b0fd 100644 --- a/test/battle/move_effect/shed_tail.c +++ b/test/battle/move_effect/shed_tail.c @@ -110,7 +110,7 @@ SINGLE_BATTLE_TEST("Shed Tail creates a Substitute with 1/4 of user maximum heal PARAMETRIZE { hp = 164; } GIVEN { - ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument == 40); + ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].argument.fixedDamage == 40); ASSUME(gMovesInfo[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG); PLAYER(SPECIES_BULBASAUR) { MaxHP(hp); } PLAYER(SPECIES_BULBASAUR); diff --git a/test/battle/move_effect/smelling_salts.c b/test/battle/move_effect/smelling_salts.c index bb3f333a42..8d97ab8f09 100644 --- a/test/battle/move_effect/smelling_salts.c +++ b/test/battle/move_effect/smelling_salts.c @@ -4,7 +4,7 @@ ASSUMPTIONS { ASSUME(MoveHasAdditionalEffect(MOVE_SMELLING_SALTS, MOVE_EFFECT_REMOVE_STATUS) == TRUE); - ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].argument == STATUS1_PARALYSIS); + ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].argument.status == STATUS1_PARALYSIS); } SINGLE_BATTLE_TEST("Smelling Salts does not cure paralyzed pokemons behind substitutes or get increased power") diff --git a/test/battle/move_effect/sparkling_aria.c b/test/battle/move_effect/sparkling_aria.c index 332cf8165c..24ac3c84bb 100644 --- a/test/battle/move_effect/sparkling_aria.c +++ b/test/battle/move_effect/sparkling_aria.c @@ -4,7 +4,7 @@ ASSUMPTIONS { ASSUME(MoveHasAdditionalEffect(MOVE_SPARKLING_ARIA, MOVE_EFFECT_REMOVE_STATUS) == TRUE); - ASSUME(gMovesInfo[MOVE_SPARKLING_ARIA].argument == STATUS1_BURN); + ASSUME(gMovesInfo[MOVE_SPARKLING_ARIA].argument.status == STATUS1_BURN); ASSUME(gMovesInfo[MOVE_SPARKLING_ARIA].soundMove == TRUE); } diff --git a/test/battle/move_effect/two_turns_attack.c b/test/battle/move_effect/two_turns_attack.c index efeb419ce5..847f8db72c 100644 --- a/test/battle/move_effect/two_turns_attack.c +++ b/test/battle/move_effect/two_turns_attack.c @@ -10,12 +10,12 @@ ASSUMPTIONS // Solar Beam - check for sun ASSUME(gMovesInfo[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM); - ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument) == B_WEATHER_SUN); + ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status) == B_WEATHER_SUN); ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM); - ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument) == B_WEATHER_SUN); + ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status) == B_WEATHER_SUN); // Electro shot - check for rain - ASSUME(HIHALF(gMovesInfo[MOVE_ELECTRO_SHOT].argument) == B_WEATHER_RAIN); + ASSUME(HIHALF(gMovesInfo[MOVE_ELECTRO_SHOT].argument.twoTurnAttack.status) == B_WEATHER_RAIN); ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].effect == EFFECT_TWO_TURNS_ATTACK); ASSUME(MoveHasAdditionalEffectSelf(MOVE_ELECTRO_SHOT, MOVE_EFFECT_SP_ATK_PLUS_1) == TRUE); } diff --git a/test/battle/move_effect/wake_up_slap.c b/test/battle/move_effect/wake_up_slap.c index 0a881be100..e4d7c2e616 100644 --- a/test/battle/move_effect/wake_up_slap.c +++ b/test/battle/move_effect/wake_up_slap.c @@ -4,7 +4,7 @@ ASSUMPTIONS { ASSUME(MoveHasAdditionalEffect(MOVE_WAKE_UP_SLAP, MOVE_EFFECT_REMOVE_STATUS) == TRUE); - ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].argument == STATUS1_SLEEP); + ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].argument.status == STATUS1_SLEEP); } SINGLE_BATTLE_TEST("Wake-Up Slap does not cure paralyzed pokemons behind substitutes or get increased power") diff --git a/test/battle/move_effect_secondary/double_power_on_arg_status.c b/test/battle/move_effect_secondary/double_power_on_arg_status.c index d147264470..1d3563c427 100644 --- a/test/battle/move_effect_secondary/double_power_on_arg_status.c +++ b/test/battle/move_effect_secondary/double_power_on_arg_status.c @@ -13,7 +13,7 @@ SINGLE_BATTLE_TEST("Hex deals double damage to foes with a status", s16 damage) PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; } GIVEN { ASSUME(gMovesInfo[MOVE_HEX].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS); - ASSUME(gMovesInfo[MOVE_HEX].argument == STATUS1_ANY); + ASSUME(gMovesInfo[MOVE_HEX].argument.status == STATUS1_ANY); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Status1(status1); } } WHEN { @@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Venoshock's power doubles if the target is poisoned/badly po PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; } GIVEN { ASSUME(gMovesInfo[MOVE_VENOSHOCK].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS); - ASSUME(gMovesInfo[MOVE_VENOSHOCK].argument == STATUS1_PSN_ANY); + ASSUME(gMovesInfo[MOVE_VENOSHOCK].argument.status == STATUS1_PSN_ANY); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Status1(status1); } } WHEN { diff --git a/test/battle/move_effects_combined/barb_barrage.c b/test/battle/move_effects_combined/barb_barrage.c index e2e5059fee..cedb671b86 100644 --- a/test/battle/move_effects_combined/barb_barrage.c +++ b/test/battle/move_effects_combined/barb_barrage.c @@ -4,7 +4,7 @@ ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_BARB_BARRAGE].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS); - ASSUME(gMovesInfo[MOVE_BARB_BARRAGE].argument == STATUS1_PSN_ANY); + ASSUME(gMovesInfo[MOVE_BARB_BARRAGE].argument.status == STATUS1_PSN_ANY); ASSUME(MoveHasAdditionalEffect(MOVE_BARB_BARRAGE, MOVE_EFFECT_POISON) == TRUE); } diff --git a/test/battle/move_effects_combined/hurricane.c b/test/battle/move_effects_combined/hurricane.c index 61acac6649..6e9228ddaf 100644 --- a/test/battle/move_effects_combined/hurricane.c +++ b/test/battle/move_effects_combined/hurricane.c @@ -40,9 +40,9 @@ SINGLE_BATTLE_TEST("Hurricane can hit airborne targets (Fly, Bounce)") PARAMETRIZE { move = MOVE_BOUNCE; } GIVEN { ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_FLY].argument)) == STATUS3_ON_AIR); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_FLY].argument.twoTurnAttack.status) == STATUS3_ON_AIR); ASSUME(gMovesInfo[MOVE_BOUNCE].effect == EFFECT_SEMI_INVULNERABLE); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_BOUNCE].argument)) == STATUS3_ON_AIR); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_BOUNCE].argument.twoTurnAttack.status) == STATUS3_ON_AIR); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Moves(move); } } WHEN { @@ -58,7 +58,7 @@ DOUBLE_BATTLE_TEST("Hurricane can hit airborne targets (Sky Drop)") { GIVEN { ASSUME(gMovesInfo[MOVE_SKY_DROP].effect == EFFECT_SKY_DROP); - ASSUME(UNCOMPRESS_BITS(HIHALF(gMovesInfo[MOVE_SKY_DROP].argument)) == STATUS3_ON_AIR); + ASSUME(UNCOMPRESS_BITS(gMovesInfo[MOVE_SKY_DROP].argument.twoTurnAttack.status) == STATUS3_ON_AIR); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effects_combined/infernal_parade.c b/test/battle/move_effects_combined/infernal_parade.c index 6aa46ef8cb..890f8f9dc5 100644 --- a/test/battle/move_effects_combined/infernal_parade.c +++ b/test/battle/move_effects_combined/infernal_parade.c @@ -4,7 +4,7 @@ ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_INFERNAL_PARADE].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS); - ASSUME(gMovesInfo[MOVE_INFERNAL_PARADE].argument == STATUS1_ANY); + ASSUME(gMovesInfo[MOVE_INFERNAL_PARADE].argument.status == STATUS1_ANY); ASSUME(MoveHasAdditionalEffect(MOVE_INFERNAL_PARADE, MOVE_EFFECT_BURN) == TRUE); } diff --git a/test/battle/sleep_clause.c b/test/battle/sleep_clause.c index c8393685b8..f0f8f2906d 100644 --- a/test/battle/sleep_clause.c +++ b/test/battle/sleep_clause.c @@ -215,7 +215,7 @@ SINGLE_BATTLE_TEST("Sleep Clause: Psycho Shift'ing sleep will fail if sleep clau STATUS_ICON(opponent, sleep: TRUE); } MESSAGE("Sleep Clause kept the opposing Wobbuffet awake!"); - } + } } SINGLE_BATTLE_TEST("Sleep Clause: Psycho Shift'ing sleep will activate sleep clause") @@ -245,7 +245,7 @@ SINGLE_BATTLE_TEST("Sleep Clause: Psycho Shift'ing sleep will activate sleep cla STATUS_ICON(opponent, sleep: TRUE); } MESSAGE("Sleep Clause kept Zigzagoon awake!"); - } + } } AI_SINGLE_BATTLE_TEST("Sleep Clause: AI will not use Yawn while sleep clause is active") @@ -507,7 +507,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: G-Max Befuddle can only sleep one opposing mon { GIVEN { FLAG_SET(B_FLAG_SLEEP_CLAUSE); - ASSUME(gMovesInfo[MOVE_G_MAX_BEFUDDLE].argument == MAX_EFFECT_EFFECT_SPORE_FOES); + ASSUME(gMovesInfo[MOVE_G_MAX_BEFUDDLE].argument.maxEffect == MAX_EFFECT_EFFECT_SPORE_FOES); PLAYER(SPECIES_BUTTERFREE) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_CATERPIE); OPPONENT(SPECIES_WOBBUFFET); @@ -682,7 +682,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo STATUS_ICON(opponentLeft, sleep: TRUE); MESSAGE("Zigzagoon used Uproar!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_UPROAR, playerRight); - MESSAGE("Zigzagoon caused an uproar!"); + MESSAGE("Zigzagoon caused an uproar!"); MESSAGE("The uproar woke the opposing Zigzagoon!"); STATUS_ICON(opponentLeft, sleep: FALSE); MESSAGE("The opposing Zigzagoon used Roar!"); @@ -1131,7 +1131,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo { GIVEN { FLAG_SET(B_FLAG_SLEEP_CLAUSE); - ASSUME(gMovesInfo[MOVE_G_MAX_SWEETNESS].argument == MAX_EFFECT_AROMATHERAPY); + ASSUME(gMovesInfo[MOVE_G_MAX_SWEETNESS].argument.maxEffect == MAX_EFFECT_AROMATHERAPY); ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); PLAYER(SPECIES_APPLETUN) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_WOBBUFFET); @@ -1467,7 +1467,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Yawn'd Pokémon who's partner is slept before ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); MESSAGE("The opposing Zigzagoon fell asleep!"); STATUS_ICON(opponentLeft, sleep: TRUE); - NONE_OF { + NONE_OF { MESSAGE( "The opposing Zigzagoon fell asleep!"); STATUS_ICON(opponentRight, sleep: TRUE); } @@ -1638,13 +1638,13 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep Clause does not prevent sleeping your pa FLAG_SET(B_FLAG_SLEEP_CLAUSE); ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); PLAYER(SPECIES_ZIGZAGOON); - PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); - OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); } WHEN { TURN { MOVE(playerLeft, MOVE_SPORE, target: playerRight); } TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_SPORE, target: playerRight); } @@ -1681,13 +1681,13 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep Clause does not prevent sleeping your pa FLAG_SET(B_FLAG_SLEEP_CLAUSE); ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); PLAYER(SPECIES_ZIGZAGOON); - PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); - OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); } WHEN { TURN { MOVE(playerLeft, MOVE_YAWN, target: playerRight); } TURN {} From b1dbc6e9b2baf1f7d483e43a68d84892689aa082 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 24 Dec 2024 10:46:40 +0100 Subject: [PATCH 36/45] Fix ASSUMPTIONS not working (#5869) --- include/test/test.h | 2 +- test/battle/move_effect/two_turns_attack.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/test/test.h b/include/test/test.h index 1a9d8a237e..ccfc589c21 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -95,7 +95,7 @@ s32 Test_MgbaPrintf(const char *fmt, ...); #define ASSUMPTIONS \ static void Assumptions(void); \ - __attribute__((section(".tests"), used)) static const struct Test sAssumptions = \ + __attribute__((section(".tests"), used, no_reorder)) static const struct Test sAssumptions = \ { \ .name = "ASSUMPTIONS: " __FILE__, \ .filename = __FILE__, \ diff --git a/test/battle/move_effect/two_turns_attack.c b/test/battle/move_effect/two_turns_attack.c index 847f8db72c..de308ab950 100644 --- a/test/battle/move_effect/two_turns_attack.c +++ b/test/battle/move_effect/two_turns_attack.c @@ -10,12 +10,12 @@ ASSUMPTIONS // Solar Beam - check for sun ASSUME(gMovesInfo[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM); - ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status) == B_WEATHER_SUN); + ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status == B_WEATHER_SUN); ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM); - ASSUME(HIHALF(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status) == B_WEATHER_SUN); + ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status == B_WEATHER_SUN); // Electro shot - check for rain - ASSUME(HIHALF(gMovesInfo[MOVE_ELECTRO_SHOT].argument.twoTurnAttack.status) == B_WEATHER_RAIN); + ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].argument.twoTurnAttack.status == B_WEATHER_RAIN); ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].effect == EFFECT_TWO_TURNS_ATTACK); ASSUME(MoveHasAdditionalEffectSelf(MOVE_ELECTRO_SHOT, MOVE_EFFECT_SP_ATK_PLUS_1) == TRUE); } From b0b1f449a3d86d47b26a2b2378d19f1dae2ec9b1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 24 Dec 2024 23:23:17 +0100 Subject: [PATCH 37/45] Fixes regression caused by argument refactor (#5870) Co-authored-by: Eduardo Quezada --- src/battle_script_commands.c | 2 +- test/battle/move_effect/solar_beam.c | 34 ++++++++++++++++++++++ test/battle/move_effect/two_turns_attack.c | 6 ---- 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 test/battle/move_effect/solar_beam.c diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ac29c893e4..76a59fa9dc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14362,7 +14362,7 @@ static bool32 CheckIfCanFireTwoTurnMoveNow(u8 battler, bool8 checkChargeTurnEffe // Certain two-turn moves may fire on the first turn in the right weather (Solar Beam, Electro Shot) // By default, all two-turn moves have the option of adding weather to their argument - if (IsBattlerWeatherAffected(battler, gMovesInfo[gCurrentMove].argument.status)) // TODO: Two Turn Moves affected by weather need a better rewrite + if (IsBattlerWeatherAffected(battler, gMovesInfo[gCurrentMove].argument.twoTurnAttack.status)) return TRUE; return FALSE; diff --git a/test/battle/move_effect/solar_beam.c b/test/battle/move_effect/solar_beam.c new file mode 100644 index 0000000000..6fca334dee --- /dev/null +++ b/test/battle/move_effect/solar_beam.c @@ -0,0 +1,34 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM); + ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status == B_WEATHER_SUN); +} + +SINGLE_BATTLE_TEST("Solar Beam does not need a charging turn if Sun is up") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_DROUGHT; } + PARAMETRIZE { ability = ABILITY_WHITE_SMOKE; } + + GIVEN { + PLAYER(SPECIES_TORKOAL) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SOLAR_BEAM); } + if (ability == ABILITY_WHITE_SMOKE) { + TURN { SKIP_TURN(player); } + } + } SCENE { + if (ability == ABILITY_WHITE_SMOKE) { + MESSAGE("Torkoal used Solar Beam!"); + MESSAGE("Torkoal absorbed light!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } + MESSAGE("Torkoal used Solar Beam!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SOLAR_BEAM, player); + } +} diff --git a/test/battle/move_effect/two_turns_attack.c b/test/battle/move_effect/two_turns_attack.c index de308ab950..8010d14356 100644 --- a/test/battle/move_effect/two_turns_attack.c +++ b/test/battle/move_effect/two_turns_attack.c @@ -8,12 +8,6 @@ ASSUMPTIONS ASSUME(MoveHasAdditionalEffectSelf(MOVE_SKULL_BASH, MOVE_EFFECT_DEF_PLUS_1) == TRUE); ASSUME(gMovesInfo[MOVE_SKY_ATTACK].effect == EFFECT_TWO_TURNS_ATTACK); - // Solar Beam - check for sun - ASSUME(gMovesInfo[MOVE_SOLAR_BEAM].effect == EFFECT_SOLAR_BEAM); - ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status == B_WEATHER_SUN); - ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].effect == EFFECT_SOLAR_BEAM); - ASSUME(gMovesInfo[MOVE_SOLAR_BLADE].argument.twoTurnAttack.status == B_WEATHER_SUN); - // Electro shot - check for rain ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].argument.twoTurnAttack.status == B_WEATHER_RAIN); ASSUME(gMovesInfo[MOVE_ELECTRO_SHOT].effect == EFFECT_TWO_TURNS_ATTACK); From 878724c9aee9a9003307a795dd84dfbfbc14a02e Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 25 Dec 2024 14:59:28 +0100 Subject: [PATCH 38/45] Install instructions (#5876) Co-authored-by: Hedara --- INSTALL.md | 588 +++-------------------------- docs/install/chromeos/CHROME_OS.md | 14 + docs/install/linux/ARCH_LINUX.md | 6 + docs/install/linux/DEBIAN.md | 6 + docs/install/linux/NIXOS.md | 5 + docs/install/linux/OTHERS.md | 11 + docs/install/linux/UBUNTU.md | 6 + docs/install/mac/MAC_OS.md | 93 +++++ docs/install/windows/CYGWIN.md | 4 + docs/install/windows/MSYS2.md | 4 + docs/install/windows/WSL.md | 87 +++++ 11 files changed, 289 insertions(+), 535 deletions(-) create mode 100644 docs/install/chromeos/CHROME_OS.md create mode 100644 docs/install/linux/ARCH_LINUX.md create mode 100644 docs/install/linux/DEBIAN.md create mode 100644 docs/install/linux/NIXOS.md create mode 100644 docs/install/linux/OTHERS.md create mode 100644 docs/install/linux/UBUNTU.md create mode 100644 docs/install/mac/MAC_OS.md create mode 100644 docs/install/windows/CYGWIN.md create mode 100644 docs/install/windows/MSYS2.md create mode 100644 docs/install/windows/WSL.md diff --git a/INSTALL.md b/INSTALL.md index fc1aeb5ba8..25e6adb428 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,564 +1,82 @@ # Instructions +Install instructions for each supported operating system can be found in their respective directories under `docs/install/`. +Lines to those can be found under each heading. +This file only contains a short introduction to each supported system. +If you run into trouble, ask for help on Discord (see [README.md](README.md)). -These instructions explain how to set up the tools required to build **pokeemerald Expansion**, which assembles the source files into a ROM (pokeemerald.gba). - -These instructions come with notes which can be expanded by clicking the "Note..." text. -In general, you should not need to open these unless if you get an error or if you need additional clarification. - -If you run into trouble, ask for help on Discord or IRC (see [README.md](README.md)). +After completing the install instructions for your OS, proceed to [Building pokeemerald-expansion](#building-pokeemerald-expansion). ## Windows -Windows has instructions for building with three possible terminals, providing 3 different options in case the user stumbles upon unexpected errors. -- [Windows 10/11 (WSL1)](#windows-1011-wsl1) (**Fastest, highly recommended**, Windows 10 and 11 only) -- [Windows (msys2)](#windows-msys2) (Second fastest) -- [Windows (Cygwin)](#windows-cygwin) (Slowest) - -Unscientific benchmarks suggest **msys2 is 2x slower** than WSL1, and **Cygwin is 5-6x slower** than WSL1. -
- Note for advanced users: WSL2... - -> WSL2 is an option and is even faster than WSL1 if files are stored on the WSL2 file system, but some tools may have trouble interacting -> with the WSL2 file system over the network drive. For example, tools which use Qt versions before 5.15.2 such as porymap -> may have problems with parsing the \\wsl$ network drive path. -
- -All of the Windows instructions assume that the default drive is C:\\. If this differs to your actual drive letter, then replace C with the correct drive letter when reading the instructions. +**Windows needs one of the systems to build the project** **A note of caution**: As Windows 7 and Windows 8 are officially unsupported by Microsoft, some maintainers are unwilling to maintain the Windows 7/8 instructions. Thus, these instructions may break in the future with fixes taking longer than fixes to the Windows 10/11 instructions. -## Windows 10/11 (WSL1) -WSL1 is the preferred terminal to build **pokeemerald Expansion**. The following instructions will explain how to install WSL1 (referred to interchangeably as WSL). -- If WSL (Debian or Ubuntu) is **not installed**, then go to [Installing WSL1](#Installing-WSL1). -- Otherwise, if WSL is installed, but it **hasn't previously been set up for another decompilation project**, then go to [Setting up WSL1](#Setting-up-WSL1). -- Otherwise, **open WSL** and go to [Choosing where to store pokeemerald Expansion (WSL1)](#Choosing-where-to-store-pokeemerald-expansion-WSL1). +On Windows, the project can be built using the following systems: +- WSL2, fastest +- WSL1, 7 times slower than WSL2 +- Msys2, 20 times slower than WSL2 (**NOTE**: Currently broken on pret upstream) +- Cygwin, 30 timer slower than WSL2 (**NOTE**: Currently broken on pret upstream) -### Installing WSL1 -1. Open [Windows Powershell **as Administrator**](https://i.imgur.com/QKmVbP9.png), and run the following commands (Right Click or Shift+Insert is paste in the Powershell). +**NOTE**: Only WSL systems are recommended. - ```powershell - wsl --install -d Ubuntu --enable-wsl1 - ``` +[WSL Install instructions](docs/install/windows/WSL.md) -2. Once the process finishes, restart your machine. +[Msys2 Install instructions](docs/install/windows/MSYS2.md) -3. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL1. - - ```powershell - wsl --set-version Ubuntu 1 - ``` -
- Note... - - > WSL may open automatically after restarting, but you can ignore it for now. -
- -### Setting up WSL1 -Some tips before proceeding: -- In WSL, Copy and Paste is either done via - - **right-click** (selection + right click to Copy, right click with no selection to Paste) - - **Ctrl+Shift+C/Ctrl+Shift+V** (enabled by right-clicking the title bar, going to Properties, then checking the checkbox next to "Use Ctrl+Shift+C/V as Copy/Paste"). -- Some of the commands that you'll run will ask for your WSL password and/or confirmation to perform the stated action. This is to be expected, just enter your WSL password and/or the yes action when necessary. - -1. Open **Ubuntu** (e.g. using Search). -2. WSL/Ubuntu will set up its own installation when it runs for the first time. Once WSL/Ubuntu finishes installing, it will ask for a username and password (to be input in). -
- Note... - - > When typing in the password, there will be no visible response, but the terminal will still read in input. -
- -3. Update WSL/Ubuntu before continuing. Do this by running the following command. These commands will likely take a long time to finish: - - ```bash - sudo apt update && sudo apt upgrade - ``` - -> Note: If the repository you plan to build has an **[older revision of the INSTALL.md](https://github.com/pret/pokeemerald/blob/571c598/INSTALL.md)**, then follow the [legacy WSL1 instructions](docs/legacy_WSL1_INSTALL.md) from here. - -4. Certain packages are required to build pokeemerald Expansion. Install these packages by running the following command: - - ```bash - sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev - ``` -
- Note... - - > If the above command does not work, try the above command but replacing `apt` with `apt-get`. -
- This will install GCC v10 on Ubuntu 22.04. pokeemerald Expansion works with GCC v10, but remote repositories and the RHH Team use GCC v13 for stricter error-checking. If you want to upgrade from v10 to v13, also follow the devkitpro install instructions. - -### Installing devkitARM on WSL1 - -1. Change directory to somewhere you can download a package, such as **C:\Users\\_\_\Downloads** (the Downloads location for most users). To do so, enter this command, where *\ is your **Windows** username: - - ```bash - cd /mnt/c/Users//Downloads - ``` - -2. Once the directory has been changed, run the following commands to install devkitARM. - - ```bash - sudo apt install wget - wget https://apt.devkitpro.org/install-devkitpro-pacman - chmod +x ./install-devkitpro-pacman - sudo ./install-devkitpro-pacman - sudo dkp-pacman -S gba-dev - ``` - The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -3. Run the following command to set devkitPro related environment variables (alternatively, close and re-open WSL): - - ```bash - source /etc/profile.d/devkit-env.sh - ``` - -devkitARM is now installed. - -### Installing Python on WSL1 - -To install Python on WSL1, simply run the following commands: - -```bash -sudo apt update && sudo apt upgrade -sudo apt install python3 -``` - -Python is now installed. - -### Choosing where to store pokeemerald Expansion (WSL1) -WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. So you're going to want to store pokeemerald Expansion within Windows. - -For example, say you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**. First, ensure that the folder already exists. Then, enter this command to **change directory** to said folder, where *\* is your **Windows** username: - -```bash -cd /mnt/c/Users//Desktop/decomps -``` - -
- Notes... - -> Note 1: The Windows C:\ drive is called /mnt/c/ in WSL. -> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "/mnt/c/users//Desktop/decomp folder"`. -> Note 3: Windows path names are case-insensitive so adhering to capitalization isn't needed -
- -If this works, then proceed to [Installation](#installation). - -Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or continue reading below for [Windows instructions using msys2](#windows-msys2). - -## Windows (msys2) - -- If devkitARM is **not installed**, then go to [Installing devkitARM](#installing-devkitarm). -- If devkitARM is installed, but msys2 **hasn't previously been set up for another decompilation project**, then go to [Setting up msys2](#setting-up-msys2). -- Otherwise, **open msys2** and go to [Choosing where to store pokeemerald Expansion (msys2)](#choosing-where-to-store-pokeemerald-expansion-msys2). - -### Installing devkitARM -1. Download the devkitPro installer [here](https://github.com/devkitPro/installer/releases). -2. Run the devkitPro installer. In the "Choose Components" screen, uncheck everything except GBA Development unless if you plan to install other devkitPro components for other purposes. Keep the install location as C:\devkitPro and leave the Start Menu option unchanged. - -### Setting up msys2 - -Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert. - -1. Open msys2 at C:\devkitPro\msys2\msys2_shell.bat. - -2. Certain packages are required to build pokeemerald Expansion. Install these by running the following two commands: - - ```bash - pacman -Sy msys2-keyring - pacman -S make gcc zlib-devel git - ``` -
- Note... - - > The commands will ask for confirmation, just enter the yes action when prompted. -
- -3. Download [libpng](https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download). - -4. Change directory to where libpng was downloaded. By default, msys2 will start in the current user's profile folder, located at **C:\Users\\⁠_\_**, where *\* is your Windows username. In most cases, libpng should be saved within a subfolder of the profile folder. For example, if libpng was saved to **C:\Users\\_\_\Downloads** (the Downloads location for most users), enter this command: - - ```bash - cd Downloads - ``` - -
- Notes... - - > Note 1: While not shown, msys uses forward slashes `/` instead of backwards slashes `\` as the directory separator. - > Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Downloads/My Downloads"`. - > Note 3: Windows path names are case-insensitive so adhering to capitalization isn’t needed. - > Note 4: If libpng was saved elsewhere, you will need to specify the full path to where libpng was downloaded, e.g. `cd c:/devkitpro/msys2` if it was saved there. -
- -5. Run the following commands to uncompress and install libpng. - - ```bash - tar xf libpng-1.6.37.tar.xz - cd libpng-1.6.37 - ./configure --prefix=/usr - make check - make install - ``` - -6. Then finally, run the following command to change back to the user profile folder. - - ```bash - cd - ``` - -### Installing Python on msys2 - -To install Python on msys2, simply run the following commands: - -```bash -pacman -S mingw-w64-x86_64-python3 -``` - -Python is now installed. - -### Choosing where to store pokeemerald Expansion (msys2) -At this point, you can choose a folder to store pokeemerald Expansion into. If you're okay with storing pokeemerald Expansion in the user profile folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald Expansion is stored when changing directory to the pokeemerald-expansion folder. - -For example, if you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps** (where *\* is your **Windows** username), enter this command: - -```bash -cd Desktop/decomps -``` - -If this works, then proceed to [Installation](#installation). - -Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or continue reading below for [Windows instructions using Cygwin](#windows-cygwin). - -## Windows (Cygwin) -1. If devkitARM is **not installed**, then follow the instructions used to [install devkitARM](#installing-devkitarm) for the msys2 setup before continuing. *Remember to not continue following the msys2 instructions by mistake!* - -2. - - If Cygwin is **not installed**, or does not have all of the required packages installed, then go to [Installing Cygwin](#installing-cygwin). - - If Cygwin is installed, but **is not configured to work with devkitARM**, then go to [Configuring devkitARM for Cygwin](#configuring-devkitarm-for-cygwin). - - Otherwise, **open Cygwin** and go to [Choosing where to store pokeemerald Expansion (Cygwin)](#choosing-where-to-store-pokeemerald-expansion-cygwin) - -### Installing Cygwin -1. Download [Cygwin](https://cygwin.com/install.html): setup-x86_64.exe for 64-bit Windows, setup-x86.exe for 32-bit. - -2. Run the Cygwin setup. Within the Cygwin setup, leave the default settings until the "Choose A Download Site" screen. - -3. At "Choose a Download Site", select any mirror within the Available Download Sites. - -4. At "Select Packages", set the view to "Full" (top left) and search for the following packages: - - `make` - - `git` - - `gcc-core` - - `gcc-g++` - - `libpng-devel` - - To quickly find these, use the search bar and type the name of each package. Ensure that the selected package name is the **exact** same as the one you're trying to download, e.g. `cmake` is **NOT** the same as `make`. - -5. For each package, double click on the text that says "**Skip**" next to each package to select the most recent version to install. If the text says anything other than "**Skip**", (e.g. Keep or a version number), then the package is or will be installed and you don't need to do anything. - -6. Once all required packages have been selected, finish the installation. - -### Configuring devkitARM for Cygwin - -Note that in Cygwin, Copy is Ctrl+Insert and Paste is Shift+Insert. - -1. Open **Cygwin**. - -2. Run the following commands to configure devkitPro to work with Cygwin. - - ```bash - export DEVKITPRO=/cygdrive/c/devkitpro - echo export DEVKITPRO=$DEVKITPRO >> ~/.bashrc - export DEVKITARM=$DEVKITPRO/devkitARM - echo export DEVKITARM=$DEVKITARM >> ~/.bashrc - ``` - -
- Note... - - > Replace the drive letter c with the actual drive letter if it is not c. -
- -### Choosing where to store pokeemerald Expansion (Cygwin) - -Cygwin has its own file system that's within Windows, at **C:\cygwin64\home\\_\_**. If you don't want to store pokeemerald Expansion there, you'll need to account for where ppokeemerald Expansion is stored when **changing directory** to the pokeemerald-expansion folder. - -For example, if you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**, enter this command, where *\* is your **Windows** username: -```bash -cd c:/Users//Desktop/decomps -``` -Note that the directory **must exist** in Windows. If you want to store pokeemerald Expansion in a dedicated folder that doesn't exist (e.g. the example provided above), then create the folder (e.g. using Windows Explorer) before executing the `cd` command. - -
- Notes... - -> Note 1: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "c:/users//Desktop/decomp folder"`. -> Note 2: Windows path names are case-insensitive so adhering to capitalization isn't needed -
- -If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)). - -## macOS -1. If the Xcode Command Line Tools are not installed, download the tools [here](https://developer.apple.com/xcode/resources/), open your Terminal, and run the following command: - - ```bash - xcode-select --install - ``` - -2. - If libpng is **not installed**, then go to [Installing libpng (macOS)](#installing-libpng-macos). - - If pkg-config is **not installed**, then go to [Installing pkg-config (macos)](#installing-pkg-config-macos). - - If devkitARM is **not installed**, then go to [Installing devkitARM (macOS)](#installing-devkitarm-macos). - - Otherwise, **open the Terminal** and go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos) - -### Installing libpng (macOS) -
- Note for advanced users... - -> This guide installs libpng via Homebrew as it is the easiest method, however advanced users can install libpng through other means if they so desire. -
- -1. Open the Terminal. -2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. -3. Run the following command to install libpng. - - ```bash - brew install libpng - ``` - libpng is now installed. - - Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**. - - If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). - -### Installing pkg-config (macOS) -
- Note for advanced users... - -> This guide installs pkg-config via Homebrew as it is the easiest method, however advanced users can install pkg-config through other means if they so desire. -
- -1. Open the Terminal. -2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. -3. Run the following command to install libpng. - - ```bash - brew install pkg-config - ``` - pkg-config is now installed. - - Continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**, otherwise, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). - -### Installing devkitARM (macOS) -1. Download the `devkitpro-pacman-installer.pkg` package from [here](https://github.com/devkitPro/pacman/releases). -2. Open the package to install devkitPro pacman. -3. In the Terminal, run the following commands to install devkitARM: - - ```bash - sudo dkp-pacman -Sy - sudo dkp-pacman -S gba-dev - sudo dkp-pacman -S devkitarm-rules - ``` - - The command with gba-dev will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -4. After the tools are installed, devkitARM must now be made accessible from anywhere by the system. To do so, run the following commands: - - ```bash - export DEVKITPRO=/opt/devkitpro - echo "export DEVKITPRO=$DEVKITPRO" >> ~/.zshrc - export DEVKITARM=$DEVKITPRO/devkitARM - echo "export DEVKITARM=$DEVKITARM" >> ~/.zshrc - - echo "if [ -f ~/.zshrc ]; then . ~/.zshrc; fi" >> ~/.zprofile - ``` - *Note: Starting with macOS 10.15, the default Unix shell is now zsh. If you migrated from an older version of macOS, you might still be using bash. You can check my running `echo $0` in the terminal.* -
- If your terminal is using bash instead of zsh... - - ```bash - export DEVKITPRO=/opt/devkitpro - echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc - export DEVKITARM=$DEVKITPRO/devkitARM - echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc - - echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile - ``` -
- -### Installing Python (macOS) -1. Download the latest Python package from [here](https://www.python.org/downloads/). -2. Open the package to install Python. - -Python is now installed. - -### Choosing where to store pokeemerald Expansion (macOS) -At this point, you can choose a folder to store pokeemerald Expansion into. If you're okay with storing pokeemerald Expansion in the user folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald Expansion is stored when changing directory to the pokeemerald-expansion folder. - -For example, if you want to store pokeemerald Expansion in **~/Desktop/decomps**, enter this command to **change directory** to the desired folder: -```bash -cd Desktop/decomps -``` -Note that the directory **must exist** in the folder system. If you want to store pokeemerald Expansion in a dedicated folder that doesn't exist (e.g. the example provided above), then create the folder (e.g. using Finder) before executing the `cd` command. - -
- Note... - -> Note: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Desktop/decomp folder"` -
- -If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)). +[Cygwin Install instructions](docs/install/windows/CYGWIN.md) ## Linux -Open Terminal and enter the following commands, depending on which distro you're using. +The project can be built on any Linux distribution. +Distributions with instructions: +- [Ubuntu](docs/install/linux/UBUNTU.md) +- [Debian](docs/install/linux/DEBIAN.md) +- [Arch Linux](docs/install/linux/ARCH_LINUX.md) +- [NixOS](docs/install/linux/NIXOS.md) -### Debian/Ubuntu-based distributions -Run the following command to install the necessary packages: -```bash -sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev -``` -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). -
- Note for legacy repos... +Other distributions have to infer what to do from [general instructions](docs/install/linux/OTHERS.md). -> If the repository you plan to build has an **[older revision of the INSTALL.md](https://github.com/pret/pokeemerald/blob/571c598/INSTALL.md)**, -> then you will have to install devkitARM. Install all the above packages except for the arm-none-eabi packages, and follow the instructions to -> [install devkitARM on Debian/Ubuntu-based distributions](#installing-devkitarm-on-debianubuntu-based-distributions). -
+## Mac +Some extra considerations exist to get the testing system working. -### Installing devkitARM on Debian/Ubuntu-based distributions +[Mac instructions](docs/install/mac/MAC_OS.md) -1. Change directory to somewhere you can download a packages, like a Downloads folder. Then, run the following commands to install devkitARM: +## ChromeOS +Only tested on x86_64 based systems. - ```bash - wget https://apt.devkitpro.org/install-devkitpro-pacman - chmod +x ./install-devkitpro-pacman - sudo ./install-devkitpro-pacman - sudo dkp-pacman -S gba-dev - ``` - The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. +[Chrome OS instructions](docs/install/chromeos/CHROME_OS.md) -4. Run the following command to set devkitPro related environment variables (alternatively, close and re-open the Terminal): - - ```bash - source /etc/profile.d/devkit-env.sh - ``` - -devkitARM is now installed. - -### Arch Linux -Run this command as root to install the necessary packages: -```bash -pacman -S base-devel arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib git libpng -``` - -### Installing devkitARM on Arch Linux - -1. Follow [devkitPro's instructions](https://devkitpro.org/wiki/devkitPro_pacman#Customising_Existing_Pacman_Install) to configure `pacman` to download devkitPro packages. -2. Install `gba-dev`: run the following command as root. +# Building pokeemerald-expansion +Follow these steps to build `pokeemerald-expansion`. +1. Navigate to the directory you want to keep the project in, be aware of any system specific limitations. +2. Download `pokeemerald-expansion` with `git` ```console - pacman -S gba-dev - ``` - This will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -3. Run the following command to set devkitPro related environment variables (alternatively, close and re-open the Terminal): - - ```bash - source /etc/profile.d/devkit-env.sh - ``` - -devkitARM is now installed. - -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). - -### NixOS -Run the following command to start an interactive shell with the necessary packages: -```bash -nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng -``` -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). - -### NixOS -Run the following command to start an interactive shell with the necessary packages: -```bash -nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng -``` -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). - -### Other distributions -_(Specific instructions for other distributions would be greatly appreciated!)_ - -1. Try to find the required software in its repositories: - - `gcc` - - `g++` - - `make` - - `git` - - `libpng-dev` - -2. Follow the instructions [here](https://devkitpro.org/wiki/devkitPro_pacman) to install devkitPro pacman. As a reminder, the goal is to configure an existing pacman installation to recognize devkitPro's repositories. -3. Once devkitPro pacman is configured, run the following commands: - - ```bash - sudo pacman -Sy - sudo pacman -S gba-dev - ``` - - The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -### Installing Python in Linux -Installing Python depends on your distribution, please refere to the instructions [here](https://docs.python-guide.org/starting/install3/linux/). - -### Choosing where to store pokeemerald Expansion (Linux) -At this point, you can choose a folder to store pokeemerald Expansion into. If so, you'll have to account for the modified folder path when changing directory to the pokeemerald-expansion folder. - -If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)). - -## Installation - -
- Note for Windows users... - -> Consider adding an exception for the `pokeemerald-expansion` and/or `decomps` folder in Windows Security using -> [these instructions](https://support.microsoft.com/help/4028485). This prevents Microsoft Defender from -> scanning them which might improve performance while building. -
- -1. If pokeemerald Expansion is not already downloaded (some users may prefer to download pokeemerald Expansion via a git client like GitHub Desktop), run: - - ```bash git clone https://github.com/rh-hideout/pokeemerald-expansion ``` +3. Navigate to the newly downloaded project. -
- Note for WSL1... + ```console + cd pokeemerald-expansion + ``` +4. Build the project. - > If you get an error stating `fatal: could not set 'core.filemode' to 'false'`, then run the following commands: - > ```bash - > cd - > sudo umount /mnt/c - > sudo mount -t drvfs C: /mnt/c -o metadata,noatime - > cd - > ``` - > Where *\* is the path of the folder [where you chose to store pokeemerald Expansion](#Choosing-where-to-store-pokeemerald-expansion-WSL1). Then run the `git clone` command again. -
+ ```console + make + ``` +5. If everything worked correctly, something very similar to this should be seen. -Now you're ready to build pokeemerald Expansion. - -## Build pokeemerald Expansion - -If you aren't in the pokeemerald-expansion directory already, then **change directory** to the pokeemerald-expansion folder: -```bash -cd pokeemerald-expansion -``` -To build **pokeemerald.gba** (Note: to speed up builds, see [Parallel builds](#parallel-builds)): -```bash -make -``` -If it has built successfully you will have the output file **pokeemerald.gba** in your project folder. -
-Note for Windows... -> If you switched terminals since the last build (e.g. from msys2 to WSL1), you must run `make clean-tools` once before any subsequent `make` commands. -
+ ```console + arm-none-eabi-ld: warning: ../../pokeemerald.elf has a LOAD segment with RWX permissions + Memory region Used Size Region Size %age Used + EWRAM: 243354 B 256 KB 92.83% + IWRAM: 30492 B 32 KB 93.05% + ROM: 26072244 B 32 MB 77.70% + cd build/modern && arm-none-eabi-ld -T ../../ld_script_modern.ld --print-memory-usage -o ../../pokeemerald.elf | cat + tools/gbafix/gbafix pokeemerald.elf -t"POKEMON EMER" -cBPEE -m01 -r0 --silent + arm-none-eabi-objcopy -O binary pokeemerald.elf pokeemerald.gba + tools/gbafix/gbafix pokeemerald.gba -p --silent + ``` + And the build ROM will be in the directory as `pokeemerald.gba`. # Building guidance diff --git a/docs/install/chromeos/CHROME_OS.md b/docs/install/chromeos/CHROME_OS.md new file mode 100644 index 0000000000..7fa57e5968 --- /dev/null +++ b/docs/install/chromeos/CHROME_OS.md @@ -0,0 +1,14 @@ +# Instructions for ChromeOS + +1. Enable the Linux terminal by following the instructions on [this page](https://chromeos.dev/en/productivity/terminal). Be sure to allocate enough space for the Linux install. +2. After the Linux terminal has finished installing, run the following command in the terminal to update and upgrade the Linux terminal: + + ```console + sudo apt update && apt upgrade + ``` +3. Then install all dependencies by running the following command: + + ```console + sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 + ``` +**NOTE**: The project must be kept in a directory inside the Linux filesystem, for example under `~/Decomps/pokeemerald-expansion` diff --git a/docs/install/linux/ARCH_LINUX.md b/docs/install/linux/ARCH_LINUX.md new file mode 100644 index 0000000000..1d69e5c39c --- /dev/null +++ b/docs/install/linux/ARCH_LINUX.md @@ -0,0 +1,6 @@ +# Arch Linux instructions +## Installing dependencies +Run the following command from the command line: +```console +sudo pacman -S base-devel arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib git libpng python +``` diff --git a/docs/install/linux/DEBIAN.md b/docs/install/linux/DEBIAN.md new file mode 100644 index 0000000000..a63d3f985e --- /dev/null +++ b/docs/install/linux/DEBIAN.md @@ -0,0 +1,6 @@ +# Debian instructions +## Installing dependencies +Open a terminal and run the following command from the command line: +```console +sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 +``` diff --git a/docs/install/linux/NIXOS.md b/docs/install/linux/NIXOS.md new file mode 100644 index 0000000000..6c613466b6 --- /dev/null +++ b/docs/install/linux/NIXOS.md @@ -0,0 +1,5 @@ +# NixOS instructions +Run the following command to start an interactive shell with the necessary packages: +```bash +nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng +``` diff --git a/docs/install/linux/OTHERS.md b/docs/install/linux/OTHERS.md new file mode 100644 index 0000000000..eb83331ed9 --- /dev/null +++ b/docs/install/linux/OTHERS.md @@ -0,0 +1,11 @@ +# Instructions for other distributions +1. Try to find the required software in its repositories: + - `gcc` + - `g++` + - `arm-none-eabi-gcc` + - `arm-none-eabi-binutils` + - `arm-none-eabi-newlib` + - `make` + - `git` + - `libpng-dev` + - `python3` diff --git a/docs/install/linux/UBUNTU.md b/docs/install/linux/UBUNTU.md new file mode 100644 index 0000000000..41beb8067a --- /dev/null +++ b/docs/install/linux/UBUNTU.md @@ -0,0 +1,6 @@ +# Ubuntu instructions +## Installing dependencies +Open a terminal and run the following command from the command line: +```console +sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 +``` diff --git a/docs/install/mac/MAC_OS.md b/docs/install/mac/MAC_OS.md new file mode 100644 index 0000000000..8ffa4df089 --- /dev/null +++ b/docs/install/mac/MAC_OS.md @@ -0,0 +1,93 @@ +# Instructions for macOS +1. If the Xcode Command Line Tools are not installed, download the tools [here](https://developer.apple.com/xcode/resources/), open your Terminal, and run the following command: + + ```bash + xcode-select --install + ``` + +2. - If libpng is **not installed**, then go to [Installing libpng (macOS)](#installing-libpng-macos). + - If pkg-config is **not installed**, then go to [Installing pkg-config (macos)](#installing-pkg-config-macos). + - If devkitARM is **not installed**, then go to [Installing devkitARM (macOS)](#installing-devkitarm-macos). + - Otherwise, **open the Terminal** and go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos) + +### Installing libpng (macOS) +
+ Note for advanced users... + +> This guide installs libpng via Homebrew as it is the easiest method, however advanced users can install libpng through other means if they so desire. +
+ +1. Open the Terminal. +2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. +3. Run the following command to install libpng. + + ```bash + brew install libpng + ``` + libpng is now installed. + + Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**. + + If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). + +### Installing pkg-config (macOS) +
+ Note for advanced users... + +> This guide installs pkg-config via Homebrew as it is the easiest method, however advanced users can install pkg-config through other means if they so desire. +
+ +1. Open the Terminal. +2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. +3. Run the following command to install libpng. + + ```bash + brew install pkg-config + ``` + pkg-config is now installed. + + Continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**, otherwise, go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). + +### Installing devkitARM (macOS) +1. Download the `devkitpro-pacman-installer.pkg` package from [here](https://github.com/devkitPro/pacman/releases). +2. Open the package to install devkitPro pacman. +3. In the Terminal, run the following commands to install devkitARM: + + ```bash + sudo dkp-pacman -Sy + sudo dkp-pacman -S gba-dev + sudo dkp-pacman -S devkitarm-rules + ``` + + The command with gba-dev will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. + +4. After the tools are installed, devkitARM must now be made accessible from anywhere by the system. To do so, run the following commands: + + ```bash + export DEVKITPRO=/opt/devkitpro + echo "export DEVKITPRO=$DEVKITPRO" >> ~/.zshrc + export DEVKITARM=$DEVKITPRO/devkitARM + echo "export DEVKITARM=$DEVKITARM" >> ~/.zshrc + + echo "if [ -f ~/.zshrc ]; then . ~/.zshrc; fi" >> ~/.zprofile + ``` + *Note: Starting with macOS 10.15, the default Unix shell is now zsh. If you migrated from an older version of macOS, you might still be using bash. You can check my running `echo $0` in the terminal.* +
+ If your terminal is using bash instead of zsh... + + ```bash + export DEVKITPRO=/opt/devkitpro + echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc + export DEVKITARM=$DEVKITPRO/devkitARM + echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc + + echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile + ``` +
+ +### Installing Python (macOS) +1. Download the latest Python package from [here](https://www.python.org/downloads/). +2. Open the package to install Python. + +Python is now installed. + diff --git a/docs/install/windows/CYGWIN.md b/docs/install/windows/CYGWIN.md new file mode 100644 index 0000000000..c9ca728c22 --- /dev/null +++ b/docs/install/windows/CYGWIN.md @@ -0,0 +1,4 @@ +# cygwin +Don't, just don't. +Currently doesn't work on current Expansion versions. +This is a bug from upstream pret `pokeemerald`. diff --git a/docs/install/windows/MSYS2.md b/docs/install/windows/MSYS2.md new file mode 100644 index 0000000000..ce7176b912 --- /dev/null +++ b/docs/install/windows/MSYS2.md @@ -0,0 +1,4 @@ +# msys2 +Don't, just don't. +Currently doesn't work on current Expansion versions. +This is a bug from upstream pret `pokeemerald`. diff --git a/docs/install/windows/WSL.md b/docs/install/windows/WSL.md new file mode 100644 index 0000000000..9534966488 --- /dev/null +++ b/docs/install/windows/WSL.md @@ -0,0 +1,87 @@ +# Windows WSL instructions +## Choosing WSL version +If you must store your project on the Windows file system (under /mnt/c/), you should use WSL1. +If you want the best performance and least amount of issues with Windows interfering with compiling the project, use WSL2 and store the project on the Linux file system (under ~/). +## Installing WSL +1. Open [Windows Powershell **as Administrator**](https://i.imgur.com/QKmVbP9.png), and run the following commands (Right Click or Shift+Insert is paste in the Powershell). + + ```powershell + wsl --install -d Ubuntu --enable-wsl1 + ``` + +2. Once the process finishes, restart your machine. + +### WSL1 +3a. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL1. + + ```powershell + wsl --set-version Ubuntu 1 + ``` +### WSL2 +3a. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL2. + + ```powershell + wsl --set-version Ubuntu 2 + ``` + +
+ Note... + + > WSL may open automatically after restarting, but you can ignore it for now. +
+ +## Installing dependencies +Some tips before proceeding: +- In WSL, Copy and Paste is either done via + - **right-click** (selection + right click to Copy, right click with no selection to Paste) + - **Ctrl+Shift+C/Ctrl+Shift+V** (enabled by right-clicking the title bar, going to Properties, then checking the checkbox next to "Use Ctrl+Shift+C/V as Copy/Paste"). +- Some of the commands that you'll run will ask for your WSL password and/or confirmation to perform the stated action. This is to be expected, just enter your WSL password and/or the yes action when necessary. + +1. Open **Ubuntu** (e.g. using Search). +2. WSL/Ubuntu will set up its own installation when it runs for the first time. Once WSL/Ubuntu finishes installing, it will ask for a username and password (to be input in). +
+ Note... + + > When typing in the password, there will be no visible response, but the terminal will still read in input. +
+ +3. Update WSL/Ubuntu before continuing. Do this by running the following command. These commands will likely take a long time to finish: + + ```bash + sudo apt update && sudo apt upgrade + ``` + +4. Certain packages are required to build pokeemerald Expansion. Install these packages by running the following command: + + ```bash + sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 + ``` + +## Choosing a location to store pokeemerald Expansion, WSL1 +WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. So you're going to want to store pokeemerald Expansion within Windows. + +For example, say you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**. First, ensure that the folder already exists. Then, enter this command to **change directory** to said folder, where *\* is your **Windows** username: + +```bash +cd /mnt/c/Users//Desktop/decomps +``` + +
+ Notes... + +> Note 1: The Windows C:\ drive is called /mnt/c/ in WSL. +> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "/mnt/c/users//Desktop/decomp folder"`. +> Note 3: Windows path names are case-insensitive so adhering to capitalization isn't needed +
+ +## Choosing a location to store pokeemerald Expansion, WSL2 +WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. But accessing files on the Windows file system with WSL2 is very slow, so you're going to want to store pokeemerald Expansion within WSL2. +To access the files on the WSL filesystem from Windowsm, you have to open the WSL filesystem as a network attached storage in the file explorer, it should be at the bottom of the left sidebar as "Ubuntu". + +Thus you're going to make sure that you're in the WSL filesystem, then create the folder for decomps if it doesn't already exist, then move into that folder. + +```bash +cd ~/ +mkdir decomps +cd decomps +``` From 816d3020fa442107e7d83fcc893b18d507518512 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 25 Dec 2024 22:42:14 +0100 Subject: [PATCH 39/45] Fixes UB in caps.c (#5878) --- src/caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caps.c b/src/caps.c index 9c30e55527..941509c2a4 100644 --- a/src/caps.c +++ b/src/caps.c @@ -54,7 +54,7 @@ u32 GetSoftLevelCapExpValue(u32 level, u32 expValue) if (B_LEVEL_CAP_EXP_UP) { levelDifference = currentLevelCap - level; - if (levelDifference > ARRAY_COUNT(sExpScalingUp)) + if (levelDifference > ARRAY_COUNT(sExpScalingUp) - 1) return expValue + (expValue / sExpScalingUp[ARRAY_COUNT(sExpScalingUp) - 1]); else return expValue + (expValue / sExpScalingUp[levelDifference]); @@ -71,7 +71,7 @@ u32 GetSoftLevelCapExpValue(u32 level, u32 expValue) else if (B_EXP_CAP_TYPE == EXP_CAP_SOFT) { levelDifference = level - currentLevelCap; - if (levelDifference > ARRAY_COUNT(sExpScalingDown)) + if (levelDifference > ARRAY_COUNT(sExpScalingDown) - 1) return expValue / sExpScalingDown[ARRAY_COUNT(sExpScalingDown) - 1]; else return expValue / sExpScalingDown[levelDifference]; From 6a1ed7e33aeca6302395088836296b1229af7bb6 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Thu, 26 Dec 2024 10:28:07 -0700 Subject: [PATCH 40/45] Change install.md to mention make debug instead of DINFO=1 (#5882) --- INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 25e6adb428..6e52559f67 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -110,9 +110,9 @@ To compile the `modern` target with this toolchain, the subdirectories `lib`, `i ### Building with debug info -To build **pokeemerald.elf** with debug symbols under a modern toolchain: +To build **pokeemerald.elf** with debug symbols and debug-compatible optimization under a modern toolchain: ```bash -make DINFO=1 +make debug ``` # Useful additional tools From 2c9352921c2fa7fdeecca865e11ebf71595185a7 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 26 Dec 2024 17:04:03 -0300 Subject: [PATCH 41/45] Fixed Ally Switch breaking Illusion (#5879) --- src/battle_anim_effects_1.c | 1 + test/battle/move_effect/ally_switch.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 826586cf9b..a3104122d1 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6736,6 +6736,7 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SwapStructData(&gSpecialStatuses[battlerAtk], &gSpecialStatuses[battlerPartner], data, sizeof(struct SpecialStatus)); SwapStructData(&gProtectStructs[battlerAtk], &gProtectStructs[battlerPartner], data, sizeof(struct ProtectStruct)); SwapStructData(&gBattleSpritesDataPtr->battlerData[battlerAtk], &gBattleSpritesDataPtr->battlerData[battlerPartner], data, sizeof(struct BattleSpriteInfo)); + SwapStructData(&gBattleStruct->illusion[battlerAtk], &gBattleStruct->illusion[battlerPartner], data, sizeof(struct Illusion)); SWAP(gBattleSpritesDataPtr->battlerData[battlerAtk].invisible, gBattleSpritesDataPtr->battlerData[battlerPartner].invisible, temp); SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp); diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index 974730f120..dee29a58e0 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -277,5 +277,21 @@ DOUBLE_BATTLE_TEST("Ally switch swaps opposing sky drop targets if partner is be } } +DOUBLE_BATTLE_TEST("Ally Switch swaps Illusion data") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_ALLY_SWITCH].effect == EFFECT_ALLY_SWITCH); + PLAYER(SPECIES_HOOPA); + PLAYER(SPECIES_ZOROARK); + PLAYER(SPECIES_MAMOSWINE); // the third member here is required for zoroark + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); } + } THEN { + EXPECT(&gPlayerParty[2] == gBattleStruct->illusion[0].mon); + } +} + // Triple Battles required to test //TO_DO_BATTLE_TEST("Ally Switch fails if the user is in the middle of the field in a Triple Battle"); From 91c7bd9e53464ee78f9bf26758de93607ce5bba5 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 26 Dec 2024 17:22:45 -0300 Subject: [PATCH 42/45] Fixed givemon not respecting perfect IVs for species (#5873) --- include/pokemon.h | 1 + src/daycare.c | 21 ----------------- src/pokemon.c | 5 ++-- src/script_pokemon_util.c | 49 ++++++++++++++++++++++++++++++++++----- test/pokemon.c | 44 +++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 29 deletions(-) diff --git a/include/pokemon.h b/include/pokemon.h index 069290b363..8aca6c58d5 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -891,6 +891,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *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); +void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv); bool32 SpeciesHasGenderDifferences(u16 species); bool32 TryFormChange(u32 monId, u32 side, u16 method); void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); diff --git a/src/daycare.c b/src/daycare.c index 912537af56..4997f4efe9 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -590,27 +590,6 @@ static void UNUSED TriggerPendingDaycareMaleEgg(void) _TriggerPendingDaycareMaleEgg(&gSaveBlock1Ptr->daycare); } -// Removes the selected index from the given IV list and shifts the remaining -// elements to the left. -static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv) -{ - s32 i, j; - u8 temp[NUM_STATS]; - - ivs[selectedIv] = 0xFF; - for (i = 0; i < NUM_STATS; i++) - { - temp[i] = ivs[i]; - } - - j = 0; - for (i = 0; i < NUM_STATS; i++) - { - if (temp[i] != 0xFF) - ivs[j++] = temp[i]; - } -} - static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare) { u16 motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM); diff --git a/src/pokemon.c b/src/pokemon.c index 72aa2c7c62..c60e95cc6a 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -75,7 +75,6 @@ static void EncryptBoxMon(struct BoxPokemon *boxMon); static void DecryptBoxMon(struct BoxPokemon *boxMon); static void Task_PlayMapChosenOrBattleBGM(u8 taskId); static bool8 ShouldSkipFriendshipChange(void); -static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv); void TrySpecialOverworldEvo(); EWRAM_DATA static u8 sLearningMoveTableID = 0; @@ -6659,7 +6658,9 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) return 0; } -static void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv) +// Removes the selected index from the given IV list and shifts the remaining +// elements to the left. +void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv) { s32 i, j; u8 temp[NUM_STATS]; diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 020094389a..fc248435a9 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -487,12 +487,49 @@ void ScrCmd_createmon(struct ScriptContext *ctx) u8 speedEv = PARSE_FLAG(8, 0); u8 spAtkEv = PARSE_FLAG(9, 0); u8 spDefEv = PARSE_FLAG(10, 0); - u8 hpIv = PARSE_FLAG(11, Random() % (MAX_PER_STAT_IVS + 1)); - u8 atkIv = PARSE_FLAG(12, Random() % (MAX_PER_STAT_IVS + 1)); - u8 defIv = PARSE_FLAG(13, Random() % (MAX_PER_STAT_IVS + 1)); - u8 speedIv = PARSE_FLAG(14, Random() % (MAX_PER_STAT_IVS + 1)); - u8 spAtkIv = PARSE_FLAG(15, Random() % (MAX_PER_STAT_IVS + 1)); - u8 spDefIv = PARSE_FLAG(16, Random() % (MAX_PER_STAT_IVS + 1)); + u8 hpIv = Random() % (MAX_PER_STAT_IVS + 1); + u8 atkIv = Random() % (MAX_PER_STAT_IVS + 1); + u8 defIv = Random() % (MAX_PER_STAT_IVS + 1); + u8 speedIv = Random() % (MAX_PER_STAT_IVS + 1); + u8 spAtkIv = Random() % (MAX_PER_STAT_IVS + 1); + u8 spDefIv = Random() % (MAX_PER_STAT_IVS + 1); + + // Perfect IV calculation + u32 i; + u8 availableIVs[NUM_STATS]; + u8 selectedIvs[NUM_STATS]; + if (gSpeciesInfo[species].perfectIVCount != 0) + { + // Initialize a list of IV indices. + for (i = 0; i < NUM_STATS; i++) + availableIVs[i] = i; + + // Select the IVs that will be perfected. + for (i = 0; i < NUM_STATS && i < gSpeciesInfo[species].perfectIVCount; i++) + { + u8 index = Random() % (NUM_STATS - i); + selectedIvs[i] = availableIVs[index]; + RemoveIVIndexFromList(availableIVs, index); + } + for (i = 0; i < NUM_STATS && i < gSpeciesInfo[species].perfectIVCount; i++) + { + switch (selectedIvs[i]) + { + case STAT_HP: hpIv = MAX_PER_STAT_IVS; break; + case STAT_ATK: atkIv = MAX_PER_STAT_IVS; break; + case STAT_DEF: defIv = MAX_PER_STAT_IVS; break; + case STAT_SPEED: speedIv = MAX_PER_STAT_IVS; break; + case STAT_SPATK: spAtkIv = MAX_PER_STAT_IVS; break; + case STAT_SPDEF: spDefIv = MAX_PER_STAT_IVS; break; + } + } + } + hpIv = PARSE_FLAG(11, hpIv); + atkIv = PARSE_FLAG(12, atkIv); + defIv = PARSE_FLAG(13, defIv); + speedIv = PARSE_FLAG(14, speedIv); + spAtkIv = PARSE_FLAG(15, spAtkIv); + spDefIv = PARSE_FLAG(16, spDefIv); u16 move1 = PARSE_FLAG(17, MOVE_NONE); u16 move2 = PARSE_FLAG(18, MOVE_NONE); u16 move3 = PARSE_FLAG(19, MOVE_NONE); diff --git a/test/pokemon.c b/test/pokemon.c index f5431559ee..00b08ebb79 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -210,6 +210,50 @@ TEST("givemon [simple]") EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_LEVEL), 100); } +TEST("givemon respects perfectIVCount") +{ + ZeroPlayerPartyMons(); + u32 perfectIVs[6] = {0}; + + ASSUME(gSpeciesInfo[SPECIES_MEW].perfectIVCount == 3); + ASSUME(gSpeciesInfo[SPECIES_CELEBI].perfectIVCount == 3); + ASSUME(gSpeciesInfo[SPECIES_JIRACHI].perfectIVCount == 3); + ASSUME(gSpeciesInfo[SPECIES_MANAPHY].perfectIVCount == 3); + ASSUME(gSpeciesInfo[SPECIES_VICTINI].perfectIVCount == 3); + ASSUME(gSpeciesInfo[SPECIES_DIANCIE].perfectIVCount == 3); + + RUN_OVERWORLD_SCRIPT( + givemon SPECIES_MEW, 100; + givemon SPECIES_CELEBI, 100; + givemon SPECIES_JIRACHI, 100; + givemon SPECIES_MANAPHY, 100; + givemon SPECIES_VICTINI, 100; + givemon SPECIES_DIANCIE, 100; + ); + + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_MEW); + EXPECT_EQ(GetMonData(&gPlayerParty[1], MON_DATA_SPECIES), SPECIES_CELEBI); + EXPECT_EQ(GetMonData(&gPlayerParty[2], MON_DATA_SPECIES), SPECIES_JIRACHI); + EXPECT_EQ(GetMonData(&gPlayerParty[3], MON_DATA_SPECIES), SPECIES_MANAPHY); + EXPECT_EQ(GetMonData(&gPlayerParty[4], MON_DATA_SPECIES), SPECIES_VICTINI); + EXPECT_EQ(GetMonData(&gPlayerParty[5], MON_DATA_SPECIES), SPECIES_DIANCIE); + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_LEVEL), 100); + EXPECT_EQ(GetMonData(&gPlayerParty[1], MON_DATA_LEVEL), 100); + EXPECT_EQ(GetMonData(&gPlayerParty[2], MON_DATA_LEVEL), 100); + EXPECT_EQ(GetMonData(&gPlayerParty[3], MON_DATA_LEVEL), 100); + EXPECT_EQ(GetMonData(&gPlayerParty[4], MON_DATA_LEVEL), 100); + EXPECT_EQ(GetMonData(&gPlayerParty[5], MON_DATA_LEVEL), 100); + for (u32 j = 0; j < 6; j++) + { + for (u32 k = 0; k < NUM_STATS; k++) + { + if (GetMonData(&gPlayerParty[j], MON_DATA_HP_IV + k) == MAX_PER_STAT_IVS) + perfectIVs[j]++; + } + EXPECT_GE(perfectIVs[j], 3); + } +} + TEST("givemon [moves]") { ZeroPlayerPartyMons(); From 767e5a1f29bf74a2b664095f4ec7744f4f23811e Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:55:56 -0500 Subject: [PATCH 43/45] Fix Script Scrollable Multichoice Arrow Positions (#5884) Co-authored-by: ghoulslash --- src/field_specials.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/field_specials.c b/src/field_specials.c index f5154f8424..7e05fb6cc5 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -2766,10 +2766,12 @@ static void ScrollableMultichoice_UpdateScrollArrows(u8 taskId) struct ScrollArrowsTemplate template = sScrollableMultichoice_ScrollArrowsTemplate; if (task->tMaxItemsOnScreen != task->tNumItems) { + u32 y0 = (8 * (task->tTop - 1)); + template.firstX = (task->tWidth / 2) * 8 + 12 + (task->tLeft - 1) * 8; - template.firstY = 8; + template.firstY = 8 + y0; template.secondX = (task->tWidth / 2) * 8 + 12 + (task->tLeft - 1) * 8; - template.secondY = task->tHeight * 8 + 10; + template.secondY = task->tHeight * 8 + 10 + y0; template.fullyUpThreshold = 0; template.fullyDownThreshold = task->tNumItems - task->tMaxItemsOnScreen; task->tScrollArrowId = AddScrollIndicatorArrowPair(&template, &gScrollableMultichoice_ScrollOffset); From dccf2632b25c2d0d0c9d879873ffa15073d8f72b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 27 Dec 2024 07:16:30 -0300 Subject: [PATCH 44/45] Added missing Belch tests (#5881) --- test/battle/move_effect/belch.c | 66 +++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/test/battle/move_effect/belch.c b/test/battle/move_effect/belch.c index 2a732e0e45..f8e28929f9 100644 --- a/test/battle/move_effect/belch.c +++ b/test/battle/move_effect/belch.c @@ -21,7 +21,7 @@ AI_SINGLE_BATTLE_TEST("AI: Belch has nonzero score after eating a berry") TURN { MOVE(player, MOVE_MUD_SHOT); EXPECT_MOVE(opponent, MOVE_TACKLE); } TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_BELCH);} } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, opponent); } } @@ -53,6 +53,64 @@ SINGLE_BATTLE_TEST("Belch cannot be used if the user has not eaten a berry") } } -TO_DO_BATTLE_TEST("Belch can still be used after switching out"); -TO_DO_BATTLE_TEST("Belch can still be used after fainting"); -TO_DO_BATTLE_TEST("Belch can still be used after restoring the consumed berry"); +SINGLE_BATTLE_TEST("Belch can still be used after switching out") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_STUFF_CHEEKS].effect == EFFECT_STUFF_CHEEKS); + PLAYER(SPECIES_GREEDENT) { Item(ITEM_ORAN_BERRY); } + PLAYER(SPECIES_SKWOVET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STUFF_CHEEKS); } + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + TURN { MOVE(player, MOVE_BELCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STUFF_CHEEKS, player); + SWITCH_OUT_MESSAGE("Greedent"); + SWITCH_OUT_MESSAGE("Skwovet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, player); + } +} + +SINGLE_BATTLE_TEST("Belch can still be used after fainting") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_STUFF_CHEEKS].effect == EFFECT_STUFF_CHEEKS); + ASSUME(gMovesInfo[MOVE_FISSURE].effect == EFFECT_OHKO); + ASSUME(gMovesInfo[MOVE_REVIVAL_BLESSING].effect == EFFECT_REVIVAL_BLESSING); + PLAYER(SPECIES_GREEDENT) { Item(ITEM_ORAN_BERRY); } + PLAYER(SPECIES_SKWOVET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STUFF_CHEEKS); MOVE(opponent, MOVE_FISSURE); SEND_OUT(player, 1); } + TURN { MOVE(player, MOVE_REVIVAL_BLESSING, partyIndex: 0); } + TURN { SWITCH(player, 0); } + TURN { MOVE(player, MOVE_BELCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STUFF_CHEEKS, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FISSURE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REVIVAL_BLESSING, player); + SWITCH_OUT_MESSAGE("Skwovet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, player); + } +} + +SINGLE_BATTLE_TEST("Belch can still be used after restoring the consumed berry") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_STUFF_CHEEKS].effect == EFFECT_STUFF_CHEEKS); + ASSUME(gMovesInfo[MOVE_RECYCLE].effect == EFFECT_RECYCLE); + PLAYER(SPECIES_GREEDENT) { Item(ITEM_ORAN_BERRY); } + PLAYER(SPECIES_SKWOVET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STUFF_CHEEKS); } + TURN { MOVE(player, MOVE_RECYCLE); } + TURN { MOVE(player, MOVE_BELCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STUFF_CHEEKS, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RECYCLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, player); + } +} From 5900a010613fd981a2d249485c1d2f94341d8a5a Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 27 Dec 2024 21:14:05 +0100 Subject: [PATCH 45/45] Atk Canceller refactor / reorder / clean up (#5885) --- include/battle_util.h | 19 +- src/battle_script_commands.c | 63 +- src/battle_util.c | 1296 +++++++++++++++------------ test/battle/ability/stance_change.c | 1 - test/battle/gimmick/dynamax.c | 1 + 5 files changed, 716 insertions(+), 664 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index adeb850061..9539321cd5 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -100,33 +100,37 @@ struct TypePower enum { CANCELLER_FLAGS, + CANCELLER_STANCE_CHANGE_1, CANCELLER_SKY_DROP, + CANCELLER_RECHARGE, CANCELLER_ASLEEP, CANCELLER_FROZEN, CANCELLER_OBEDIENCE, CANCELLER_TRUANT, - CANCELLER_RECHARGE, CANCELLER_FLINCH, + CANCELLER_IN_LOVE, CANCELLER_DISABLED, - CANCELLER_GRAVITY, CANCELLER_HEAL_BLOCKED, + CANCELLER_GRAVITY, + CANCELLER_THROAT_CHOP, CANCELLER_TAUNTED, CANCELLER_IMPRISONED, CANCELLER_CONFUSED, CANCELLER_PARALYSED, - CANCELLER_IN_LOVE, CANCELLER_BIDE, CANCELLER_THAW, + CANCELLER_STANCE_CHANGE_2, + CANCELLER_WEATHER_PRIMAL, + CANCELLER_DYNAMAX_BLOCKED, CANCELLER_POWDER_MOVE, CANCELLER_POWDER_STATUS, - CANCELLER_THROAT_CHOP, + CANCELLER_PROTEAN, + CANCELLER_PSYCHIC_TERRAIN, CANCELLER_EXPLODING_DAMP, CANCELLER_MULTIHIT_MOVES, CANCELLER_Z_MOVES, CANCELLER_MULTI_TARGET_MOVES, CANCELLER_END, - CANCELLER_PSYCHIC_TERRAIN, - CANCELLER_END2, }; enum { @@ -197,9 +201,8 @@ u8 DoBattlerEndTurnEffects(void); bool32 HandleWishPerishSongOnTurnEnd(void); bool32 HandleFaintedMonActions(void); void TryClearRageAndFuryCutter(void); -u8 AtkCanceller_UnableToUseMove(u32 moveType); +u32 AtkCanceller_MoveSuccessOrder(void); void SetAtkCancellerForCalledMove(void); -u8 AtkCanceller_UnableToUseMove2(void); bool32 HasNoMonsToSwitch(u32 battler, u8 r1, u8 r2); bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility); u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 76a59fa9dc..0c9a7dd811 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1126,19 +1126,6 @@ static bool32 NoTargetPresent(u8 battler, u32 move) return FALSE; } -static bool32 TryFormChangeBeforeMove(void) -{ - bool32 result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE); - if (!result) - result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE_CATEGORY); - if (!result) - return FALSE; - - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AttackerFormChange; - return TRUE; -} - bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType) { if ((ability == ABILITY_PROTEAN || ability == ABILITY_LIBERO) @@ -1177,8 +1164,6 @@ static void Cmd_attackcanceler(void) CMD_ARGS(); s32 i; - u16 attackerAbility = GetBattlerAbility(gBattlerAttacker); - u32 moveType = GetMoveType(gCurrentMove); if (gBattleStruct->usedEjectItem & (1u << gBattlerAttacker)) { @@ -1187,14 +1172,6 @@ static void Cmd_attackcanceler(void) return; } - // Weight-based moves are blocked by Dynamax. - if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && IsMoveBlockedByDynamax(gCurrentMove)) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveBlockedByDynamax; - return; - } - if (gBattleOutcome != 0) { gCurrentActionFuncId = B_ACTION_FINISHED; @@ -1207,28 +1184,8 @@ static void Cmd_attackcanceler(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } - if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) + if (AtkCanceller_MoveSuccessOrder()) return; - if (AtkCanceller_UnableToUseMove(moveType)) - return; - - if (WEATHER_HAS_EFFECT && gMovesInfo[gCurrentMove].power) - { - if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL)) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; - return; - } - else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL)) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; - return; - } - } if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND @@ -1242,22 +1199,6 @@ static void Cmd_attackcanceler(void) return; } - // Check Protean activation. - if (ProteanTryChangeType(gBattlerAttacker, attackerAbility, gCurrentMove, moveType)) - { - if (B_PROTEAN_LIBERO == GEN_9) - gDisableStructs[gBattlerAttacker].usedProteanLibero = TRUE; - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - gBattlerAbility = gBattlerAttacker; - BattleScriptPushCursor(); - PrepareStringBattle(STRINGID_EMPTYSTRING3, gBattlerAttacker); - gBattleCommunication[MSG_DISPLAY] = 1; - gBattlescriptCurrInstr = BattleScript_ProteanActivates; - return; - } - - if (AtkCanceller_UnableToUseMove2()) - return; if (AbilityBattleEffects(ABILITYEFFECT_MOVES_BLOCK, gBattlerTarget, 0, 0, 0)) return; if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE @@ -1268,8 +1209,6 @@ static void Cmd_attackcanceler(void) gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; return; } - if (B_STANCE_CHANGE_FAIL >= GEN_7 && TryFormChangeBeforeMove()) - return; gHitMarker &= ~HITMARKER_ALLOW_NO_PP; diff --git a/src/battle_util.c b/src/battle_util.c index 900ebf2d6e..b09f3622f6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -56,6 +56,7 @@ match the ROM; this is also why sSoundMovesTable's declaration is in the middle functions instead of at the top of the file with the other declarations. */ +typedef void (*MoveSuccessOrderCancellers)(u32 *effect); static bool32 TryRemoveScreens(u32 battler); static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler); static u32 GetFlingPowerFromItemId(u32 itemId); @@ -3116,638 +3117,747 @@ void TryClearRageAndFuryCutter(void) } } +static inline bool32 TryFormChangeBeforeMove(void) +{ + bool32 result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE); + if (!result) + result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE_CATEGORY); + if (!result) + return FALSE; + + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AttackerFormChange; + return TRUE; +} + void SetAtkCancellerForCalledMove(void) { gBattleStruct->atkCancellerTracker = CANCELLER_HEAL_BLOCKED; gBattleStruct->isAtkCancelerForCalledMove = TRUE; } -u8 AtkCanceller_UnableToUseMove(u32 moveType) +static void CancellerFlags(u32 *effect) { - u32 effect = 0; - u32 obedienceResult; - do + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND; + gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; + gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH; +} + +static void CancellerStanceChangeOne(u32 *effect) +{ + if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) + *effect = 1; +} + +static void CancellerSkyDrop(u32 *effect) +{ + // If Pokemon is being held in Sky Drop + if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED) { - switch (gBattleStruct->atkCancellerTracker) + gBattlescriptCurrInstr = BattleScript_MoveEnd; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerRecharge(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) + { + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RECHARGE; + gDisableStructs[gBattlerAttacker].rechargeTimer = 0; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerAsleep(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + { + if (UproarWakeUpCheck(gBattlerAttacker)) { - case CANCELLER_FLAGS: // flags clear - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND; - gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; - gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH; - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_SKY_DROP: - // If Pokemon is being held in Sky Drop - if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED) - { - gBattlescriptCurrInstr = BattleScript_MoveEnd; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_ASLEEP: // check being asleep + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); + gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + BattleScriptPushCursor(); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; + gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; + *effect = 2; + } + else + { + u8 toSub; + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_EARLY_BIRD) + toSub = 2; + else + toSub = 1; + if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) < toSub) + gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; + else + gBattleMons[gBattlerAttacker].status1 -= toSub; if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) { - if (UproarWakeUpCheck(gBattlerAttacker)) + if (gChosenMove != MOVE_SNORE && gChosenMove != MOVE_SLEEP_TALK) { - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; - BattleScriptPushCursor(); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; - gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; - effect = 2; - } - else - { - u8 toSub; - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_EARLY_BIRD) - toSub = 2; - else - toSub = 1; - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) < toSub) - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - else - gBattleMons[gBattlerAttacker].status1 -= toSub; - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) - { - if (gChosenMove != MOVE_SNORE && gChosenMove != MOVE_SLEEP_TALK) - { - gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 2; - } - } - else - { - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; - BattleScriptPushCursor(); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; - gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; - effect = 2; - } - } - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_FROZEN: // check being frozen - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !(gMovesInfo[gCurrentMove].thawsUser)) - { - if (!RandomPercentage(RNG_FROZEN, 20)) - { - gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen; - gHitMarker |= (HITMARKER_NO_ATTACKSTRING | HITMARKER_UNABLE_TO_USE_MOVE); - } - else // unfreeze - { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED; - } - effect = 2; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_OBEDIENCE: - obedienceResult = GetAttackerObedienceForAction(); - if (obedienceResult != OBEYS - && !(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves - && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) - { - switch (obedienceResult) - { - case DISOBEYS_LOAFS: - // Randomly select, then print a disobedient string - // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE - gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS); - gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; - case DISOBEYS_HITS_SELF: - gBattlerTarget = gBattlerAttacker; - struct DamageCalculationData damageCalcData; - damageCalcData.battlerAtk = damageCalcData.battlerDef = gBattlerAttacker; - damageCalcData.move = MOVE_NONE; - damageCalcData.moveType = TYPE_MYSTERY; - damageCalcData.isCrit = FALSE; - damageCalcData.randomFactor = FALSE; - damageCalcData.updateFlags = TRUE; - gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&damageCalcData, 40); - gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; + gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - gHitMarker |= HITMARKER_OBEYS; - break; - case DISOBEYS_FALL_ASLEEP: - if (IsSleepClauseEnabled()) - gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; - case DISOBEYS_WHILE_ASLEEP: - gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; - case DISOBEYS_RANDOM_MOVE: - gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; - SetAtkCancellerForCalledMove(); - gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; - gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; - gHitMarker |= HITMARKER_OBEYS; - break; + *effect = 2; } - effect = 1; } else { - gHitMarker |= HITMARKER_OBEYS; + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); + gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + BattleScriptPushCursor(); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; + gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; + *effect = 2; } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_TRUANT: // truant - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) - { - CancelMultiTurnMoves(gBattlerAttacker); - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LOAFING; - gBattlerAbility = gBattlerAttacker; - gBattlescriptCurrInstr = BattleScript_TruantLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_RECHARGE: // recharge - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) - { - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RECHARGE; - gDisableStructs[gBattlerAttacker].rechargeTimer = 0; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_FLINCH: // flinch - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED) - { - gProtectStructs[gBattlerAttacker].flinchImmobility = TRUE; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_DISABLED: // disabled move - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE) - { - gProtectStructs[gBattlerAttacker].usedDisabledMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_HEAL_BLOCKED: - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].usedHealBlockedMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_GRAVITY: - if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].usedGravityPreventedMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_TAUNTED: // taunt - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].tauntTimer && IS_MOVE_STATUS(gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].usedTauntedMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_IMPRISONED: // imprisoned - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].usedImprisonedMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_CONFUSED: // confusion - if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) - { - if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION)) - gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) - { - // confusion dmg - if (RandomPercentage(RNG_CONFUSION, (B_CONFUSION_SELF_DMG_CHANCE >= GEN_7 ? 33 : 50))) - { - gBattleCommunication[MULTISTRING_CHOOSER] = TRUE; - gBattlerTarget = gBattlerAttacker; - struct DamageCalculationData damageCalcData; - damageCalcData.battlerAtk = damageCalcData.battlerDef = gBattlerAttacker; - damageCalcData.move = MOVE_NONE; - damageCalcData.moveType = TYPE_MYSTERY; - damageCalcData.isCrit = FALSE; - damageCalcData.randomFactor = FALSE; - damageCalcData.updateFlags = TRUE; - gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&damageCalcData, 40); - gProtectStructs[gBattlerAttacker].confusionSelfDmg = TRUE; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - } - else - { - gBattleCommunication[MULTISTRING_CHOOSER] = FALSE; - BattleScriptPushCursor(); - } - gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused; - } - else // snapped out of confusion - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore; - } - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_PARALYSED: // paralysis - if (!gBattleStruct->isAtkCancelerForCalledMove && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && !RandomPercentage(RNG_PARALYSIS, 75)) - { - gProtectStructs[gBattlerAttacker].prlzImmobility = TRUE; - // This is removed in FRLG and Emerald for some reason - //CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_IN_LOVE: // infatuation - if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) - { - gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10); - if (!RandomPercentage(RNG_INFATUATION, 50)) - { - BattleScriptPushCursor(); - } - else - { - BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack); - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - gProtectStructs[gBattlerAttacker].loveImmobility = TRUE; - CancelMultiTurnMoves(gBattlerAttacker); - } - gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_BIDE: // bide - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) - { - gBattleMons[gBattlerAttacker].status2 -= STATUS2_BIDE_TURN(1); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) - { - gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; - } - else - { - // This is removed in FRLG and Emerald for some reason - //gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS; - if (gBideDmg[gBattlerAttacker]) - { - gCurrentMove = MOVE_BIDE; - gBattlerTarget = gBideTarget[gBattlerAttacker]; - if (gAbsentBattlerFlags & (1u << gBattlerTarget)) - gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); - gBattlescriptCurrInstr = BattleScript_BideAttack; - } - else - { - gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack; - } - } - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_THAW: // move thawing - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) - { - if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) - { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE; - } - effect = 2; - } - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && gMovesInfo[gCurrentMove].thawsUser) - { - if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !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: - if ((gMovesInfo[gCurrentMove].powderMove) && (gBattlerAttacker != gBattlerTarget)) - { - if (B_POWDER_GRASS >= GEN_6 - && (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) || GetBattlerAbility(gBattlerTarget) == ABILITY_OVERCOAT)) - { - gBattlerAbility = gBattlerTarget; - effect = 1; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) - { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_SAFETY_GOGGLES); - gLastUsedItem = gBattleMons[gBattlerTarget].item; - effect = 1; - } + } + } +} - if (effect != 0) - gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_POWDER_STATUS: - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER) - { - u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]]; - if ((moveType == TYPE_FIRE && !gBattleStruct->pledgeMove) - || (gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE) - || (gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE && gBattleStruct->pledgeMove)) - { - gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD - && (B_POWDER_RAIN < GEN_7 || !IsBattlerWeatherAffected(gBattlerAttacker, B_WEATHER_RAIN_PRIMAL))) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE - || HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE)) - gBattlescriptCurrInstr = BattleScript_MoveUsedPowder; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_THROAT_CHOP: - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer && gMovesInfo[gCurrentMove].soundMove) - { - gProtectStructs[gBattlerAttacker].usedThroatChopPreventedMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_Z_MOVES: - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) - { - // For Z-Mirror Move, so it doesn't play the animation twice. - bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE); - - // attacker has a queued z move - RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_Z_CRYSTAL); - SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE); - - gBattleScripting.battler = gBattlerAttacker; - if (gProtectStructs[gBattlerAttacker].powderSelfDmg) - { - if (!alreadyUsed) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_ZMoveActivatePowder; - } - } - else if (gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS) - { - if (!alreadyUsed) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_ZMoveActivateStatus; - } - } - else - { - if (!alreadyUsed) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_ZMoveActivateDamaging; - } - } - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_EXPLODING_DAMP: +static void CancellerFrozen(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !(gMovesInfo[gCurrentMove].thawsUser)) + { + if (!RandomPercentage(RNG_FROZEN, 20)) { - u32 dampBattler = IsAbilityOnField(ABILITY_DAMP); - if (dampBattler && (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION - || gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN)) - { - gBattleScripting.battler = dampBattler - 1; - gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; + gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen; + gHitMarker |= (HITMARKER_NO_ATTACKSTRING | HITMARKER_UNABLE_TO_USE_MOVE); + } + else // unfreeze + { + gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED; + } + *effect = 2; + } +} + +static void CancellerObedience(u32 *effect) +{ + u32 obedienceResult = GetAttackerObedienceForAction(); + if (obedienceResult != OBEYS + && !(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves + && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) + { + switch (obedienceResult) + { + case DISOBEYS_LOAFS: + // Randomly select, then print a disobedient string + // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE + gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS); + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + break; + case DISOBEYS_HITS_SELF: + gBattlerTarget = gBattlerAttacker; + struct DamageCalculationData damageCalcData; + damageCalcData.battlerAtk = damageCalcData.battlerDef = gBattlerAttacker; + damageCalcData.move = MOVE_NONE; + damageCalcData.moveType = TYPE_MYSTERY; + damageCalcData.isCrit = FALSE; + damageCalcData.randomFactor = FALSE; + damageCalcData.updateFlags = TRUE; + gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&damageCalcData, 40); + gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gHitMarker |= HITMARKER_OBEYS; + break; + case DISOBEYS_FALL_ASLEEP: + if (IsSleepClauseEnabled()) + gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + break; + case DISOBEYS_WHILE_ASLEEP: + gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + break; + case DISOBEYS_RANDOM_MOVE: + gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; + SetAtkCancellerForCalledMove(); + gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; + gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; + gHitMarker |= HITMARKER_OBEYS; break; } - case CANCELLER_MULTIHIT_MOVES: - if (gMovesInfo[gCurrentMove].effect == EFFECT_MULTI_HIT) + *effect = 1; + } + else + { + gHitMarker |= HITMARKER_OBEYS; + } +} + +static void CancellerTruant(u32 *effect) +{ + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) + { + CancelMultiTurnMoves(gBattlerAttacker); + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LOAFING; + gBattlerAbility = gBattlerAttacker; + gBattlescriptCurrInstr = BattleScript_TruantLoafingAround; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + *effect = 1; + } +} + +static void CancellerFlinch(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED) + { + gProtectStructs[gBattlerAttacker].flinchImmobility = TRUE; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerInLove(u32 *effect) +{ + if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) + { + gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10); + if (!RandomPercentage(RNG_INFATUATION, 50)) + { + BattleScriptPushCursor(); + } + else + { + BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack); + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gProtectStructs[gBattlerAttacker].loveImmobility = TRUE; + CancelMultiTurnMoves(gBattlerAttacker); + } + gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; + *effect = 1; + } +} + +static void CancellerDisabled(u32 *effect) +{ + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE) + { + gProtectStructs[gBattlerAttacker].usedDisabledMove = TRUE; + gBattleScripting.battler = gBattlerAttacker; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerHealBlocked(u32 *effect) +{ + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) + { + gProtectStructs[gBattlerAttacker].usedHealBlockedMove = TRUE; + gBattleScripting.battler = gBattlerAttacker; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerGravity(u32 *effect) +{ + if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(gCurrentMove)) + { + gProtectStructs[gBattlerAttacker].usedGravityPreventedMove = TRUE; + gBattleScripting.battler = gBattlerAttacker; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerThroatChop(u32 *effect) +{ + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer && gMovesInfo[gCurrentMove].soundMove) + { + gProtectStructs[gBattlerAttacker].usedThroatChopPreventedMove = TRUE; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerTaunted(u32 *effect) +{ + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].tauntTimer && IS_MOVE_STATUS(gCurrentMove)) + { + gProtectStructs[gBattlerAttacker].usedTauntedMove = TRUE; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerImprisoned(u32 *effect) +{ + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove)) + { + gProtectStructs[gBattlerAttacker].usedImprisonedMove = TRUE; + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerConfused(u32 *effect) +{ + if (gBattleStruct->isAtkCancelerForCalledMove) + return; + + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) + { + if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION)) + gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) + { + // confusion dmg + if (RandomPercentage(RNG_CONFUSION, (B_CONFUSION_SELF_DMG_CHANCE >= GEN_7 ? 33 : 50))) { - u32 ability = GetBattlerAbility(gBattlerAttacker); - - if (ability == ABILITY_SKILL_LINK) - { - gMultiHitCounter = 5; - } - else if (ability == ABILITY_BATTLE_BOND - && gCurrentMove == MOVE_WATER_SHURIKEN - && gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_ASH) - { - gMultiHitCounter = 3; - } - else - { - SetRandomMultiHitCounter(); - } - - PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) - } - else if (gMovesInfo[gCurrentMove].strikeCount > 1) - { - if (gMovesInfo[gCurrentMove].effect == EFFECT_POPULATION_BOMB && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) - { - gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 10); - } - else - { - gMultiHitCounter = gMovesInfo[gCurrentMove].strikeCount; - - if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS - && CanTargetPartner(gBattlerAttacker, gBattlerTarget) - && TargetFullyImmuneToCurrMove(gBattlerAttacker, gBattlerTarget)) - gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); - } - - PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) - } - else if (B_BEAT_UP >= GEN_5 && gMovesInfo[gCurrentMove].effect == EFFECT_BEAT_UP) - { - struct Pokemon* party = GetBattlerParty(gBattlerAttacker); - int i; - - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&party[i], MON_DATA_HP) - && GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE - && !GetMonData(&party[i], MON_DATA_IS_EGG) - && !GetMonData(&party[i], MON_DATA_STATUS)) - gMultiHitCounter++; - } - - gBattleStruct->beatUpSlot = 0; - PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) + gBattleCommunication[MULTISTRING_CHOOSER] = TRUE; + gBattlerTarget = gBattlerAttacker; + struct DamageCalculationData damageCalcData; + damageCalcData.battlerAtk = damageCalcData.battlerDef = gBattlerAttacker; + damageCalcData.move = MOVE_NONE; + damageCalcData.moveType = TYPE_MYSTERY; + damageCalcData.isCrit = FALSE; + damageCalcData.randomFactor = FALSE; + damageCalcData.updateFlags = TRUE; + gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&damageCalcData, 40); + gProtectStructs[gBattlerAttacker].confusionSelfDmg = TRUE; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; } else { - gMultiHitCounter = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = FALSE; + BattleScriptPushCursor(); } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_MULTI_TARGET_MOVES: - if (!IsDoubleBattle()) + gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused; + } + else // snapped out of confusion + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore; + } + *effect = 1; + } +} + +static void CancellerParalysed(u32 *effect) +{ + if (!gBattleStruct->isAtkCancelerForCalledMove && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && !RandomPercentage(RNG_PARALYSIS, 75)) + { + gProtectStructs[gBattlerAttacker].prlzImmobility = TRUE; + // This is removed in FRLG and Emerald for some reason + //CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerBide(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) + { + gBattleMons[gBattlerAttacker].status2 -= STATUS2_BIDE_TURN(1); + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) + { + gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; + } + else + { + // This is removed in FRLG and Emerald for some reason + //gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS; + if (gBideDmg[gBattlerAttacker]) { - gBattleStruct->atkCancellerTracker++; - break; + gCurrentMove = MOVE_BIDE; + gBattlerTarget = gBideTarget[gBattlerAttacker]; + if (gAbsentBattlerFlags & (1u << gBattlerTarget)) + gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); + gBattlescriptCurrInstr = BattleScript_BideAttack; } - - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - if (IsSpreadMove(moveTarget)) + else { - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) - { - if (gBattleStruct->bouncedMoveIsUsed && B_SIDE_OPPONENT == GetBattlerSide(battlerDef)) - continue; - - if (gBattlerAttacker == battlerDef - || !IsBattlerAlive(battlerDef) - || (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef)) - || IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check - { - gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT; - gBattleStruct->noResultString[battlerDef] = TRUE; - } - else if (AbilityBattleEffects(ABILITYEFFECT_WOULD_BLOCK, battlerDef, 0, 0, 0) - || (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN) && GetMovePriority(gBattlerAttacker, gCurrentMove) > 0)) - { - gBattleStruct->moveResultFlags[battlerDef] = 0; - gBattleStruct->noResultString[battlerDef] = TRUE; - } - else if (AbilityBattleEffects(ABILITYEFFECT_WOULD_ABSORB, battlerDef, 0, 0, gCurrentMove)) - { - gBattleStruct->moveResultFlags[battlerDef] = 0; - gBattleStruct->noResultString[battlerDef] = DO_ACCURACY_CHECK; - } - else - { - CalcTypeEffectivenessMultiplier(gCurrentMove, gMovesInfo[gCurrentMove].type, gBattlerAttacker, battlerDef, GetBattlerAbility(battlerDef), TRUE); - } - } - if (moveTarget == MOVE_TARGET_BOTH) - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, gBattlerAttacker); - else - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker); - + gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack; } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_END: - break; + } + *effect = 1; + } +} + +static void CancellerThaw(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) + { + if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + { + gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE; + } + *effect = 2; + } + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && gMovesInfo[gCurrentMove].thawsUser) + { + if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !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; + } +} + +static void CancellerStanceChangeTwo(u32 *effect) +{ + if (B_STANCE_CHANGE_FAIL >= GEN_7 && TryFormChangeBeforeMove()) + *effect = 1; +} + +static void CancellerWeatherPrimal(u32 *effect) +{ + if (WEATHER_HAS_EFFECT && gMovesInfo[gCurrentMove].power) + { + u32 moveType = GetMoveType(gCurrentMove); + if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN; + *effect = 1; + } + else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN; + *effect = 1; + } + if (*effect == 1) + { + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; + } + } +} + +static void CancellerDynamaxBlocked(u32 *effect) +{ + if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && IsMoveBlockedByDynamax(gCurrentMove)) + { + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveBlockedByDynamax; + *effect = 1; + } +} + +static void CancellerPowderMove(u32 *effect) +{ + if ((gMovesInfo[gCurrentMove].powderMove) && (gBattlerAttacker != gBattlerTarget)) + { + if (B_POWDER_GRASS >= GEN_6 + && (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) || GetBattlerAbility(gBattlerTarget) == ABILITY_OVERCOAT)) + { + gBattlerAbility = gBattlerTarget; + *effect = 1; + } + else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) + { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_SAFETY_GOGGLES); + gLastUsedItem = gBattleMons[gBattlerTarget].item; + *effect = 1; } - } while (gBattleStruct->atkCancellerTracker != CANCELLER_END && gBattleStruct->atkCancellerTracker != CANCELLER_END2 && effect == 0); + if (*effect != 0) + gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; + } +} + +static void CancellerPowderStatus(u32 *effect) +{ + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER) + { + u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]]; + if ((GetMoveType(gCurrentMove) == TYPE_FIRE && !gBattleStruct->pledgeMove) + || (gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE) + || (gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE && gBattleStruct->pledgeMove)) + { + gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD + && (B_POWDER_RAIN < GEN_7 || !IsBattlerWeatherAffected(gBattlerAttacker, B_WEATHER_RAIN_PRIMAL))) + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE + || HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE)) + gBattlescriptCurrInstr = BattleScript_MoveUsedPowder; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } + } +} + +static void CancellerProtean(u32 *effect) +{ + u32 moveType = GetMoveType(gCurrentMove); + if (ProteanTryChangeType(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gCurrentMove, moveType)) + { + if (B_PROTEAN_LIBERO == GEN_9) + gDisableStructs[gBattlerAttacker].usedProteanLibero = TRUE; + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); + gBattlerAbility = gBattlerAttacker; + BattleScriptPushCursor(); + PrepareStringBattle(STRINGID_EMPTYSTRING3, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + gBattlescriptCurrInstr = BattleScript_ProteanActivates; + *effect = 1; + } +} + +static void CancellerPsychicTerrain(u32 *effect) +{ + if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN + && IsBattlerGrounded(gBattlerTarget) + && GetChosenMovePriority(gBattlerAttacker) > 0 + && gMovesInfo[gCurrentMove].target != MOVE_TARGET_ALL_BATTLERS + && gMovesInfo[gCurrentMove].target != MOVE_TARGET_OPPONENTS_FIELD + && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) + { + CancelMultiTurnMoves(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerExplodingDamp(u32 *effect) +{ + u32 dampBattler = IsAbilityOnField(ABILITY_DAMP); + if (dampBattler && (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION + || gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN)) + { + gBattleScripting.battler = dampBattler - 1; + gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + *effect = 1; + } +} + +static void CancellerMultihitMoves(u32 *effect) +{ + if (gMovesInfo[gCurrentMove].effect == EFFECT_MULTI_HIT) + { + u32 ability = GetBattlerAbility(gBattlerAttacker); + + if (ability == ABILITY_SKILL_LINK) + { + gMultiHitCounter = 5; + } + else if (ability == ABILITY_BATTLE_BOND + && gCurrentMove == MOVE_WATER_SHURIKEN + && gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_ASH) + { + gMultiHitCounter = 3; + } + else + { + SetRandomMultiHitCounter(); + } + + PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) + } + else if (gMovesInfo[gCurrentMove].strikeCount > 1) + { + if (gMovesInfo[gCurrentMove].effect == EFFECT_POPULATION_BOMB && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) + { + gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 10); + } + else + { + gMultiHitCounter = gMovesInfo[gCurrentMove].strikeCount; + + if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS + && CanTargetPartner(gBattlerAttacker, gBattlerTarget) + && TargetFullyImmuneToCurrMove(gBattlerAttacker, gBattlerTarget)) + gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); + } + + PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) + } + else if (B_BEAT_UP >= GEN_5 && gMovesInfo[gCurrentMove].effect == EFFECT_BEAT_UP) + { + struct Pokemon* party = GetBattlerParty(gBattlerAttacker); + int i; + + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&party[i], MON_DATA_HP) + && GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && !GetMonData(&party[i], MON_DATA_STATUS)) + gMultiHitCounter++; + } + + gBattleStruct->beatUpSlot = 0; + PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) + } + else + { + gMultiHitCounter = 0; + } +} + +static void CancellerZMoves(u32 *effect) +{ + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) + { + // For Z-Mirror Move, so it doesn't play the animation twice. + bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE); + + // attacker has a queued z move + RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_Z_CRYSTAL); + SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE); + + gBattleScripting.battler = gBattlerAttacker; + if (gProtectStructs[gBattlerAttacker].powderSelfDmg) + { + if (!alreadyUsed) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_ZMoveActivatePowder; + } + } + else if (gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS) + { + if (!alreadyUsed) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_ZMoveActivateStatus; + } + } + else + { + if (!alreadyUsed) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_ZMoveActivateDamaging; + } + } + *effect = 1; + } +} + +static void CancellerMultiTargetMoves(u32 *effect) +{ + u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + if (IsSpreadMove(moveTarget)) + { + for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + { + if (gBattleStruct->bouncedMoveIsUsed && B_SIDE_OPPONENT == GetBattlerSide(battlerDef)) + continue; + + if (gBattlerAttacker == battlerDef + || !IsBattlerAlive(battlerDef) + || (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef)) + || IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check + { + gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT; + gBattleStruct->noResultString[battlerDef] = TRUE; + } + else if (AbilityBattleEffects(ABILITYEFFECT_WOULD_BLOCK, battlerDef, 0, 0, 0) + || (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN) && GetMovePriority(gBattlerAttacker, gCurrentMove) > 0)) + { + gBattleStruct->moveResultFlags[battlerDef] = 0; + gBattleStruct->noResultString[battlerDef] = TRUE; + } + else if (AbilityBattleEffects(ABILITYEFFECT_WOULD_ABSORB, battlerDef, 0, 0, gCurrentMove)) + { + gBattleStruct->moveResultFlags[battlerDef] = 0; + gBattleStruct->noResultString[battlerDef] = DO_ACCURACY_CHECK; + } + else + { + CalcTypeEffectivenessMultiplier(gCurrentMove, gMovesInfo[gCurrentMove].type, gBattlerAttacker, battlerDef, GetBattlerAbility(battlerDef), TRUE); + } + } + if (moveTarget == MOVE_TARGET_BOTH) + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, gBattlerAttacker); + else + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker); + } +} + +static const MoveSuccessOrderCancellers sMoveSuccessOrderCancellers[] = +{ + [CANCELLER_FLAGS] = CancellerFlags, + [CANCELLER_STANCE_CHANGE_1] = CancellerStanceChangeOne, + [CANCELLER_SKY_DROP] = CancellerSkyDrop, + [CANCELLER_RECHARGE] = CancellerRecharge, + [CANCELLER_ASLEEP] = CancellerAsleep, + [CANCELLER_FROZEN] = CancellerFrozen, + [CANCELLER_OBEDIENCE] = CancellerObedience, + [CANCELLER_TRUANT] = CancellerTruant, + [CANCELLER_FLINCH] = CancellerFlinch, + [CANCELLER_IN_LOVE] = CancellerInLove, + [CANCELLER_DISABLED] = CancellerDisabled, + [CANCELLER_HEAL_BLOCKED] = CancellerHealBlocked, + [CANCELLER_GRAVITY] = CancellerGravity, + [CANCELLER_THROAT_CHOP] = CancellerThroatChop, + [CANCELLER_TAUNTED] = CancellerTaunted, + [CANCELLER_IMPRISONED] = CancellerImprisoned, + [CANCELLER_CONFUSED] = CancellerConfused, + [CANCELLER_PARALYSED] = CancellerParalysed, + [CANCELLER_BIDE] = CancellerBide, + [CANCELLER_THAW] = CancellerThaw, + [CANCELLER_STANCE_CHANGE_2] = CancellerStanceChangeTwo, + [CANCELLER_WEATHER_PRIMAL] = CancellerWeatherPrimal, + [CANCELLER_DYNAMAX_BLOCKED] = CancellerDynamaxBlocked, + [CANCELLER_POWDER_MOVE] = CancellerPowderMove, + [CANCELLER_POWDER_STATUS] = CancellerPowderStatus, + [CANCELLER_PROTEAN] = CancellerProtean, + [CANCELLER_PSYCHIC_TERRAIN] = CancellerPsychicTerrain, + [CANCELLER_EXPLODING_DAMP] = CancellerExplodingDamp, + [CANCELLER_MULTIHIT_MOVES] = CancellerMultihitMoves, + [CANCELLER_Z_MOVES] = CancellerZMoves, + [CANCELLER_MULTI_TARGET_MOVES] = CancellerMultiTargetMoves, +}; + +u32 AtkCanceller_MoveSuccessOrder(void) +{ + u32 effect = 0; + + while (gBattleStruct->atkCancellerTracker < CANCELLER_END && effect == 0) + { + sMoveSuccessOrderCancellers[gBattleStruct->atkCancellerTracker](&effect); + gBattleStruct->atkCancellerTracker++; + } if (effect == 2) { BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); MarkBattlerForControllerExec(gBattlerAttacker); } - return effect; -} - -// After Protean Activation. -u8 AtkCanceller_UnableToUseMove2(void) -{ - u8 effect = 0; - - do - { - switch (gBattleStruct->atkCancellerTracker) - { - case CANCELLER_END: - gBattleStruct->atkCancellerTracker++; - case CANCELLER_PSYCHIC_TERRAIN: - if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN - && IsBattlerGrounded(gBattlerTarget) - && GetChosenMovePriority(gBattlerAttacker) > 0 - && gMovesInfo[gCurrentMove].target != MOVE_TARGET_ALL_BATTLERS - && gMovesInfo[gCurrentMove].target != MOVE_TARGET_OPPONENTS_FIELD - && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) - { - CancelMultiTurnMoves(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - effect = 1; - } - gBattleStruct->atkCancellerTracker++; - break; - case CANCELLER_END2: - break; - } - - } while (gBattleStruct->atkCancellerTracker != CANCELLER_END2 && effect == 0); return effect; } diff --git a/test/battle/ability/stance_change.c b/test/battle/ability/stance_change.c index 8221e16385..f8a0c70b3e 100644 --- a/test/battle/ability/stance_change.c +++ b/test/battle/ability/stance_change.c @@ -63,7 +63,6 @@ SINGLE_BATTLE_TEST("Stance Change changes Aegislash from Blade to Shield when us SINGLE_BATTLE_TEST("Stance Change doesn't change Aegislash to Shield if King's Shield is called by a different move - Sleep Talk") { - KNOWN_FAILING; // Currently does change form GIVEN { ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK); PLAYER(SPECIES_AEGISLASH_BLADE) { Moves(MOVE_KINGS_SHIELD, MOVE_SLEEP_TALK); Status1(STATUS1_SLEEP_TURN(3)); } diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index 97b099d046..d76febbd0a 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -1431,6 +1431,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage" } // Bug Testing +// This test will fail if it's the first test a thread runs DOUBLE_BATTLE_TEST("(DYNAMAX) Max Flare doesn't softlock the game when fainting player partner") { GIVEN {