From ef1c60de67a1af3d945efe421c925fb0ea62e026 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Sun, 15 Oct 2023 18:53:11 +0100 Subject: [PATCH 01/15] Buffer 'GBA: '-prefixed messages TODO: Detect illegal opcodes in the test runner because mgba-rom-test evaluates them very slowly, making the TIMEOUT mechanism effectively realtime. --- tools/mgba-rom-test-hydra/main.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/mgba-rom-test-hydra/main.c b/tools/mgba-rom-test-hydra/main.c index 123d8a2552..c2189ac0df 100644 --- a/tools/mgba-rom-test-hydra/main.c +++ b/tools/mgba-rom-test-hydra/main.c @@ -2,9 +2,9 @@ * parses the output to display human-readable progress. * * Output lines starting with "GBA Debug: :" are parsed as commands to - * Hydra, other output lines starting with "GBA Debug: " are parsed as - * output from the current test, and any other lines are parsed as - * output from the mgba-rom-test process itself. + * Hydra, other output lines starting with "GBA Debug: " or with "GBA: " + * are parsed as output from the current test, and any other lines are + * parsed as output from the mgba-rom-test process itself. * * COMMANDS * N: Sets the test name to the remainder of the line. @@ -75,10 +75,17 @@ static void handle_read(int i, struct Runner *runner) { eol++; size_t n = eol - sol; - if (runner->input_buffer_size >= strlen("GBA Debug: ") - && !strncmp(sol, "GBA Debug: ", strlen("GBA Debug: "))) + char *soc; + if (runner->input_buffer_size >= strlen("GBA: ") + && !strncmp(sol, "GBA: ", strlen("GBA: "))) { - char *soc = sol + strlen("GBA Debug: "); + soc = sol + strlen("GBA: "); + goto buffer_output; + } + else if (runner->input_buffer_size >= strlen("GBA Debug: ") + && !strncmp(sol, "GBA Debug: ", strlen("GBA Debug: "))) + { + soc = sol + strlen("GBA Debug: "); if (soc[0] == ':') { switch (soc[1]) From 6e7e7fdafa21654bca58d9b68d739201c0b66746 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 23 Oct 2023 07:03:45 +0100 Subject: [PATCH 02/15] make check MODERN=1 in a separate build directory --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 80ee5303d3..5326383023 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,11 @@ ELF = $(ROM:.gba=.elf) MAP = $(ROM:.gba=.map) SYM = $(ROM:.gba=.sym) +ifeq ($(MODERN),0) TEST_OBJ_DIR_NAME := build/test +else +TEST_OBJ_DIR_NAME := build/modern-test +endif TESTELF = $(ROM:.gba=-test.elf) HEADLESSELF = $(ROM:.gba=-test-headless.elf) From b0b6e1604264722f63807c3649d996164565884f Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 23 Oct 2023 06:57:57 +0100 Subject: [PATCH 03/15] Separate ASSIGN_TEST from NEXT_TEST Silences a warning about an invalid pointer when building with modern. --- include/test/test.h | 1 + test/test_runner.c | 28 +++++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/test/test.h b/include/test/test.h index 5b3ab8af0c..e9c920bd0b 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -47,6 +47,7 @@ struct TestRunnerState u8 expectedResult; bool8 expectLeaks:1; bool8 inBenchmark:1; + bool8 tearDown:1; u32 timeoutSeconds; }; diff --git a/test/test_runner.c b/test/test_runner.c index 0ae4f0a185..ddfe23b3ec 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -56,9 +56,10 @@ static bool32 PrefixMatch(const char *pattern, const char *string) enum { STATE_INIT, - STATE_NEXT_TEST, + STATE_ASSIGN_TEST, STATE_RUN_TEST, STATE_REPORT_RESULT, + STATE_NEXT_TEST, STATE_EXIT, }; @@ -152,17 +153,15 @@ void CB2_TestRunner(void) } else { - gTestRunnerState.state = STATE_NEXT_TEST; - gTestRunnerState.test = __start_tests - 1; + gTestRunnerState.state = STATE_ASSIGN_TEST; + gTestRunnerState.test = __start_tests; } gTestRunnerState.exitCode = 0; gTestRunnerState.skipFilename = NULL; break; - case STATE_NEXT_TEST: - gTestRunnerState.test++; - + case STATE_ASSIGN_TEST: if (gTestRunnerState.test == __stop_tests) { gTestRunnerState.state = STATE_EXIT; @@ -172,6 +171,7 @@ void CB2_TestRunner(void) if (gTestRunnerState.test->runner != &gAssumptionsRunner && !PrefixMatch(gTestRunnerArgv, gTestRunnerState.test->name)) { + gTestRunnerState.state = STATE_NEXT_TEST; return; } @@ -191,6 +191,8 @@ void CB2_TestRunner(void) sCurrentTest.address = (uintptr_t)gTestRunnerState.test; sCurrentTest.state = CURRENT_TEST_STATE_ESTIMATE; + // If AssignCostToRunner fails, we want to report the failure. + gTestRunnerState.state = STATE_REPORT_RESULT; if (AssignCostToRunner() == gTestRunnerI) gTestRunnerState.state = STATE_RUN_TEST; else @@ -204,7 +206,10 @@ void CB2_TestRunner(void) SeedRng(0); SeedRng2(0); if (gTestRunnerState.test->runner->setUp) + { gTestRunnerState.test->runner->setUp(gTestRunnerState.test->data); + gTestRunnerState.tearDown = TRUE; + } // NOTE: Assumes that the compiler interns __FILE__. if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename) // Assumption fails for tests in this file. { @@ -216,13 +221,17 @@ void CB2_TestRunner(void) gTestRunnerState.test->runner->run(gTestRunnerState.test->data); } break; + case STATE_REPORT_RESULT: REG_TM2CNT_H = 0; gTestRunnerState.state = STATE_NEXT_TEST; - if (gTestRunnerState.test->runner->tearDown) + if (gTestRunnerState.tearDown && gTestRunnerState.test->runner->tearDown) + { gTestRunnerState.test->runner->tearDown(gTestRunnerState.test->data); + gTestRunnerState.tearDown = FALSE; + } if (gTestRunnerState.result == TEST_RESULT_PASS && !gTestRunnerState.expectLeaks) @@ -342,6 +351,11 @@ void CB2_TestRunner(void) break; + case STATE_NEXT_TEST: + gTestRunnerState.state = STATE_ASSIGN_TEST; + gTestRunnerState.test++; + break; + case STATE_EXIT: MgbaExit_(gTestRunnerState.exitCode); break; From cd59e055c24dd18e4fe9294ea5e53b723e898d17 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 23 Oct 2023 06:08:36 -0300 Subject: [PATCH 04/15] Made Reflect Type handle 3rd types (#3303) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Made Reflect Type handle 3rd types Misc: -Turned VARIOUS_TRY_REFLECT_TYPE into a callnative (BS_TryReflectType) -Introduced a macro to to check for typeless Pokémon (Pokémon who have Mystery in all 3 type slots) in battle. -Made the new BS_TryReflectType take into account the forms for Arceus and Silvally, rather than just their default form. --- asm/macros/battle_script.inc | 10 +- include/battle.h | 4 + src/battle_script_commands.c | 77 +++++----- test/battle/move_effect/reflect_type.c | 186 +++++++++++++++++++++++++ 4 files changed, 241 insertions(+), 36 deletions(-) create mode 100644 test/battle/move_effect/reflect_type.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 866831c462..c875729b85 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1456,6 +1456,11 @@ .4byte \jumpInstr .endm + .macro tryreflecttype failInstr:req + callnative BS_TryReflectType + .4byte \failInstr + .endm + @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES @@ -1686,11 +1691,6 @@ .4byte \failInstr .endm - .macro tryreflecttype failInstr:req - various BS_ATTACKER, VARIOUS_TRY_REFLECT_TYPE - .4byte \failInstr - .endm - .macro trysoak failInstr:req various BS_ATTACKER, VARIOUS_TRY_SOAK .4byte \failInstr diff --git a/include/battle.h b/include/battle.h index 037259fc5b..95886b7e13 100644 --- a/include/battle.h +++ b/include/battle.h @@ -724,12 +724,16 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER #define BATTLER_DAMAGED(battlerId) ((gSpecialStatuses[battlerId].physicalDmg != 0 || gSpecialStatuses[battlerId].specialDmg != 0)) #define IS_BATTLER_OF_TYPE(battlerId, type)((GetBattlerType(battlerId, 0) == type || GetBattlerType(battlerId, 1) == type || (GetBattlerType(battlerId, 2) != TYPE_MYSTERY && GetBattlerType(battlerId, 2) == type))) + +#define IS_BATTLER_TYPELESS(battlerId)(GetBattlerType(battlerId, 0) == TYPE_MYSTERY && GetBattlerType(battlerId, 1) == TYPE_MYSTERY && GetBattlerType(battlerId, 2) == TYPE_MYSTERY) + #define SET_BATTLER_TYPE(battlerId, type) \ { \ gBattleMons[battlerId].type1 = type; \ gBattleMons[battlerId].type2 = type; \ gBattleMons[battlerId].type3 = TYPE_MYSTERY; \ } + #define RESTORE_BATTLER_TYPE(battlerId) \ { \ gBattleMons[battlerId].type1 = gSpeciesInfo[gBattleMons[battlerId].species].types[0]; \ diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e9b7ba941b..c886178ec0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9409,37 +9409,6 @@ static void Cmd_various(void) } return; } - case VARIOUS_TRY_REFLECT_TYPE: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].species == SPECIES_ARCEUS || gBattleMons[gBattlerTarget].species == SPECIES_SILVALLY) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetBattlerType(gBattlerTarget, 0) == TYPE_MYSTERY && GetBattlerType(gBattlerTarget, 1) != TYPE_MYSTERY) - { - gBattleMons[gBattlerAttacker].type1 = GetBattlerType(gBattlerTarget, 1); - gBattleMons[gBattlerAttacker].type2 = GetBattlerType(gBattlerTarget, 1); - gBattlescriptCurrInstr = cmd->nextInstr; - } - else if (GetBattlerType(gBattlerTarget, 0) != TYPE_MYSTERY && GetBattlerType(gBattlerTarget, 1) == TYPE_MYSTERY) - { - gBattleMons[gBattlerAttacker].type1 = GetBattlerType(gBattlerTarget, 0); - gBattleMons[gBattlerAttacker].type2 = GetBattlerType(gBattlerTarget, 0); - gBattlescriptCurrInstr = cmd->nextInstr; - } - else if (GetBattlerType(gBattlerTarget, 0) == TYPE_MYSTERY && GetBattlerType(gBattlerTarget, 1) == TYPE_MYSTERY) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleMons[gBattlerAttacker].type1 = GetBattlerType(gBattlerTarget, 0); - gBattleMons[gBattlerAttacker].type2 = GetBattlerType(gBattlerTarget, 1); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } case VARIOUS_TRY_SOAK: { VARIOUS_ARGS(const u8 *failInstr); @@ -16331,3 +16300,49 @@ void BS_JumpIfTerrainAffected(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_TryReflectType(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u16 targetBaseSpecies = GET_BASE_SPECIES_ID(gBattleMons[gBattlerTarget].species); + u8 targetType1 = GetBattlerType(gBattlerTarget, 0); + u8 targetType2 = GetBattlerType(gBattlerTarget, 1); + u8 targetType3 = GetBattlerType(gBattlerTarget, 2); + + if (targetBaseSpecies == SPECIES_ARCEUS || targetBaseSpecies == SPECIES_SILVALLY) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (IS_BATTLER_TYPELESS(gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (targetType1 == TYPE_MYSTERY && targetType2 == TYPE_MYSTERY && targetType3 != TYPE_MYSTERY) + { + gBattleMons[gBattlerAttacker].type1 = TYPE_NORMAL; + gBattleMons[gBattlerAttacker].type2 = TYPE_NORMAL; + gBattleMons[gBattlerAttacker].type3 = targetType3; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else if (targetType1 == TYPE_MYSTERY && targetType2 != TYPE_MYSTERY) + { + gBattleMons[gBattlerAttacker].type1 = targetType2; + gBattleMons[gBattlerAttacker].type2 = targetType2; + gBattleMons[gBattlerAttacker].type3 = targetType3; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else if (targetType1 != TYPE_MYSTERY && targetType2 == TYPE_MYSTERY) + { + gBattleMons[gBattlerAttacker].type1 = targetType1; + gBattleMons[gBattlerAttacker].type2 = targetType1; + gBattleMons[gBattlerAttacker].type3 = targetType3; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattleMons[gBattlerAttacker].type1 = targetType1; + gBattleMons[gBattlerAttacker].type2 = targetType2; + gBattleMons[gBattlerAttacker].type3 = targetType3; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} diff --git a/test/battle/move_effect/reflect_type.c b/test/battle/move_effect/reflect_type.c new file mode 100644 index 0000000000..e873516034 --- /dev/null +++ b/test/battle/move_effect/reflect_type.c @@ -0,0 +1,186 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Reflect Type fails if the user is Terastallized"); +TO_DO_BATTLE_TEST("Reflect Type succeeds against a Terastallized target and copies its Tera type"); + +SINGLE_BATTLE_TEST("Reflect Type does not affect any of Arceus' forms") +{ + u32 j; + static const u16 sArceusFormSpeciesIdTable[] = { + SPECIES_ARCEUS, + SPECIES_ARCEUS_FIGHTING, + SPECIES_ARCEUS_FLYING, + SPECIES_ARCEUS_POISON, + SPECIES_ARCEUS_GROUND, + SPECIES_ARCEUS_ROCK, + SPECIES_ARCEUS_BUG, + SPECIES_ARCEUS_GHOST, + SPECIES_ARCEUS_STEEL, + SPECIES_ARCEUS_FIRE, + SPECIES_ARCEUS_WATER, + SPECIES_ARCEUS_GRASS, + SPECIES_ARCEUS_ELECTRIC, + SPECIES_ARCEUS_PSYCHIC, + SPECIES_ARCEUS_ICE, + SPECIES_ARCEUS_DRAGON, + SPECIES_ARCEUS_DARK, + SPECIES_ARCEUS_FAIRY, + }; + u16 species = SPECIES_NONE; + + for (j = 0; j < ARRAY_COUNT(sArceusFormSpeciesIdTable); j++) + { + PARAMETRIZE { species = sArceusFormSpeciesIdTable[j]; } + } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species); + } WHEN { + TURN { MOVE(player, MOVE_REFLECT_TYPE); } + } SCENE { + MESSAGE("Wobbuffet used Reflect Type!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Reflect Type does not affect any of Silvally's forms") +{ + u32 j; + static const u16 sSilvallyFormSpeciesIdTable[] = { + SPECIES_SILVALLY, + SPECIES_SILVALLY_FIGHTING, + SPECIES_SILVALLY_FLYING, + SPECIES_SILVALLY_POISON, + SPECIES_SILVALLY_GROUND, + SPECIES_SILVALLY_ROCK, + SPECIES_SILVALLY_BUG, + SPECIES_SILVALLY_GHOST, + SPECIES_SILVALLY_STEEL, + SPECIES_SILVALLY_FIRE, + SPECIES_SILVALLY_WATER, + SPECIES_SILVALLY_GRASS, + SPECIES_SILVALLY_ELECTRIC, + SPECIES_SILVALLY_PSYCHIC, + SPECIES_SILVALLY_ICE, + SPECIES_SILVALLY_DRAGON, + SPECIES_SILVALLY_DARK, + SPECIES_SILVALLY_FAIRY, + }; + u16 species = SPECIES_NONE; + + for (j = 0; j < ARRAY_COUNT(sSilvallyFormSpeciesIdTable); j++) + { + PARAMETRIZE { species = sSilvallyFormSpeciesIdTable[j]; } + } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species); + } WHEN { + TURN { MOVE(player, MOVE_REFLECT_TYPE); } + } SCENE { + MESSAGE("Wobbuffet used Reflect Type!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Reflect Type does not affect Pokémon with no types") +{ + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_POLIWRATH].types[0] == TYPE_WATER); + ASSUME(gSpeciesInfo[SPECIES_POLIWRATH].types[1] == TYPE_FIGHTING); + GIVEN { + PLAYER(SPECIES_ARCANINE); + OPPONENT(SPECIES_POLIWRATH); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); MOVE(opponent, MOVE_REFLECT_TYPE); } + } SCENE { + MESSAGE("Arcanine used Burn Up!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent); + MESSAGE("Arcanine burned itself out!"); + MESSAGE("Foe Poliwrath used Reflect Type!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Reflect Type copies a target's dual types") +{ + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_POLIWRATH].types[0] == TYPE_WATER); + ASSUME(gSpeciesInfo[SPECIES_POLIWRATH].types[1] == TYPE_FIGHTING); + GIVEN { + PLAYER(SPECIES_ARCANINE); + OPPONENT(SPECIES_POLIWRATH); + } WHEN { + TURN { MOVE(player, MOVE_REFLECT_TYPE); } + } SCENE { + MESSAGE("Arcanine used Reflect Type!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REFLECT_TYPE, player); + MESSAGE("Arcanine's type changed to match the Foe Poliwrath's!"); + } THEN { + EXPECT_EQ(player->type1, TYPE_WATER); + EXPECT_EQ(player->type2, TYPE_FIGHTING); + EXPECT_EQ(player->type3, TYPE_MYSTERY); + } +} + +SINGLE_BATTLE_TEST("Reflect Type copies a target's pure type") +{ + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_SUDOWOODO].types[0] == TYPE_ROCK); + ASSUME(gSpeciesInfo[SPECIES_SUDOWOODO].types[1] == TYPE_ROCK); + GIVEN { + PLAYER(SPECIES_ARCANINE); + OPPONENT(SPECIES_SUDOWOODO); + } WHEN { + TURN { MOVE(player, MOVE_REFLECT_TYPE); } + } SCENE { + MESSAGE("Arcanine used Reflect Type!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REFLECT_TYPE, player); + MESSAGE("Arcanine's type changed to match the Foe Sudowoodo's!"); + } THEN { + EXPECT_EQ(player->type1, TYPE_ROCK); + EXPECT_EQ(player->type2, TYPE_ROCK); + EXPECT_EQ(player->type3, TYPE_MYSTERY); + } +} + +SINGLE_BATTLE_TEST("Reflect Type defaults to Normal type for the user's type1 and type2 if the target only has a 3rd type") +{ + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] == TYPE_PSYCHIC); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[1] == TYPE_PSYCHIC); + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ARCANINE); + } WHEN { + TURN { MOVE(opponent, MOVE_BURN_UP); } + TURN { MOVE(player, MOVE_FORESTS_CURSE); } + TURN { MOVE(player, MOVE_REFLECT_TYPE); } + } SCENE { + // Turn 1 + MESSAGE("Foe Arcanine used Burn Up!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, opponent); + HP_BAR(player); + MESSAGE("Foe Arcanine burned itself out!"); + // Turn 2 + MESSAGE("Wobbuffet used Forest'sCurs!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FORESTS_CURSE, player); + MESSAGE("Grass type was added to Foe Arcanine!"); + // Turn 3 + MESSAGE("Wobbuffet used Reflect Type!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REFLECT_TYPE, player); + MESSAGE("Wobbuffet's type changed to match the Foe Arcanine's!"); + } THEN { + EXPECT_EQ(player->type1, TYPE_NORMAL); + EXPECT_EQ(player->type2, TYPE_NORMAL); + EXPECT_EQ(player->type3, TYPE_GRASS); + } +} From 5fd36a8e390c7b3d72ee470846bc0a91754425bd Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 23 Oct 2023 13:37:40 +0100 Subject: [PATCH 05/15] Fix ModifyPersonalityForNature (#3452) --- src/battle_main.c | 2 +- test/battle/trainer_control.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/battle_main.c b/src/battle_main.c index 037d9a857f..514b69fd68 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -1896,7 +1896,7 @@ static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i) void ModifyPersonalityForNature(u32 *personality, u32 newNature) { u32 nature = GetNatureFromPersonality(*personality); - s32 diff = abs(nature - newNature); + s32 diff = abs((s32)nature - (s32)newNature); s32 sign = (nature > newNature) ? 1 : -1; if (diff > NUM_NATURES / 2) { diff --git a/test/battle/trainer_control.c b/test/battle/trainer_control.c index a0e94dbbec..99bea0e8cc 100644 --- a/test/battle/trainer_control.c +++ b/test/battle/trainer_control.c @@ -4,6 +4,7 @@ #include "battle_main.h" #include "data.h" #include "malloc.h" +#include "random.h" #include "string_util.h" #include "constants/item.h" #include "constants/abilities.h" @@ -119,3 +120,17 @@ TEST("CreateNPCTrainerPartyForTrainer generates different personalities for diff EXPECT(testParty[0].box.personality != testParty[1].box.personality); Free(testParty); } + +TEST("ModifyPersonalityForNature can set any nature") +{ + u32 personality, nature, j, k; + for (j = 0; j < 64; j++) + { + for (k = 0; k < NUM_NATURES; k++) + { + PARAMETRIZE { personality = Random32(); nature = k; } + } + } + ModifyPersonalityForNature(&personality, nature); + EXPECT_EQ(GetNatureFromPersonality(personality), nature); +} From 5592706a71170cb8064de999ff5f82ba0b0b6f47 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Mon, 23 Oct 2023 17:59:07 +0200 Subject: [PATCH 06/15] Fix Synchronize devnote + Gen9 behaviour --- include/config/battle.h | 2 +- src/wild_encounter.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/config/battle.h b/include/config/battle.h index aee79daee5..5ce2e4f9f8 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -115,7 +115,7 @@ #define B_SHADOW_TAG_ESCAPE GEN_LATEST // In Gen4+, if both sides have a Pokémon with Shadow Tag, all battlers can escape. Before, neither side could escape this situation. #define B_MOODY_ACC_EVASION GEN_LATEST // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore. #define B_FLASH_FIRE_FROZEN GEN_LATEST // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. -#define B_SYNCHRONIZE_NATURE GEN_LATEST // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. +#define B_SYNCHRONIZE_NATURE GEN_LATEST // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same Nature, as opposed to 50% previously. In Gen9, it has no out-of-battle effect. #define B_SYNCHRONIZE_TOXIC GEN_LATEST // In Gen5+, if a Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned. #define B_UPDATED_INTIMIDATE GEN_LATEST // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. It also activates Rattled. #define B_OBLIVIOUS_TAUNT GEN_LATEST // In Gen6+, Pokémon with Oblivious can't be taunted. diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 6016e08e69..5ea88f4c4a 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -415,6 +415,7 @@ static u8 PickWildMonNature(void) } } } +#if B_SYNCHRONIZE_NATURE < GEN_9 // check synchronize for a pokemon with the same ability if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG) && GetMonAbility(&gPlayerParty[0]) == ABILITY_SYNCHRONIZE @@ -425,6 +426,7 @@ static u8 PickWildMonNature(void) { return GetMonData(&gPlayerParty[0], MON_DATA_PERSONALITY) % NUM_NATURES; } +#endif // random nature return Random() % NUM_NATURES; From bac135c6e8a82601c2add44918310454f49bbc10 Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:03:31 -0400 Subject: [PATCH 07/15] Gave Razor Fang EVO_HELD_ITEM type/fieldUseFunc properties (#3456) --- src/data/items.h | 4 ++-- src/data/pokemon/item_effects.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/data/items.h b/src/data/items.h index 6990e7cded..ec7e22a608 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -6045,8 +6045,8 @@ const struct Item gItems[] = .holdEffectParam = 10, .description = sRazorFangDesc, .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .type = EVO_HELD_ITEM_TYPE, + .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .flingPower = 30, }, diff --git a/src/data/pokemon/item_effects.h b/src/data/pokemon/item_effects.h index d7482d5043..dc2e4f755d 100644 --- a/src/data/pokemon/item_effects.h +++ b/src/data/pokemon/item_effects.h @@ -566,6 +566,7 @@ const u8 *const gItemEffectTable[ITEMS_COUNT] = [ITEM_METAL_COAT] = gItemEffect_EvoItem, [ITEM_KINGS_ROCK] = gItemEffect_EvoItem, [ITEM_RAZOR_CLAW] = gItemEffect_EvoItem, + [ITEM_RAZOR_FANG] = gItemEffect_EvoItem, [ITEM_AUSPICIOUS_ARMOR] = gItemEffect_EvoItem, [ITEM_MALICIOUS_ARMOR] = gItemEffect_EvoItem, [ITEM_SCROLL_OF_DARKNESS] = gItemEffect_EvoItem, From 1110d0aeb9d52be1bc1a3735307d8b11994242f6 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 23 Oct 2023 21:12:17 +0100 Subject: [PATCH 08/15] ROM space on debug menu (#3453) --- data/scripts/debug.inc | 19 +++++++++++-- ld_script.txt | 2 ++ ld_script_modern.txt | 2 ++ ld_script_test.txt | 2 ++ src/debug.c | 64 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index b29291a7f9..7385101c1e 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -104,13 +104,26 @@ Debug_CheckSaveBlock:: end Debug_SaveBlock1Size:: - .string "SaveBlock1 size: {STR_VAR_1}/{STR_VAR_2}.$" + .string "SaveBlock1 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" Debug_SaveBlock2Size:: - .string "SaveBlock2 size: {STR_VAR_1}/{STR_VAR_2}.$" + .string "SaveBlock2 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" Debug_PokemonStorageSize:: - .string "{PKMN}Storage size: {STR_VAR_1}/{STR_VAR_2}.$" + .string "{PKMN}Storage size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" + +Debug_CheckROMSpace:: + callnative CheckROMSize + msgbox Debug_ROMSize, MSGBOX_DEFAULT + release + end + +Debug_ROMSize:: + .string "ROM size: {STR_VAR_1}MB/32MB.\n" + .string "Free space: {STR_VAR_2}MB.$" Debug_HatchAnEgg:: lockall diff --git a/ld_script.txt b/ld_script.txt index a68d1a2a2c..27b340f490 100644 --- a/ld_script.txt +++ b/ld_script.txt @@ -1325,6 +1325,8 @@ SECTIONS { data/*.o(.rodata); } = 0 + __rom_end = .; + /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ diff --git a/ld_script_modern.txt b/ld_script_modern.txt index 082d694291..ab68976661 100644 --- a/ld_script_modern.txt +++ b/ld_script_modern.txt @@ -130,6 +130,8 @@ SECTIONS { src/graphics.o(.rodata); } =0 + __rom_end = .; + /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ diff --git a/ld_script_test.txt b/ld_script_test.txt index f4abad98ab..c7e19d7189 100644 --- a/ld_script_test.txt +++ b/ld_script_test.txt @@ -114,6 +114,8 @@ SECTIONS { test/*.o(.rodata*); } =0 + __rom_end = .; + /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ diff --git a/src/debug.c b/src/debug.c index 8279033bf4..3d8d6f33bc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -83,6 +83,7 @@ enum { // Util DEBUG_UTIL_MENU_ITEM_WARP, DEBUG_UTIL_MENU_ITEM_POISON_MONS, DEBUG_UTIL_MENU_ITEM_SAVEBLOCK, + DEBUG_UTIL_MENU_ITEM_ROM_SPACE, DEBUG_UTIL_MENU_ITEM_WEATHER, DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK, DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK, @@ -303,6 +304,7 @@ static void DebugAction_Util_Warp_SelectWarp(u8 taskId); static void DebugAction_FlagsVars_RunningShoes(u8 taskId); static void DebugAction_Util_PoisonMons(u8 taskId); static void DebugAction_Util_CheckSaveBlock(u8 taskId); +static void DebugAction_Util_CheckROMSpace(u8 taskId); static void DebugAction_Util_Weather(u8 taskId); static void DebugAction_Util_Weather_SelectId(u8 taskId); static void DebugAction_Util_CheckWallClock(u8 taskId); @@ -390,6 +392,7 @@ extern const u8 Debug_HatchAnEgg[]; extern const u8 PlayersHouse_2F_EventScript_SetWallClock[]; extern const u8 PlayersHouse_2F_EventScript_CheckWallClock[]; extern const u8 Debug_CheckSaveBlock[]; +extern const u8 Debug_CheckROMSpace[]; extern const u8 Debug_BoxFilledMessage[]; #include "data/map_group_count.h" @@ -432,6 +435,7 @@ static const u8 sDebugText_Util_WarpToMap_SelectWarp[] = _("Warp:{CLEAR_TO 90 static const u8 sDebugText_Util_WarpToMap_SelMax[] = _("{STR_VAR_1} / {STR_VAR_2}"); static const u8 sDebugText_Util_PoisonMons[] = _("Poison all mons"); static const u8 sDebugText_Util_SaveBlockSpace[] = _("SaveBlock Space…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_ROMSpace[] = _("ROM Space…{CLEAR_TO 110}{RIGHT_ARROW}"); static const u8 sDebugText_Util_Weather[] = _("Set weather…{CLEAR_TO 110}{RIGHT_ARROW}"); static const u8 sDebugText_Util_Weather_ID[] = _("Weather Id: {STR_VAR_3}\n{STR_VAR_1}\n{STR_VAR_2}"); static const u8 sDebugText_Util_CheckWallClock[] = _("Check Wall Clock…{CLEAR_TO 110}{RIGHT_ARROW}"); @@ -595,6 +599,7 @@ static const struct ListMenuItem sDebugMenu_Items_Utilities[] = [DEBUG_UTIL_MENU_ITEM_WARP] = {sDebugText_Util_WarpToMap, DEBUG_UTIL_MENU_ITEM_WARP}, [DEBUG_UTIL_MENU_ITEM_POISON_MONS] = {sDebugText_Util_PoisonMons, DEBUG_UTIL_MENU_ITEM_POISON_MONS}, [DEBUG_UTIL_MENU_ITEM_SAVEBLOCK] = {sDebugText_Util_SaveBlockSpace, DEBUG_UTIL_MENU_ITEM_SAVEBLOCK}, + [DEBUG_UTIL_MENU_ITEM_ROM_SPACE] = {sDebugText_Util_ROMSpace, DEBUG_UTIL_MENU_ITEM_ROM_SPACE}, [DEBUG_UTIL_MENU_ITEM_WEATHER] = {sDebugText_Util_Weather, DEBUG_UTIL_MENU_ITEM_WEATHER}, [DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK] = {sDebugText_Util_CheckWallClock, DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK}, [DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK] = {sDebugText_Util_SetWallClock, DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK}, @@ -728,6 +733,7 @@ static void (*const sDebugMenu_Actions_Utilities[])(u8) = [DEBUG_UTIL_MENU_ITEM_WARP] = DebugAction_Util_Warp_Warp, [DEBUG_UTIL_MENU_ITEM_POISON_MONS] = DebugAction_Util_PoisonMons, [DEBUG_UTIL_MENU_ITEM_SAVEBLOCK] = DebugAction_Util_CheckSaveBlock, + [DEBUG_UTIL_MENU_ITEM_ROM_SPACE] = DebugAction_Util_CheckROMSpace, [DEBUG_UTIL_MENU_ITEM_WEATHER] = DebugAction_Util_Weather, [DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK] = DebugAction_Util_CheckWallClock, [DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK] = DebugAction_Util_SetWallClock, @@ -1800,6 +1806,7 @@ void CheckSaveBlock1Size(struct ScriptContext *ctx) u32 maxSb1Size = SECTOR_DATA_SIZE * (SECTOR_ID_SAVEBLOCK1_END - SECTOR_ID_SAVEBLOCK1_START + 1); ConvertIntToDecimalStringN(gStringVar1, currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar2, maxSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxSb1Size - currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); } void CheckSaveBlock2Size(struct ScriptContext *ctx) @@ -1808,6 +1815,7 @@ void CheckSaveBlock2Size(struct ScriptContext *ctx) u32 maxSb2Size = SECTOR_DATA_SIZE; ConvertIntToDecimalStringN(gStringVar1, currSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar2, maxSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxSb2Size - currSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); } void CheckPokemonStorageSize(struct ScriptContext *ctx) @@ -1816,6 +1824,7 @@ void CheckPokemonStorageSize(struct ScriptContext *ctx) u32 maxPkmnStorageSize = SECTOR_DATA_SIZE * (SECTOR_ID_PKMN_STORAGE_END - SECTOR_ID_PKMN_STORAGE_START + 1); ConvertIntToDecimalStringN(gStringVar1, currPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar2, maxPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxPkmnStorageSize - currPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); } static void DebugAction_Util_CheckSaveBlock(u8 taskId) @@ -1825,6 +1834,61 @@ static void DebugAction_Util_CheckSaveBlock(u8 taskId) ScriptContext_SetupScript(Debug_CheckSaveBlock); } +enum RoundMode +{ + ROUND_CEILING, + ROUND_NEAREST, + ROUND_FLOOR, +}; + +static u8 *ConvertQ22_10ToDecimalString(u8 *string, u32 q22_10, u32 decimalDigits, enum RoundMode roundMode) +{ + string = ConvertIntToDecimalStringN(string, q22_10 >> 10, STR_CONV_MODE_LEFT_ALIGN, 10); + + if (decimalDigits == 0) + return string; + + *string++ = CHAR_PERIOD; + + q22_10 &= (1 << 10) - 1; + while (decimalDigits-- > 1) + { + q22_10 *= 10; + *string++ = CHAR_0 + (q22_10 >> 10); + q22_10 &= (1 << 10) - 1; + } + + q22_10 *= 10; + switch (roundMode) + { + case ROUND_CEILING: q22_10 += (1 << 10) - 1; break; + case ROUND_NEAREST: q22_10 += 1 << (10 - 1); break; + case ROUND_FLOOR: break; + } + *string++ = CHAR_0 + (q22_10 >> 10); + + *string++ = EOS; + + return string; +} + +void CheckROMSize(struct ScriptContext *ctx) +{ + extern u8 __rom_end[]; + u32 currROMSizeB = __rom_end - (const u8 *)ROM_START; + u32 currROMSizeKB = (currROMSizeB + 1023) / 1024; + u32 currROMFreeKB = ((const u8 *)ROM_END - __rom_end) / 1024; + ConvertQ22_10ToDecimalString(gStringVar1, currROMSizeKB, 2, ROUND_CEILING); + ConvertQ22_10ToDecimalString(gStringVar2, currROMFreeKB, 2, ROUND_FLOOR); +} + +static void DebugAction_Util_CheckROMSpace(u8 taskId) +{ + Debug_DestroyMenu_Full(taskId); + LockPlayerFieldControls(); + ScriptContext_SetupScript(Debug_CheckROMSpace); +} + static const u8 sWeatherNames[22][24] = { [WEATHER_NONE] = _("NONE"), [WEATHER_SUNNY_CLOUDS] = _("SUNNY CLOUDS"), From 4488f983be2581cd1e4182551211a3addb508ad4 Mon Sep 17 00:00:00 2001 From: sbird Date: Tue, 24 Oct 2023 01:00:40 +0200 Subject: [PATCH 09/15] fix -Wmaybe-uninitialized for ModifyPersonalityForNature test --- test/battle/trainer_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/battle/trainer_control.c b/test/battle/trainer_control.c index 99bea0e8cc..810a721fa5 100644 --- a/test/battle/trainer_control.c +++ b/test/battle/trainer_control.c @@ -123,7 +123,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates different personalities for diff TEST("ModifyPersonalityForNature can set any nature") { - u32 personality, nature, j, k; + u32 personality = 0, nature = 0, j = 0, k = 0; for (j = 0; j < 64; j++) { for (k = 0; k < NUM_NATURES; k++) From 5fe564f0146caeae619b9aa27c042464b374aba8 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Tue, 24 Oct 2023 08:55:32 +0100 Subject: [PATCH 10/15] Detect 'NOT x; NOT y;' (#3459) Fix Purifying Salt to be immune to statuses from secondary effects. --- src/battle_util.c | 6 ++ test/battle/ability/cute_charm.c | 10 ++-- test/battle/ability/flame_body.c | 10 ++-- test/battle/ability/leaf_guard.c | 13 +++-- test/battle/ability/limber.c | 6 +- test/battle/ability/poison_point.c | 10 ++-- test/battle/ability/purifying_salt.c | 7 ++- test/battle/ability/sap_sipper.c | 12 ++-- test/battle/ability/static.c | 10 ++-- test/battle/ability/toxic_debris.c | 21 ++++--- test/battle/ability/wind_power.c | 6 +- test/battle/hold_effect/attack_up.c | 13 ++--- test/battle/hold_effect/critical_hit_up.c | 9 +-- test/battle/hold_effect/defense_up.c | 13 ++--- test/battle/hold_effect/kee_berry.c | 6 +- test/battle/hold_effect/micle_berry.c | 15 ++--- test/battle/hold_effect/rowap_berry.c | 6 +- test/battle/hold_effect/special_attack_up.c | 13 ++--- test/battle/hold_effect/special_defense_up.c | 13 ++--- test/battle/hold_effect/speed_up.c | 13 ++--- test/battle/move_effect/absorb.c | 8 ++- test/battle/move_effect/burn_hit.c | 6 +- test/battle/move_effect/dire_claw.c | 55 +++++++++--------- test/battle/move_effect/dream_eater.c | 8 ++- test/battle/move_effect/freeze_hit.c | 8 ++- test/battle/move_effect/paralyze_hit.c | 6 +- test/battle/move_effect/poison_hit.c | 6 +- test/battle/move_effect/protect.c | 33 +++++++---- test/battle/move_effect/roost.c | 42 +++++++++----- test/battle/move_effect/teatime.c | 8 ++- test/battle/move_effect/toxic.c | 8 ++- test/battle/move_effect/tri_attack.c | 60 ++++++++++---------- test/test_runner_battle.c | 14 ++++- 33 files changed, 276 insertions(+), 198 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 3486b6a3b3..d64acb6fb5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6315,6 +6315,7 @@ bool32 CanSleep(u32 battler) if (ability == ABILITY_INSOMNIA || ability == ABILITY_VITAL_SPIRIT || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityOnSide(battler, ABILITY_SWEET_VEIL) @@ -6333,6 +6334,7 @@ bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget) || gBattleMons[battlerTarget].status1 & STATUS1_ANY || ability == ABILITY_IMMUNITY || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT || IsAbilityOnSide(battlerTarget, ABILITY_PASTEL_VEIL) || IsAbilityStatusProtected(battlerTarget) || IsBattlerTerrainAffected(battlerTarget, STATUS_FIELD_MISTY_TERRAIN)) @@ -6350,6 +6352,7 @@ bool32 CanBeBurned(u32 battler) || ability == ABILITY_WATER_BUBBLE || ability == ABILITY_COMATOSE || ability == ABILITY_THERMAL_EXCHANGE + || ability == ABILITY_PURIFYING_SALT || IsAbilityStatusProtected(battler) || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) return FALSE; @@ -6366,6 +6369,7 @@ bool32 CanBeParalyzed(u32 battler) gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || ability == ABILITY_LIMBER || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler) || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) @@ -6381,6 +6385,7 @@ bool32 CanBeFrozen(u32 battler) || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || ability == ABILITY_MAGMA_ARMOR || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler) || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) @@ -6395,6 +6400,7 @@ bool32 CanGetFrostbite(u32 battler) || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || ability == ABILITY_MAGMA_ARMOR || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler) || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) diff --git a/test/battle/ability/cute_charm.c b/test/battle/ability/cute_charm.c index 9bef66b19a..54ca0c2907 100644 --- a/test/battle/ability/cute_charm.c +++ b/test/battle/ability/cute_charm.c @@ -21,10 +21,12 @@ SINGLE_BATTLE_TEST("Cute Charm inflicts infatuation on contact") MESSAGE("Foe Clefairy's Cute Charm infatuated Wobbuffet!"); MESSAGE("Wobbuffet is in love with Foe Clefairy!"); } else { - NOT ABILITY_POPUP(opponent, ABILITY_CUTE_CHARM); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_INFATUATION, player); - NOT MESSAGE("Foe Clefairy's Cute Charm infatuated Wobbuffet!"); - NOT MESSAGE("Wobbuffet is in love with Foe Clefairy!"); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_CUTE_CHARM); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_INFATUATION, player); + MESSAGE("Foe Clefairy's Cute Charm infatuated Wobbuffet!"); + MESSAGE("Wobbuffet is in love with Foe Clefairy!"); + } } } } diff --git a/test/battle/ability/flame_body.c b/test/battle/ability/flame_body.c index 959b583f80..b275c20e1c 100644 --- a/test/battle/ability/flame_body.c +++ b/test/battle/ability/flame_body.c @@ -20,10 +20,12 @@ SINGLE_BATTLE_TEST("Flame Body inflicts burn on contact") MESSAGE("Foe Magmar's Flame Body burned Wobbuffet!"); STATUS_ICON(player, burn: TRUE); } else { - NOT ABILITY_POPUP(opponent, ABILITY_FLAME_BODY); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, player); - NOT MESSAGE("Foe Magmar's Flame Body burned Wobbuffet!"); - NOT STATUS_ICON(player, burn: TRUE); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_FLAME_BODY); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, player); + MESSAGE("Foe Magmar's Flame Body burned Wobbuffet!"); + STATUS_ICON(player, burn: TRUE); + } } } } diff --git a/test/battle/ability/leaf_guard.c b/test/battle/ability/leaf_guard.c index 66eb6fc186..595a9451c3 100644 --- a/test/battle/ability/leaf_guard.c +++ b/test/battle/ability/leaf_guard.c @@ -25,10 +25,13 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent); ABILITY_POPUP(player, ABILITY_LEAF_GUARD); MESSAGE("It doesn't affect Leafeon…"); + NOT STATUS_ICON(player, status); } else { - NOT ABILITY_POPUP(player, ABILITY_LEAF_GUARD); + NONE_OF { + ABILITY_POPUP(player, ABILITY_LEAF_GUARD); + STATUS_ICON(player, status); + } } - NOT STATUS_ICON(player, status); } } @@ -65,7 +68,9 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun") TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_REST); } } SCENE { MESSAGE("But it failed!"); - NOT STATUS_ICON(player, sleep: TRUE); - NONE_OF { HP_BAR(player); } + NONE_OF { + STATUS_ICON(player, sleep: TRUE); + HP_BAR(player); + } } } diff --git a/test/battle/ability/limber.c b/test/battle/ability/limber.c index 87d4177ffd..9ba2760c87 100644 --- a/test/battle/ability/limber.c +++ b/test/battle/ability/limber.c @@ -10,7 +10,9 @@ SINGLE_BATTLE_TEST("Limber prevents paralysis") TURN { MOVE(opponent, MOVE_THUNDER_SHOCK); } } SCENE { HP_BAR(player); - NONE_OF { ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, player); } - NONE_OF { STATUS_ICON(player, paralysis: TRUE); } + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, player); + STATUS_ICON(player, paralysis: TRUE); + } } } diff --git a/test/battle/ability/poison_point.c b/test/battle/ability/poison_point.c index 7d2fcd518b..0df1255081 100644 --- a/test/battle/ability/poison_point.c +++ b/test/battle/ability/poison_point.c @@ -21,10 +21,12 @@ SINGLE_BATTLE_TEST("Poison Point inflicts poison on contact") MESSAGE("Wobbuffet was poisoned by Foe Nidoran♂'s Poison Point!"); STATUS_ICON(player, poison: TRUE); } else { - NOT ABILITY_POPUP(opponent, ABILITY_POISON_POINT); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player); - NOT MESSAGE("Wobbuffet was poisoned by Foe Nidoran♂'s Poison Point!"); - NOT STATUS_ICON(player, poison: TRUE); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_POISON_POINT); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player); + MESSAGE("Wobbuffet was poisoned by Foe Nidoran♂'s Poison Point!"); + STATUS_ICON(player, poison: TRUE); + } } } } diff --git a/test/battle/ability/purifying_salt.c b/test/battle/ability/purifying_salt.c index 0a53dbc61b..ea89124681 100644 --- a/test/battle/ability/purifying_salt.c +++ b/test/battle/ability/purifying_salt.c @@ -57,9 +57,12 @@ SINGLE_BATTLE_TEST("Purifying Salt grants immunity to status effects") NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent); ABILITY_POPUP(player, ABILITY_PURIFYING_SALT); MESSAGE("It doesn't affect Wobbuffet…"); + NOT STATUS_ICON(player, status); } else { - NOT ABILITY_POPUP(player, ABILITY_PURIFYING_SALT); + NONE_OF { + ABILITY_POPUP(player, ABILITY_PURIFYING_SALT); + STATUS_ICON(player, status); + } } - NOT STATUS_ICON(player, status); } } diff --git a/test/battle/ability/sap_sipper.c b/test/battle/ability/sap_sipper.c index 89ec422491..918e553a3a 100644 --- a/test/battle/ability/sap_sipper.c +++ b/test/battle/ability/sap_sipper.c @@ -21,8 +21,10 @@ SINGLE_BATTLE_TEST("Sap Sipper negates effects from Grass-type moves") } WHEN { TURN { MOVE(opponent, MOVE_SPORE); } } SCENE { - NONE_OF { ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); } - NONE_OF { STATUS_ICON(player, sleep: TRUE); } + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + STATUS_ICON(player, sleep: TRUE); + } } } @@ -49,7 +51,9 @@ SINGLE_BATTLE_TEST("Sap Sipper does not increase Attack if already maxed") TURN { MOVE(player, MOVE_BELLY_DRUM); MOVE(opponent, MOVE_VINE_WHIP); } } SCENE { ABILITY_POPUP(player, ABILITY_SAP_SIPPER); - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } - NONE_OF { MESSAGE("Marill's Attack rose!"); } + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Marill's Attack rose!"); + } } } diff --git a/test/battle/ability/static.c b/test/battle/ability/static.c index e0d91aa0d5..51224da944 100644 --- a/test/battle/ability/static.c +++ b/test/battle/ability/static.c @@ -20,10 +20,12 @@ SINGLE_BATTLE_TEST("Static inflicts paralysis on contact") MESSAGE("Foe Pikachu's Static paralyzed Wobbuffet! It may be unable to move!"); STATUS_ICON(player, paralysis: TRUE); } else { - NOT ABILITY_POPUP(opponent, ABILITY_STATIC); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, player); - NOT MESSAGE("Foe Pikachu's Static paralyzed Wobbuffet! It may be unable to move!"); - NOT STATUS_ICON(player, paralysis: TRUE); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_STATIC); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, player); + MESSAGE("Foe Pikachu's Static paralyzed Wobbuffet! It may be unable to move!"); + STATUS_ICON(player, paralysis: TRUE); + } } } } diff --git a/test/battle/ability/toxic_debris.c b/test/battle/ability/toxic_debris.c index f3e23e5abb..fadde2ceb5 100644 --- a/test/battle/ability/toxic_debris.c +++ b/test/battle/ability/toxic_debris.c @@ -17,10 +17,11 @@ SINGLE_BATTLE_TEST("Toxic Debris sets Toxic Spikes on the opposing side if hit b if (move == MOVE_TACKLE) { ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); - } - else { - NOT ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); - NOT MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } else { + NONE_OF { + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } } } } @@ -42,8 +43,10 @@ SINGLE_BATTLE_TEST("Toxic Debris does not activate if two layers of Toxic Spikes ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); - NOT ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); - NOT MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + NONE_OF { + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } } } @@ -58,8 +61,10 @@ SINGLE_BATTLE_TEST("If a Substitute is hit, Toxic Debris does not set Toxic Spik } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); - NOT ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); - NOT MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + NONE_OF { + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } } } diff --git a/test/battle/ability/wind_power.c b/test/battle/ability/wind_power.c index 4616a69fb7..98934a93d1 100644 --- a/test/battle/ability/wind_power.c +++ b/test/battle/ability/wind_power.c @@ -133,8 +133,10 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab ABILITY_POPUP(playerRight, ABILITY_WIND_POWER); MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!"); } - NOT HP_BAR(opponentLeft); - NOT HP_BAR(opponentRight); + NONE_OF { + HP_BAR(opponentLeft); + HP_BAR(opponentRight); + } } THEN { EXPECT_NE(playerLeft->hp, playerLeft->maxHP); diff --git a/test/battle/hold_effect/attack_up.c b/test/battle/hold_effect/attack_up.c index 2a6dd7c2df..0602d651d7 100644 --- a/test/battle/hold_effect/attack_up.c +++ b/test/battle/hold_effect/attack_up.c @@ -21,13 +21,12 @@ SINGLE_BATTLE_TEST("Liechi Berry raises the holder's Attack by one stage when HP TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_TACKLE) - { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Using Liechi Berry, the Attack of Wobbuffet rose!"); - } - else - { + if (move == MOVE_TACKLE) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Liechi Berry, the Attack of Wobbuffet rose!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Using Liechi Berry, the Attack of Wobbuffet rose!"); } diff --git a/test/battle/hold_effect/critical_hit_up.c b/test/battle/hold_effect/critical_hit_up.c index fc8e5acec5..c0cc2e864f 100644 --- a/test/battle/hold_effect/critical_hit_up.c +++ b/test/battle/hold_effect/critical_hit_up.c @@ -22,10 +22,11 @@ SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two s } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); if (move == MOVE_TACKLE) { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Wobbuffet used Lansat Berry to get pumped!"); - } - else { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet used Lansat Berry to get pumped!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Wobbuffet used Lansat Berry to get pumped!"); } diff --git a/test/battle/hold_effect/defense_up.c b/test/battle/hold_effect/defense_up.c index 4326f156dc..774cd3b981 100644 --- a/test/battle/hold_effect/defense_up.c +++ b/test/battle/hold_effect/defense_up.c @@ -21,13 +21,12 @@ SINGLE_BATTLE_TEST("Ganlon Berry raises the holder's Defense by one stage when H TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_TACKLE) - { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Using Ganlon Berry, the Defense of Wobbuffet rose!"); - } - else - { + if (move == MOVE_TACKLE) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Ganlon Berry, the Defense of Wobbuffet rose!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Using Ganlon Berry, the Defense of Wobbuffet rose!"); } diff --git a/test/battle/hold_effect/kee_berry.c b/test/battle/hold_effect/kee_berry.c index cfb6b14e5c..6e5319416f 100644 --- a/test/battle/hold_effect/kee_berry.c +++ b/test/battle/hold_effect/kee_berry.c @@ -67,7 +67,9 @@ SINGLE_BATTLE_TEST("Kee Berry is not triggered by a special move") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); - NOT MESSAGE("Using Kee Berry, the Defense of Foe Wobbuffet rose!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Using Kee Berry, the Defense of Foe Wobbuffet rose!"); + } } } diff --git a/test/battle/hold_effect/micle_berry.c b/test/battle/hold_effect/micle_berry.c index 224c2fecf6..79c40f68cc 100644 --- a/test/battle/hold_effect/micle_berry.c +++ b/test/battle/hold_effect/micle_berry.c @@ -21,13 +21,12 @@ SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2 when HP drop TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_TACKLE) - { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Wobbuffet boosted the accuracy of its next move using Micle Berry!"); - } - else - { + if (move == MOVE_TACKLE) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet boosted the accuracy of its next move using Micle Berry!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Wobbuffet boosted the accuracy of its next move using Micle Berry!"); } @@ -64,5 +63,3 @@ SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2") ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBMISSION, player); } } - - diff --git a/test/battle/hold_effect/rowap_berry.c b/test/battle/hold_effect/rowap_berry.c index 3df8d004f4..d019a0f77b 100644 --- a/test/battle/hold_effect/rowap_berry.c +++ b/test/battle/hold_effect/rowap_berry.c @@ -51,7 +51,9 @@ SINGLE_BATTLE_TEST("Rowap Berry is not triggered by a physical move") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); - NOT MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Rowap Berry!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Rowap Berry!"); + } } } diff --git a/test/battle/hold_effect/special_attack_up.c b/test/battle/hold_effect/special_attack_up.c index 1059960abc..9815ab1212 100644 --- a/test/battle/hold_effect/special_attack_up.c +++ b/test/battle/hold_effect/special_attack_up.c @@ -21,13 +21,12 @@ SINGLE_BATTLE_TEST("Petaya Berry raises the holder's Sp. Atk by one stage when H TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_TACKLE) - { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Using Petaya Berry, the Sp. Atk of Wobbuffet rose!"); - } - else - { + if (move == MOVE_TACKLE) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Petaya Berry, the Sp. Atk of Wobbuffet rose!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Using Petaya Berry, the Sp. Atk of Wobbuffet rose!"); } diff --git a/test/battle/hold_effect/special_defense_up.c b/test/battle/hold_effect/special_defense_up.c index 9a6c8c44be..2ba3c02a57 100644 --- a/test/battle/hold_effect/special_defense_up.c +++ b/test/battle/hold_effect/special_defense_up.c @@ -21,13 +21,12 @@ SINGLE_BATTLE_TEST("Apicot Berry raises the holder's Sp. Def by one stage when H TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_TACKLE) - { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Using Apicot Berry, the Sp. Def of Wobbuffet rose!"); - } - else - { + if (move == MOVE_TACKLE) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Apicot Berry, the Sp. Def of Wobbuffet rose!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Using Apicot Berry, the Sp. Def of Wobbuffet rose!"); } diff --git a/test/battle/hold_effect/speed_up.c b/test/battle/hold_effect/speed_up.c index 62ca65dbc2..558d4262e8 100644 --- a/test/battle/hold_effect/speed_up.c +++ b/test/battle/hold_effect/speed_up.c @@ -21,13 +21,12 @@ SINGLE_BATTLE_TEST("Salac Berry raises the holder's Speed by one stage when HP d TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_TACKLE) - { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); - NOT MESSAGE("Using Salac Berry, the Speed of Wobbuffet rose!"); - } - else - { + if (move == MOVE_TACKLE) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Salac Berry, the Speed of Wobbuffet rose!"); + } + } else { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Using Salac Berry, the Speed of Wobbuffet rose!"); } diff --git a/test/battle/move_effect/absorb.c b/test/battle/move_effect/absorb.c index d46dbd9c5c..5d164de40d 100644 --- a/test/battle/move_effect/absorb.c +++ b/test/battle/move_effect/absorb.c @@ -34,8 +34,10 @@ SINGLE_BATTLE_TEST("Absorb fails if Heal Block applies") TURN { MOVE(opponent, MOVE_HEAL_BLOCK); MOVE(player, MOVE_ABSORB); } } SCENE { MESSAGE("Wobbuffet was prevented from healing!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player); - NOT HP_BAR(opponent); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player); + HP_BAR(opponent); + HP_BAR(player); + } } } diff --git a/test/battle/move_effect/burn_hit.c b/test/battle/move_effect/burn_hit.c index 762780009c..627a051a53 100644 --- a/test/battle/move_effect/burn_hit.c +++ b/test/battle/move_effect/burn_hit.c @@ -32,7 +32,9 @@ SINGLE_BATTLE_TEST("Ember cannot burn a Fire-type Pokémon") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent); - NOT STATUS_ICON(opponent, burn: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent); + STATUS_ICON(opponent, burn: TRUE); + } } } diff --git a/test/battle/move_effect/dire_claw.c b/test/battle/move_effect/dire_claw.c index 421ba201d0..9149f4a3cc 100644 --- a/test/battle/move_effect/dire_claw.c +++ b/test/battle/move_effect/dire_claw.c @@ -25,11 +25,9 @@ SINGLE_BATTLE_TEST("Dire Claw can inflict poison, paralysis or sleep") ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); if (statusAnim == B_ANIM_STATUS_PRZ) { STATUS_ICON(opponent, paralysis: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_SLP) { + } else if (statusAnim == B_ANIM_STATUS_SLP) { STATUS_ICON(opponent, sleep: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PSN) { + } else if (statusAnim == B_ANIM_STATUS_PSN) { STATUS_ICON(opponent, poison: TRUE); } } @@ -53,12 +51,13 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respe } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); - if (statusAnim == B_ANIM_STATUS_PRZ) { - NOT STATUS_ICON(opponent, paralysis: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PSN) { - NOT STATUS_ICON(opponent, poison: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); + if (statusAnim == B_ANIM_STATUS_PRZ) { + STATUS_ICON(opponent, paralysis: TRUE); + } else if (statusAnim == B_ANIM_STATUS_PSN) { + STATUS_ICON(opponent, poison: TRUE); + } } } } @@ -86,15 +85,15 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep pokemo } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); - if (statusAnim == B_ANIM_STATUS_PRZ) { - NOT STATUS_ICON(opponent, paralysis: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_SLP) { - NOT STATUS_ICON(opponent, sleep: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PSN) { - NOT STATUS_ICON(opponent, poison: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); + if (statusAnim == B_ANIM_STATUS_PRZ) { + STATUS_ICON(opponent, paralysis: TRUE); + } else if (statusAnim == B_ANIM_STATUS_SLP) { + STATUS_ICON(opponent, sleep: TRUE); + } else if (statusAnim == B_ANIM_STATUS_PSN) { + STATUS_ICON(opponent, poison: TRUE); + } } } } @@ -115,15 +114,15 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep a mon } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); - if (statusAnim == B_ANIM_STATUS_PRZ) { - NOT STATUS_ICON(opponent, paralysis: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_SLP) { - NOT STATUS_ICON(opponent, sleep: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PSN) { - NOT STATUS_ICON(opponent, poison: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); + if (statusAnim == B_ANIM_STATUS_PRZ) { + STATUS_ICON(opponent, paralysis: TRUE); + } else if (statusAnim == B_ANIM_STATUS_SLP) { + STATUS_ICON(opponent, sleep: TRUE); + } else if (statusAnim == B_ANIM_STATUS_PSN) { + STATUS_ICON(opponent, poison: TRUE); + } } } } diff --git a/test/battle/move_effect/dream_eater.c b/test/battle/move_effect/dream_eater.c index 047fe78982..62fd918a1b 100644 --- a/test/battle/move_effect/dream_eater.c +++ b/test/battle/move_effect/dream_eater.c @@ -47,8 +47,10 @@ SINGLE_BATTLE_TEST("Dream Eater fails if Heal Block applies") TURN { MOVE(opponent, MOVE_HEAL_BLOCK); MOVE(player, MOVE_DREAM_EATER); } } SCENE { MESSAGE("Wobbuffet was prevented from healing!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DREAM_EATER, player); - NOT HP_BAR(opponent); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DREAM_EATER, player); + HP_BAR(opponent); + HP_BAR(player); + } } } diff --git a/test/battle/move_effect/freeze_hit.c b/test/battle/move_effect/freeze_hit.c index 9874ccc775..4c9ff557e4 100644 --- a/test/battle/move_effect/freeze_hit.c +++ b/test/battle/move_effect/freeze_hit.c @@ -33,8 +33,10 @@ SINGLE_BATTLE_TEST("Powder Snow cannot freeze an Ice-type Pokémon") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER_SNOW, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); - NOT STATUS_ICON(opponent, freeze: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + STATUS_ICON(opponent, freeze: TRUE); + } } } @@ -61,6 +63,6 @@ SINGLE_BATTLE_TEST("Blizzard bypasses accuracy checks in Hail and Snow") } WHEN { TURN { MOVE(opponent, move); MOVE(player, MOVE_BLIZZARD); } } SCENE { - NONE_OF { MESSAGE("Wobbuffet's attack missed!"); } + NOT MESSAGE("Wobbuffet's attack missed!"); } } diff --git a/test/battle/move_effect/paralyze_hit.c b/test/battle/move_effect/paralyze_hit.c index 4efe6746ce..c2fa440be1 100644 --- a/test/battle/move_effect/paralyze_hit.c +++ b/test/battle/move_effect/paralyze_hit.c @@ -33,7 +33,9 @@ SINGLE_BATTLE_TEST("Thunder Shock cannot paralyze an Electric-type") } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent); - NOT STATUS_ICON(opponent, paralysis: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent); + STATUS_ICON(opponent, paralysis: TRUE); + } } } diff --git a/test/battle/move_effect/poison_hit.c b/test/battle/move_effect/poison_hit.c index 95a8fbc946..229355cb65 100644 --- a/test/battle/move_effect/poison_hit.c +++ b/test/battle/move_effect/poison_hit.c @@ -38,7 +38,9 @@ SINGLE_BATTLE_TEST("Poison cannot be inflicted on Poison and Steel-type Pokémon } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TWINEEDLE, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); - NOT STATUS_ICON(opponent, poison: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } } } diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 39bd0eb8ae..dd9f57b356 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -93,8 +93,8 @@ SINGLE_BATTLE_TEST("King's Shield, Silk Trap and Obstruct protect from damaging } else { NOT ANIMATION(ANIM_TYPE_MOVE, usedMove, player); MESSAGE("Foe Wobbuffet protected itself!"); - NOT HP_BAR(opponent); if (usedMove == MOVE_TACKLE) { + NOT HP_BAR(opponent); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); if (statId == STAT_ATK) { MESSAGE("Wobbuffet's Attack fell!"); @@ -106,7 +106,10 @@ SINGLE_BATTLE_TEST("King's Shield, Silk Trap and Obstruct protect from damaging } } } else { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + NONE_OF { + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } } } } THEN { @@ -173,11 +176,14 @@ SINGLE_BATTLE_TEST("Baneful Bunker poisons pokemon for moves making contact") MESSAGE("Foe Wobbuffet protected itself!"); NOT ANIMATION(ANIM_TYPE_MOVE, usedMove, player); MESSAGE("Foe Wobbuffet protected itself!"); - NOT HP_BAR(opponent); if (usedMove == MOVE_TACKLE) { + NOT HP_BAR(opponent); STATUS_ICON(player, STATUS1_POISON); } else { - NOT STATUS_ICON(player, STATUS1_POISON); + NONE_OF { + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_POISON); + } } } } @@ -218,8 +224,10 @@ SINGLE_BATTLE_TEST("Recoil damage is not applied if target was protected") ANIMATION(ANIM_TYPE_MOVE, protectMove, opponent); MESSAGE("Foe Beautifly protected itself!"); // MESSAGE("Rapidash used recoilMove!"); - NOT ANIMATION(ANIM_TYPE_MOVE, recoilMove, player); - NOT MESSAGE("Rapidash is hit with recoil!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, recoilMove, player); + MESSAGE("Rapidash is hit with recoil!"); + } } } @@ -251,16 +259,17 @@ SINGLE_BATTLE_TEST("Multi-hit moves don't hit a protected target and fail only o // Each effect happens only once. if (move == MOVE_KINGS_SHIELD || move == MOVE_SILK_TRAP || move == MOVE_OBSTRUCT) { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - } - else if (move == MOVE_SPIKY_SHIELD) { + } else if (move == MOVE_SPIKY_SHIELD) { HP_BAR(player); - NOT HP_BAR(player); - } - else if (move == MOVE_BANEFUL_BUNKER) { + } else if (move == MOVE_BANEFUL_BUNKER) { STATUS_ICON(player, STATUS1_POISON); } NONE_OF { + if (move == MOVE_KINGS_SHIELD || move == MOVE_SILK_TRAP || move == MOVE_OBSTRUCT) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } else if (move == MOVE_SPIKY_SHIELD) { + HP_BAR(player); + } MESSAGE("Hit 2 time(s)!"); MESSAGE("Hit 3 time(s)!"); MESSAGE("Hit 4 time(s)!"); diff --git a/test/battle/move_effect/roost.c b/test/battle/move_effect/roost.c index 4a3f90602d..12731e2345 100644 --- a/test/battle/move_effect/roost.c +++ b/test/battle/move_effect/roost.c @@ -36,8 +36,10 @@ SINGLE_BATTLE_TEST("Roost fails when user is at full HP") TURN { MOVE(player, MOVE_ROOST); } } SCENE { MESSAGE("Wobbuffet's HP is full!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); + HP_BAR(player); + } } } @@ -52,8 +54,10 @@ SINGLE_BATTLE_TEST("Roost fails if the user is under the effects of Heal Block") ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BLOCK, opponent); MESSAGE("Wobbuffet was prevented from healing!"); // Message when Heal Block is applied MESSAGE("Wobbuffet was prevented from healing!"); // Message when trying to heal under Heal Block - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); + HP_BAR(player); + } } } @@ -340,8 +344,10 @@ SINGLE_BATTLE_TEST("Roost's suppression prevents Reflect Type from copying any F // Turn 3: EQ has no effect MESSAGE("Swellow used Earthquake!"); MESSAGE("It doesn't affect Foe Wobbuffet…"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, player); - NOT HP_BAR(opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, player); + HP_BAR(opponent); + } } } @@ -357,8 +363,10 @@ SINGLE_BATTLE_TEST("Roost does not suppress the ungrounded effect of Levitate") ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); MESSAGE("Flygon regained health!"); MESSAGE("Foe Wobbuffet used Earthquake!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); + HP_BAR(player); + } } } @@ -374,8 +382,10 @@ SINGLE_BATTLE_TEST("Roost does not suppress the ungrounded effect of Air Balloon ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); MESSAGE("Wobbuffet regained health!"); MESSAGE("Foe Wobbuffet used Earthquake!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); + HP_BAR(player); + } } } @@ -397,8 +407,10 @@ SINGLE_BATTLE_TEST("Roost does not suppress the ungrounded effect of Magnet Rise ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); MESSAGE("Wobbuffet regained health!"); MESSAGE("Foe Wobbuffet used Earthquake!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); + HP_BAR(player); + } } } @@ -421,8 +433,10 @@ SINGLE_BATTLE_TEST("Roost does not suppress the ungrounded effect of Telekinesis ANIMATION(ANIM_TYPE_MOVE, MOVE_ROOST, player); MESSAGE("Wobbuffet regained health!"); MESSAGE("Foe Wobbuffet used Earthquake!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); - NOT HP_BAR(player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); + HP_BAR(player); + } } } diff --git a/test/battle/move_effect/teatime.c b/test/battle/move_effect/teatime.c index 7995937fa5..c4398f296a 100644 --- a/test/battle/move_effect/teatime.c +++ b/test/battle/move_effect/teatime.c @@ -149,8 +149,10 @@ SINGLE_BATTLE_TEST("Teatime does not affect Pokémon in the semi-invulnerable tu } } SCENE { MESSAGE("Wobbuffet used Teatime!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TEATIME, player); - NOT MESSAGE("Using Liechi Berry, the Attack of Foe Wobbuffet rose!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TEATIME, player); + MESSAGE("Using Liechi Berry, the Attack of Foe Wobbuffet rose!"); + } } } @@ -206,7 +208,7 @@ SINGLE_BATTLE_TEST("Teatime triggers Lightning Rod if it has been affected by El PLAYER(SPECIES_PIKACHU) { Ability(ABILITY_LIGHTNING_ROD); Item(item); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIECHI_BERRY); } } WHEN { - TURN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_TEATIME); } diff --git a/test/battle/move_effect/toxic.c b/test/battle/move_effect/toxic.c index 78d978b268..4a07994fb8 100644 --- a/test/battle/move_effect/toxic.c +++ b/test/battle/move_effect/toxic.c @@ -40,9 +40,11 @@ SINGLE_BATTLE_TEST("Toxic cannot miss if used by a Poison-type") ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); STATUS_ICON(opponent, badPoison: TRUE); } else { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player); - NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); - NOT STATUS_ICON(opponent, badPoison: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, badPoison: TRUE); + } } } } diff --git a/test/battle/move_effect/tri_attack.c b/test/battle/move_effect/tri_attack.c index aec711aaba..d7d2102271 100644 --- a/test/battle/move_effect/tri_attack.c +++ b/test/battle/move_effect/tri_attack.c @@ -25,11 +25,9 @@ SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze") ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); if (statusAnim == B_ANIM_STATUS_BRN) { STATUS_ICON(opponent, burn: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_FRZ) { + } else if (statusAnim == B_ANIM_STATUS_FRZ) { STATUS_ICON(opponent, freeze: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PRZ) { + } else if (statusAnim == B_ANIM_STATUS_PRZ) { STATUS_ICON(opponent, paralysis: TRUE); } } @@ -54,15 +52,15 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); - if (statusAnim == B_ANIM_STATUS_BRN) { - NOT STATUS_ICON(opponent, burn: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_FRZ) { - NOT STATUS_ICON(opponent, freeze: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PRZ) { - NOT STATUS_ICON(opponent, paralysis: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); + if (statusAnim == B_ANIM_STATUS_BRN) { + STATUS_ICON(opponent, burn: TRUE); + } else if (statusAnim == B_ANIM_STATUS_FRZ) { + STATUS_ICON(opponent, freeze: TRUE); + } else if (statusAnim == B_ANIM_STATUS_PRZ) { + STATUS_ICON(opponent, paralysis: TRUE); + } } } } @@ -92,15 +90,15 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilitie } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); - if (statusAnim == B_ANIM_STATUS_BRN) { - NOT STATUS_ICON(opponent, burn: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_FRZ) { - NOT STATUS_ICON(opponent, freeze: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PRZ) { - NOT STATUS_ICON(opponent, paralysis: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); + if (statusAnim == B_ANIM_STATUS_BRN) { + STATUS_ICON(opponent, burn: TRUE); + } else if (statusAnim == B_ANIM_STATUS_FRZ) { + STATUS_ICON(opponent, freeze: TRUE); + } else if (statusAnim == B_ANIM_STATUS_PRZ) { + STATUS_ICON(opponent, paralysis: TRUE); + } } } } @@ -121,15 +119,15 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze a mon which is alread } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); HP_BAR(opponent); - NOT ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); - if (statusAnim == B_ANIM_STATUS_BRN) { - NOT STATUS_ICON(opponent, burn: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_FRZ) { - NOT STATUS_ICON(opponent, freeze: TRUE); - } - else if (statusAnim == B_ANIM_STATUS_PRZ) { - NOT STATUS_ICON(opponent, paralysis: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponent); + if (statusAnim == B_ANIM_STATUS_BRN) { + STATUS_ICON(opponent, burn: TRUE); + } else if (statusAnim == B_ANIM_STATUS_FRZ) { + STATUS_ICON(opponent, freeze: TRUE); + } else if (statusAnim == B_ANIM_STATUS_PRZ) { + STATUS_ICON(opponent, paralysis: TRUE); + } } } } diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 54c8baae24..d784b3314d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1657,8 +1657,18 @@ static const char *const sQueueGroupTypeMacros[] = void OpenQueueGroup(u32 sourceLine, enum QueueGroupType type) { INVALID_IF(DATA.queueGroupType, "%s inside %s", sQueueGroupTypeMacros[type], sQueueGroupTypeMacros[DATA.queueGroupType]); - DATA.queueGroupType = type; - DATA.queueGroupStart = DATA.queuedEventsCount; + if (DATA.queuedEventsCount > 0 + && DATA.queuedEvents[DATA.queueGroupStart].groupType == QUEUE_GROUP_NONE_OF + && DATA.queuedEvents[DATA.queueGroupStart].groupSize == DATA.queuedEventsCount - DATA.queueGroupStart + && type == QUEUE_GROUP_NONE_OF) + { + INVALID("'NOT x; NOT y;', did you mean 'NONE_OF { x; y; }'?"); + } + else + { + DATA.queueGroupType = type; + DATA.queueGroupStart = DATA.queuedEventsCount; + } } void CloseQueueGroup(u32 sourceLine) From 81cbbdb185bcc2f73589d72f92a43ce84d3b063b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Tue, 24 Oct 2023 09:31:03 -0300 Subject: [PATCH 11/15] Setting Modern as default (#3305) --- .github/workflows/build.yml | 6 +++++- Makefile | 12 +++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b55f8a9ab1..9fd8944d38 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,9 @@ jobs: working-directory: agbcc - name: Agbcc + env: + MODERN: 0 + COMPARE: 0 run: make -j${nproc} -O all - name: Modern @@ -50,7 +53,8 @@ jobs: - name: Test env: + MODERN: 1 TEST: 1 run: | - make -j${nproc} -O pokeemerald-test.elf + make -j${nproc} -O pokeemerald_modern-test.elf make -j${nproc} check diff --git a/Makefile b/Makefile index abd395c057..4b59c76f66 100644 --- a/Makefile +++ b/Makefile @@ -40,12 +40,12 @@ TITLE := POKEMON EMER GAME_CODE := BPEE MAKER_CODE := 01 REVISION := 0 -MODERN ?= 0 +MODERN ?= 1 TEST ?= 0 ANALYZE ?= 0 -ifeq (modern,$(MAKECMDGOALS)) - MODERN := 1 +ifeq (agbcc,$(MAKECMDGOALS)) + MODERN := 0 endif ifeq (check,$(MAKECMDGOALS)) @@ -182,7 +182,7 @@ MAKEFLAGS += --no-print-directory # Secondary expansion is required for dependency variables in object rules. .SECONDEXPANSION: -.PHONY: all rom clean compare tidy tools check-tools mostlyclean clean-tools clean-check-tools $(TOOLDIRS) $(CHECKTOOLDIRS) libagbsyscall modern tidymodern tidynonmodern check +.PHONY: all rom clean compare tidy tools check-tools mostlyclean clean-tools clean-check-tools $(TOOLDIRS) $(CHECKTOOLDIRS) libagbsyscall agbcc modern tidymodern tidynonmodern check infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line)))) @@ -190,7 +190,7 @@ infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst # Disable dependency scanning for clean/tidy/tools # Use a separate minimal makefile for speed # Since we don't need to reload most of this makefile -ifeq (,$(filter-out all rom compare modern check libagbsyscall syms $(TESTELF),$(MAKECMDGOALS))) +ifeq (,$(filter-out all rom compare agbcc modern check libagbsyscall syms $(TESTELF),$(MAKECMDGOALS))) $(call infoshell, $(MAKE) -f make_tools.mk) else NODEP ?= 1 @@ -485,6 +485,8 @@ $(ROM): $(ELF) $(OBJCOPY) -O binary $< $@ $(FIX) $@ -p --silent +agbcc: all + modern: all LD_SCRIPT_TEST := ld_script_test.txt From 7a9221e7b990299c95af8089b4a36f209bbc7af5 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Wed, 25 Oct 2023 12:51:12 +0200 Subject: [PATCH 12/15] Rename output roms (#3462) * Rename output roms * Update build.yml --- .github/workflows/build.yml | 2 +- Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9fd8944d38..51c0a78e51 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,5 +56,5 @@ jobs: MODERN: 1 TEST: 1 run: | - make -j${nproc} -O pokeemerald_modern-test.elf + make -j${nproc} -O pokeemerald-test.elf make -j${nproc} check diff --git a/Makefile b/Makefile index 4b59c76f66..b9a06f55f3 100644 --- a/Makefile +++ b/Makefile @@ -69,12 +69,12 @@ else CPP := $(PREFIX)cpp endif -ROM_NAME := pokeemerald.gba +ROM_NAME := pokeemerald_agbcc.gba ELF_NAME := $(ROM_NAME:.gba=.elf) MAP_NAME := $(ROM_NAME:.gba=.map) OBJ_DIR_NAME := build/emerald -MODERN_ROM_NAME := pokeemerald_modern.gba +MODERN_ROM_NAME := pokeemerald.gba MODERN_ELF_NAME := $(MODERN_ROM_NAME:.gba=.elf) MODERN_MAP_NAME := $(MODERN_ROM_NAME:.gba=.map) MODERN_OBJ_DIR_NAME := build/modern From cb38f3bee6422a814bddea0cdc6d7eca04df4661 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 25 Oct 2023 17:06:25 +0200 Subject: [PATCH 13/15] Fixes legendary backgrounds (#3464) * Fixes legendary backgrounds * missed one * forgot break --- data/scripts/debug.inc | 12 ++++++------ src/battle_bg.c | 9 +++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 7385101c1e..b9028177d9 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -155,28 +155,28 @@ DebugScript_HatchAnEgg_Text_EmptyParty:: DebugScript_HatchAnEgg_Text_NotAnEgg:: .string "That's not a Pokémon Egg.$" - + DebugScript_ZeroDaycareMons:: msgbox DebugText_DaycareNoPokemon, MSGBOX_DEFAULT releaseall end - + DebugScript_OneDaycareMons:: msgbox DebugText_DaycareOnePokemon, MSGBOX_DEFAULT releaseall end - + DebugScript_DaycareMonsNotCompatible:: msgbox DebugText_DaycarePokemonNotCompatible, MSGBOX_DEFAULT releaseall end - + DebugText_DaycareNoPokemon: .string "You have no Pokémon at Daycare.$" - + DebugText_DaycareOnePokemon: .string "You have only one Pokémon at Daycare.$" - + DebugText_DaycarePokemonNotCompatible: .string "Your Pokémon at Daycare can't\nhave babies together!$" diff --git a/src/battle_bg.c b/src/battle_bg.c index 1da5d5c65e..2e92658343 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -777,6 +777,11 @@ void DrawMainBattleBackground(void) LZDecompressVram(gBattleTerrainTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Rayquaza, 0x20, 0x60); break; + default: + LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); + LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); + LoadCompressedPalette(sBattleTerrainTable[gBattleTerrain].palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); + break; } } else @@ -1174,6 +1179,10 @@ void DrawBattleEntryBackground(void) LZDecompressVram(gBattleTerrainAnimTiles_Rayquaza, (void*)(BG_CHAR_ADDR(1))); LZDecompressVram(gBattleTerrainAnimTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(28))); break; + default: + LZDecompressVram(sBattleTerrainTable[gBattleTerrain].entryTileset, (void *)(BG_CHAR_ADDR(1))); + LZDecompressVram(sBattleTerrainTable[gBattleTerrain].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); + break; } } else From bb9d3208b00632f24ee8dfbc1ea0b0aa1382b92c Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 26 Oct 2023 15:52:43 +0200 Subject: [PATCH 14/15] Frontier ban refactor (#3465) Co-authored-by: Eduardo Quezada D'Ottone --- src/frontier_util.c | 65 +++++++++++++++++++++++++-------------------- src/party_menu.c | 2 +- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/frontier_util.c b/src/frontier_util.c index d138daba4c..df3afcd8a2 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -624,8 +624,28 @@ static const u8 sFrontierBrainObjEventGfx[NUM_FRONTIER_FACILITIES][2] = const u16 gFrontierBannedSpecies[] = { - SPECIES_MEW, SPECIES_MEWTWO, SPECIES_HO_OH, SPECIES_LUGIA, SPECIES_CELEBI, - SPECIES_KYOGRE, SPECIES_GROUDON, SPECIES_RAYQUAZA, SPECIES_JIRACHI, SPECIES_DEOXYS, 0xFFFF + SPECIES_MEW, SPECIES_MEWTWO, + SPECIES_HO_OH, SPECIES_LUGIA, SPECIES_CELEBI, + SPECIES_KYOGRE, SPECIES_GROUDON, SPECIES_RAYQUAZA, SPECIES_JIRACHI, SPECIES_DEOXYS, +#if P_GEN_4_POKEMON == TRUE + SPECIES_DIALGA, SPECIES_PALKIA, SPECIES_GIRATINA, SPECIES_MANAPHY, SPECIES_PHIONE, SPECIES_DARKRAI, SPECIES_SHAYMIN, SPECIES_ARCEUS, +#endif +#if P_GEN_5_POKEMON == TRUE + SPECIES_VICTINI, SPECIES_RESHIRAM, SPECIES_ZEKROM, SPECIES_KYUREM, SPECIES_KELDEO, SPECIES_MELOETTA, SPECIES_GENESECT, +#endif +#if P_GEN_6_POKEMON == TRUE + SPECIES_XERNEAS, SPECIES_YVELTAL, SPECIES_ZYGARDE, SPECIES_DIANCIE, SPECIES_HOOPA, SPECIES_VOLCANION, +#endif +#if P_GEN_7_POKEMON == TRUE + SPECIES_COSMOG, SPECIES_COSMOEM, SPECIES_SOLGALEO, SPECIES_LUNALA, SPECIES_NECROZMA, SPECIES_MAGEARNA, SPECIES_MARSHADOW, SPECIES_ZERAORA, SPECIES_MELTAN, SPECIES_MELMETAL, +#endif +#if P_GEN_8_POKEMON == TRUE + SPECIES_ZACIAN, SPECIES_ZAMAZENTA, SPECIES_ETERNATUS, SPECIES_CALYREX, SPECIES_ZARUDE, +#endif +#if P_GEN_9_POKEMON == TRUE + SPECIES_KORAIDON, SPECIES_MIRAIDON, +#endif + 0xFFFF }; static const u8 *const sRecordsWindowChallengeTexts[][2] = @@ -1878,38 +1898,23 @@ static void CheckBattleTypeFlag(void) gSpecialVar_Result = FALSE; } +#define SPECIES_PER_LINE 3 + static u8 AppendCaughtBannedMonSpeciesName(u16 species, u8 count, s32 numBannedMonsCaught) { if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT)) { count++; - switch (count) + if (numBannedMonsCaught == count) + StringAppend(gStringVar1, gText_SpaceAndSpace); + else if (numBannedMonsCaught > count) + StringAppend(gStringVar1, gText_CommaSpace); + if ((count % SPECIES_PER_LINE) == 0) { - case 1: - case 3: - case 5: - case 7: - case 9: - case 11: - if (numBannedMonsCaught == count) - StringAppend(gStringVar1, gText_SpaceAndSpace); - else if (numBannedMonsCaught > count) - StringAppend(gStringVar1, gText_CommaSpace); - break; - case 2: - if (count == numBannedMonsCaught) - StringAppend(gStringVar1, gText_SpaceAndSpace); + if (count == SPECIES_PER_LINE) + StringAppend(gStringVar1, gText_NewLine); else - StringAppend(gStringVar1, gText_CommaSpace); - StringAppend(gStringVar1, gText_NewLine); - break; - default: - if (count == numBannedMonsCaught) - StringAppend(gStringVar1, gText_SpaceAndSpace); - else - StringAppend(gStringVar1, gText_CommaSpace); - StringAppend(gStringVar1, gText_LineBreak); - break; + StringAppend(gStringVar1, gText_LineBreak); } StringAppend(gStringVar1, GetSpeciesName(species)); } @@ -1924,7 +1929,7 @@ static void AppendIfValid(u16 species, u16 heldItem, u16 hp, u8 lvlMode, u8 monL if (species == SPECIES_EGG || species == SPECIES_NONE) return; - for (i = 0; gFrontierBannedSpecies[i] != 0xFFFF && gFrontierBannedSpecies[i] != species; i++) + for (i = 0; gFrontierBannedSpecies[i] != 0xFFFF && gFrontierBannedSpecies[i] != GET_BASE_SPECIES_ID(species); i++) ; if (gFrontierBannedSpecies[i] != 0xFFFF) @@ -2034,7 +2039,7 @@ static void CheckPartyIneligibility(void) } else { - if (count & 1) + if (count % SPECIES_PER_LINE == SPECIES_PER_LINE - 1) StringAppend(gStringVar1, gText_LineBreak); else StringAppend(gStringVar1, gText_Space2); @@ -2049,6 +2054,8 @@ static void CheckPartyIneligibility(void) #undef numEligibleMons } +#undef SPECIES_PER_LINE + static void ValidateVisitingTrainer(void) { ValidateEReaderTrainer(); diff --git a/src/party_menu.c b/src/party_menu.c index 8170ec7d25..e1dad9ef9b 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -6195,7 +6195,7 @@ static bool8 GetBattleEntryEligibility(struct Pokemon *mon) species = GetMonData(mon, MON_DATA_SPECIES); for (; gFrontierBannedSpecies[i] != 0xFFFF; i++) { - if (gFrontierBannedSpecies[i] == species) + if (gFrontierBannedSpecies[i] == GET_BASE_SPECIES_ID(species)) return FALSE; } return TRUE; From a8632f0fc52d2630e9973541718748a4e998aaab Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Thu, 26 Oct 2023 15:45:33 -0500 Subject: [PATCH 15/15] Update PLA Pokemon data to correct values (#3458) * Fix PLA Pokemon data to use correct values * oops, cant forget basculin white stripe * Update level_up_learnsets.h * Update species_info.h --- src/data/pokemon/level_up_learnsets.h | 580 +++++++++++++++++--------- src/data/pokemon/species_info.h | 79 ++-- 2 files changed, 418 insertions(+), 241 deletions(-) diff --git a/src/data/pokemon/level_up_learnsets.h b/src/data/pokemon/level_up_learnsets.h index 092a711918..7ae4e87471 100644 --- a/src/data/pokemon/level_up_learnsets.h +++ b/src/data/pokemon/level_up_learnsets.h @@ -18099,92 +18099,144 @@ static const struct LevelUpMove sCalyrexLevelUpLearnset[] = { }; static const struct LevelUpMove sWyrdeerLevelUpLearnset[] = { + LEVEL_UP_MOVE( 0, MOVE_PSYSHIELD_BASH), LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 5, MOVE_CONFUSION), - LEVEL_UP_MOVE( 9, MOVE_HYPNOSIS), - LEVEL_UP_MOVE(15, MOVE_CALM_MIND), - LEVEL_UP_MOVE(21, MOVE_PSYSHIELD_BASH), - LEVEL_UP_MOVE(29, MOVE_EXTRASENSORY), + LEVEL_UP_MOVE( 3, MOVE_LEER), + LEVEL_UP_MOVE( 7, MOVE_ASTONISH), + LEVEL_UP_MOVE(10, MOVE_HYPNOSIS), + LEVEL_UP_MOVE(13, MOVE_STOMP), + LEVEL_UP_MOVE(16, MOVE_SAND_ATTACK), + LEVEL_UP_MOVE(21, MOVE_TAKE_DOWN), + LEVEL_UP_MOVE(23, MOVE_CONFUSE_RAY), + LEVEL_UP_MOVE(27, MOVE_CALM_MIND), + LEVEL_UP_MOVE(32, MOVE_ROLE_PLAY), LEVEL_UP_MOVE(37, MOVE_ZEN_HEADBUTT), - LEVEL_UP_MOVE(47, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE(49, MOVE_IMPRISON), + LEVEL_UP_MOVE(55, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE(62, MOVE_MEGAHORN), LEVEL_UP_END }; static const struct LevelUpMove sKleavorLevelUpLearnset[] = { + LEVEL_UP_MOVE( 0, MOVE_STONE_AXE), + LEVEL_UP_MOVE( 1, MOVE_LEER), LEVEL_UP_MOVE( 1, MOVE_QUICK_ATTACK), - LEVEL_UP_MOVE( 6, MOVE_SILVER_WIND), - LEVEL_UP_MOVE(11, MOVE_AERIAL_ACE), - LEVEL_UP_MOVE(14, MOVE_DOUBLE_HIT), - LEVEL_UP_MOVE(14, MOVE_STEALTH_ROCK), - LEVEL_UP_MOVE(18, MOVE_AIR_SLASH), - LEVEL_UP_MOVE(25, MOVE_SWORDS_DANCE), - LEVEL_UP_MOVE(29, MOVE_STONE_AXE), - LEVEL_UP_MOVE(34, MOVE_X_SCISSOR), - LEVEL_UP_MOVE(43, MOVE_CLOSE_COMBAT), + LEVEL_UP_MOVE( 4, MOVE_FURY_CUTTER), + LEVEL_UP_MOVE( 8, MOVE_FALSE_SWIPE), + LEVEL_UP_MOVE(12, MOVE_SMACK_DOWN), + LEVEL_UP_MOVE(16, MOVE_DOUBLE_TEAM), + LEVEL_UP_MOVE(20, MOVE_DOUBLE_HIT), + LEVEL_UP_MOVE(24, MOVE_SLASH), + LEVEL_UP_MOVE(28, MOVE_FOCUS_ENERGY), + LEVEL_UP_MOVE(32, MOVE_AGILITY), + LEVEL_UP_MOVE(36, MOVE_ROCK_SLIDE), + LEVEL_UP_MOVE(40, MOVE_X_SCISSOR), + LEVEL_UP_MOVE(44, MOVE_SWORDS_DANCE), LEVEL_UP_END }; static const struct LevelUpMove sUrsalunaLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 6, MOVE_BABY_DOLL_EYES), - LEVEL_UP_MOVE(11, MOVE_BULLDOZE), - LEVEL_UP_MOVE(18, MOVE_SLASH), - LEVEL_UP_MOVE(25, MOVE_PLAY_ROUGH), - LEVEL_UP_MOVE(34, MOVE_HIGH_HORSEPOWER), - LEVEL_UP_MOVE(43, MOVE_DOUBLE_EDGE), - LEVEL_UP_MOVE(47, MOVE_HEADLONG_RUSH), + LEVEL_UP_MOVE( 0, MOVE_HEADLONG_RUSH), + LEVEL_UP_MOVE( 1, MOVE_FAKE_TEARS), + LEVEL_UP_MOVE( 1, MOVE_COVET), + LEVEL_UP_MOVE( 1, MOVE_SCRATCH), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_LICK), + LEVEL_UP_MOVE( 8, MOVE_FURY_SWIPES), + LEVEL_UP_MOVE(13, MOVE_PAYBACK), + LEVEL_UP_MOVE(17, MOVE_SWEET_SCENT), + LEVEL_UP_MOVE(22, MOVE_SLASH), + LEVEL_UP_MOVE(25, MOVE_PLAY_NICE), + LEVEL_UP_MOVE(29, MOVE_PLAY_ROUGH), + LEVEL_UP_MOVE(35, MOVE_SCARY_FACE), + LEVEL_UP_MOVE(41, MOVE_REST), + LEVEL_UP_MOVE(41, MOVE_SNORE), + LEVEL_UP_MOVE(48, MOVE_HIGH_HORSEPOWER), + LEVEL_UP_MOVE(56, MOVE_THRASH), + LEVEL_UP_MOVE(64, MOVE_HAMMER_ARM), LEVEL_UP_END }; static const struct LevelUpMove sBasculegionLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 6, MOVE_AQUA_JET), - LEVEL_UP_MOVE(11, MOVE_BITE), - LEVEL_UP_MOVE(11, MOVE_HEX), - LEVEL_UP_MOVE(18, MOVE_ZEN_HEADBUTT), - LEVEL_UP_MOVE(25, MOVE_CRUNCH), - LEVEL_UP_MOVE(25, MOVE_SHADOW_BALL), - LEVEL_UP_MOVE(34, MOVE_WAVE_CRASH), - LEVEL_UP_MOVE(43, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE( 1, MOVE_SHADOW_BALL), + LEVEL_UP_MOVE( 1, MOVE_TAIL_WHIP), + LEVEL_UP_MOVE( 1, MOVE_WATER_GUN), + LEVEL_UP_MOVE( 1, MOVE_PHANTOM_FORCE), + LEVEL_UP_MOVE( 4, MOVE_TACKLE), + LEVEL_UP_MOVE( 8, MOVE_FLAIL), + LEVEL_UP_MOVE(12, MOVE_AQUA_JET), + LEVEL_UP_MOVE(16, MOVE_BITE), + LEVEL_UP_MOVE(20, MOVE_SCARY_FACE), + LEVEL_UP_MOVE(24, MOVE_HEADBUTT), + LEVEL_UP_MOVE(28, MOVE_SOAK), + LEVEL_UP_MOVE(32, MOVE_CRUNCH), + LEVEL_UP_MOVE(36, MOVE_TAKE_DOWN), + LEVEL_UP_MOVE(40, MOVE_UPROAR), + LEVEL_UP_MOVE(44, MOVE_WAVE_CRASH), + LEVEL_UP_MOVE(48, MOVE_THRASH), + LEVEL_UP_MOVE(52, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE(56, MOVE_HEAD_SMASH), LEVEL_UP_END }; static const struct LevelUpMove sSneaslerLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_QUICK_ATTACK), - LEVEL_UP_MOVE( 6, MOVE_ROCK_SMASH), - LEVEL_UP_MOVE(11, MOVE_DIRE_CLAW), - LEVEL_UP_MOVE(11, MOVE_SWIFT), - LEVEL_UP_MOVE(18, MOVE_SLASH), - LEVEL_UP_MOVE(25, MOVE_POISON_JAB), - LEVEL_UP_MOVE(34, MOVE_SWORDS_DANCE), - LEVEL_UP_MOVE(43, MOVE_CLOSE_COMBAT), + LEVEL_UP_MOVE( 0, MOVE_DIRE_CLAW), + LEVEL_UP_MOVE( 1, MOVE_FLING), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_ROCK_SMASH), + LEVEL_UP_MOVE( 1, MOVE_SCRATCH), + LEVEL_UP_MOVE( 6, MOVE_TAUNT), + LEVEL_UP_MOVE(12, MOVE_QUICK_ATTACK), + LEVEL_UP_MOVE(18, MOVE_METAL_CLAW), + LEVEL_UP_MOVE(24, MOVE_POISON_JAB), + LEVEL_UP_MOVE(30, MOVE_BRICK_BREAK), + LEVEL_UP_MOVE(36, MOVE_HONE_CLAWS), + LEVEL_UP_MOVE(42, MOVE_SLASH), + LEVEL_UP_MOVE(48, MOVE_AGILITY), + LEVEL_UP_MOVE(54, MOVE_SCREECH), + LEVEL_UP_MOVE(60, MOVE_CLOSE_COMBAT), LEVEL_UP_END }; static const struct LevelUpMove sOverqwilLevelUpLearnset[] = { + LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE( 1, MOVE_POISON_STING), - LEVEL_UP_MOVE( 5, MOVE_SPIKES), - LEVEL_UP_MOVE( 9, MOVE_PIN_MISSILE), - LEVEL_UP_MOVE(15, MOVE_BARB_BARRAGE), - LEVEL_UP_MOVE(21, MOVE_WATER_PULSE), - LEVEL_UP_MOVE(26, MOVE_DARK_PULSE), - LEVEL_UP_MOVE(29, MOVE_POISON_JAB), - LEVEL_UP_MOVE(37, MOVE_AQUA_TAIL), - LEVEL_UP_MOVE(47, MOVE_DOUBLE_EDGE), - LEVEL_UP_MOVE(57, MOVE_SELF_DESTRUCT), + LEVEL_UP_MOVE( 4, MOVE_HARDEN), + LEVEL_UP_MOVE( 8, MOVE_BITE), + LEVEL_UP_MOVE(12, MOVE_FELL_STINGER), + LEVEL_UP_MOVE(16, MOVE_MINIMIZE), + LEVEL_UP_MOVE(20, MOVE_SPIKES), + LEVEL_UP_MOVE(24, MOVE_BRINE), + LEVEL_UP_MOVE(28, MOVE_BARB_BARRAGE), + LEVEL_UP_MOVE(32, MOVE_PIN_MISSILE), + LEVEL_UP_MOVE(36, MOVE_TOXIC_SPIKES), + LEVEL_UP_MOVE(40, MOVE_STOCKPILE), + LEVEL_UP_MOVE(40, MOVE_SPIT_UP), + LEVEL_UP_MOVE(44, MOVE_TOXIC), + LEVEL_UP_MOVE(48, MOVE_CRUNCH), + LEVEL_UP_MOVE(52, MOVE_ACUPRESSURE), + LEVEL_UP_MOVE(56, MOVE_DESTINY_BOND), LEVEL_UP_END }; static const struct LevelUpMove sEnamorusLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 7, MOVE_BITE), - LEVEL_UP_MOVE(11, MOVE_TWISTER), - LEVEL_UP_MOVE(14, MOVE_DRAINING_KISS), - LEVEL_UP_MOVE(22, MOVE_IRON_DEFENSE), - LEVEL_UP_MOVE(31, MOVE_EXTRASENSORY), - LEVEL_UP_MOVE(41, MOVE_CRUNCH), - LEVEL_UP_MOVE(47, MOVE_MOONBLAST), - LEVEL_UP_MOVE( 1, MOVE_SPRINGTIDE_STORM), + LEVEL_UP_MOVE( 1, MOVE_ASTONISH), + LEVEL_UP_MOVE( 1, MOVE_FAIRY_WIND), + LEVEL_UP_MOVE( 5, MOVE_TORMENT), + LEVEL_UP_MOVE(10, MOVE_FLATTER), + LEVEL_UP_MOVE(15, MOVE_TWISTER), + LEVEL_UP_MOVE(20, MOVE_DRAINING_KISS), + LEVEL_UP_MOVE(25, MOVE_IRON_DEFENSE), + LEVEL_UP_MOVE(30, MOVE_IMPRISON), + LEVEL_UP_MOVE(35, MOVE_MYSTICAL_FIRE), + LEVEL_UP_MOVE(40, MOVE_DAZZLING_GLEAM), + LEVEL_UP_MOVE(45, MOVE_EXTRASENSORY), + LEVEL_UP_MOVE(50, MOVE_UPROAR), + LEVEL_UP_MOVE(55, MOVE_SUPERPOWER), + LEVEL_UP_MOVE(60, MOVE_HEALING_WISH), + LEVEL_UP_MOVE(65, MOVE_MOONBLAST), + LEVEL_UP_MOVE(70, MOVE_OUTRAGE), + LEVEL_UP_MOVE(75, MOVE_SPRINGTIDE_STORM), LEVEL_UP_END }; #endif @@ -18946,221 +18998,345 @@ static const struct LevelUpMove sStunfiskGalarianLevelUpLearnset[] = { #endif static const struct LevelUpMove sGrowlitheHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 5, MOVE_EMBER), - LEVEL_UP_MOVE( 9, MOVE_BITE), - LEVEL_UP_MOVE(15, MOVE_FIRE_FANG), - LEVEL_UP_MOVE(21, MOVE_ROCK_SLIDE), - LEVEL_UP_MOVE(29, MOVE_CRUNCH), - LEVEL_UP_MOVE(37, MOVE_DOUBLE_EDGE), - LEVEL_UP_MOVE(47, MOVE_FLARE_BLITZ), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_EMBER), + LEVEL_UP_MOVE( 4, MOVE_HOWL), + LEVEL_UP_MOVE( 8, MOVE_BITE), + LEVEL_UP_MOVE(12, MOVE_FLAME_WHEEL), + LEVEL_UP_MOVE(16, MOVE_HELPING_HAND), + LEVEL_UP_MOVE(24, MOVE_FIRE_FANG), + LEVEL_UP_MOVE(28, MOVE_RETALIATE), + LEVEL_UP_MOVE(32, MOVE_CRUNCH), + LEVEL_UP_MOVE(36, MOVE_TAKE_DOWN), + LEVEL_UP_MOVE(40, MOVE_FLAMETHROWER), + LEVEL_UP_MOVE(44, MOVE_ROAR), + LEVEL_UP_MOVE(48, MOVE_ROCK_SLIDE), + LEVEL_UP_MOVE(52, MOVE_REVERSAL), + LEVEL_UP_MOVE(56, MOVE_FLARE_BLITZ), LEVEL_UP_END }; static const struct LevelUpMove sArcanineHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 5, MOVE_EMBER), - LEVEL_UP_MOVE( 9, MOVE_BITE), - LEVEL_UP_MOVE(15, MOVE_FIRE_FANG), - LEVEL_UP_MOVE(21, MOVE_ROCK_SLIDE), - LEVEL_UP_MOVE(29, MOVE_CRUNCH), - LEVEL_UP_MOVE(29, MOVE_RAGING_FURY), - LEVEL_UP_MOVE(37, MOVE_DOUBLE_EDGE), - LEVEL_UP_MOVE(47, MOVE_FLARE_BLITZ), + LEVEL_UP_MOVE( 0, MOVE_EXTREME_SPEED), + LEVEL_UP_MOVE( 1, MOVE_FLAME_WHEEL), + LEVEL_UP_MOVE( 1, MOVE_FIRE_FANG), + LEVEL_UP_MOVE( 1, MOVE_FLARE_BLITZ), + LEVEL_UP_MOVE( 1, MOVE_HOWL), + LEVEL_UP_MOVE( 1, MOVE_HELPING_HAND), + LEVEL_UP_MOVE( 1, MOVE_CRUNCH), + LEVEL_UP_MOVE( 1, MOVE_REVERSAL), + LEVEL_UP_MOVE( 1, MOVE_RETALIATE), + LEVEL_UP_MOVE( 1, MOVE_TAKE_DOWN), + LEVEL_UP_MOVE( 1, MOVE_AGILITY), + LEVEL_UP_MOVE( 1, MOVE_ROCK_THROW), + LEVEL_UP_MOVE( 1, MOVE_EMBER), + LEVEL_UP_MOVE( 1, MOVE_ROAR), + LEVEL_UP_MOVE( 1, MOVE_BITE), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_ROCK_SLIDE), + LEVEL_UP_MOVE( 5, MOVE_FLAMETHROWER), + LEVEL_UP_MOVE(64, MOVE_RAGING_FURY), LEVEL_UP_END }; static const struct LevelUpMove sVoltorbHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_THUNDER_SHOCK), - LEVEL_UP_MOVE( 5, MOVE_TACKLE), - LEVEL_UP_MOVE( 9, MOVE_THUNDER_WAVE), - LEVEL_UP_MOVE(15, MOVE_SPARK), - LEVEL_UP_MOVE(21, MOVE_ENERGY_BALL), - LEVEL_UP_MOVE(29, MOVE_THUNDERBOLT), - LEVEL_UP_MOVE(37, MOVE_THUNDER), - LEVEL_UP_MOVE(47, MOVE_SELF_DESTRUCT), + LEVEL_UP_MOVE( 1, MOVE_CHARGE), + LEVEL_UP_MOVE( 1, MOVE_TACKLE), + LEVEL_UP_MOVE( 4, MOVE_THUNDER_SHOCK), + LEVEL_UP_MOVE( 6, MOVE_STUN_SPORE), + LEVEL_UP_MOVE( 9, MOVE_BULLET_SEED), + LEVEL_UP_MOVE(11, MOVE_ROLLOUT), + LEVEL_UP_MOVE(13, MOVE_SCREECH), + LEVEL_UP_MOVE(16, MOVE_CHARGE_BEAM), + LEVEL_UP_MOVE(20, MOVE_SWIFT), + LEVEL_UP_MOVE(22, MOVE_ELECTRO_BALL), + LEVEL_UP_MOVE(26, MOVE_SELF_DESTRUCT), + LEVEL_UP_MOVE(29, MOVE_ENERGY_BALL), + LEVEL_UP_MOVE(34, MOVE_SEED_BOMB), + LEVEL_UP_MOVE(34, MOVE_DISCHARGE), + LEVEL_UP_MOVE(41, MOVE_EXPLOSION), + LEVEL_UP_MOVE(46, MOVE_GYRO_BALL), + LEVEL_UP_MOVE(50, MOVE_GRASSY_TERRAIN), LEVEL_UP_END }; static const struct LevelUpMove sElectrodeHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_THUNDER_SHOCK), - LEVEL_UP_MOVE( 5, MOVE_TACKLE), - LEVEL_UP_MOVE( 9, MOVE_THUNDER_WAVE), - LEVEL_UP_MOVE(15, MOVE_SPARK), - LEVEL_UP_MOVE(21, MOVE_ENERGY_BALL), - LEVEL_UP_MOVE(29, MOVE_THUNDERBOLT), - LEVEL_UP_MOVE(37, MOVE_THUNDER), - LEVEL_UP_MOVE(47, MOVE_CHLOROBLAST), - LEVEL_UP_MOVE(47, MOVE_SELF_DESTRUCT), + LEVEL_UP_MOVE( 0, MOVE_CHLOROBLAST), + LEVEL_UP_MOVE( 1, MOVE_CHARGE), + LEVEL_UP_MOVE( 1, MOVE_TACKLE), + LEVEL_UP_MOVE( 4, MOVE_THUNDER_SHOCK), + LEVEL_UP_MOVE( 6, MOVE_STUN_SPORE), + LEVEL_UP_MOVE( 9, MOVE_BULLET_SEED), + LEVEL_UP_MOVE(11, MOVE_ROLLOUT), + LEVEL_UP_MOVE(13, MOVE_SCREECH), + LEVEL_UP_MOVE(16, MOVE_CHARGE_BEAM), + LEVEL_UP_MOVE(20, MOVE_SWIFT), + LEVEL_UP_MOVE(22, MOVE_ELECTRO_BALL), + LEVEL_UP_MOVE(26, MOVE_SELF_DESTRUCT), + LEVEL_UP_MOVE(29, MOVE_ENERGY_BALL), + LEVEL_UP_MOVE(34, MOVE_SEED_BOMB), + LEVEL_UP_MOVE(34, MOVE_DISCHARGE), + LEVEL_UP_MOVE(41, MOVE_EXPLOSION), + LEVEL_UP_MOVE(46, MOVE_GYRO_BALL), + LEVEL_UP_MOVE(50, MOVE_GRASSY_TERRAIN), LEVEL_UP_END }; static const struct LevelUpMove sTyphlosionHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 0, MOVE_HEX), - LEVEL_UP_MOVE( 1, MOVE_QUICK_ATTACK), - LEVEL_UP_MOVE( 6, MOVE_EMBER), - LEVEL_UP_MOVE(11, MOVE_ROLLOUT), - LEVEL_UP_MOVE(18, MOVE_FLAME_WHEEL), - LEVEL_UP_MOVE(25, MOVE_SWIFT), - LEVEL_UP_MOVE(34, MOVE_FLAMETHROWER), - LEVEL_UP_MOVE(40, MOVE_INFERNAL_PARADE), - LEVEL_UP_MOVE(43, MOVE_OVERHEAT), - LEVEL_UP_MOVE(43, MOVE_SHADOW_BALL), + LEVEL_UP_MOVE( 0, MOVE_INFERNAL_PARADE), + LEVEL_UP_MOVE( 1, MOVE_GYRO_BALL), + LEVEL_UP_MOVE( 1, MOVE_ERUPTION), + LEVEL_UP_MOVE( 1, MOVE_SMOKESCREEN), + LEVEL_UP_MOVE( 1, MOVE_TACKLE), + LEVEL_UP_MOVE( 1, MOVE_EMBER), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE(13, MOVE_QUICK_ATTACK), + LEVEL_UP_MOVE(20, MOVE_FLAME_WHEEL), + LEVEL_UP_MOVE(24, MOVE_DEFENSE_CURL), + LEVEL_UP_MOVE(31, MOVE_SWIFT), + LEVEL_UP_MOVE(35, MOVE_FLAME_CHARGE), + LEVEL_UP_MOVE(43, MOVE_LAVA_PLUME), + LEVEL_UP_MOVE(48, MOVE_FLAMETHROWER), + LEVEL_UP_MOVE(56, MOVE_INFERNO), + LEVEL_UP_MOVE(61, MOVE_ROLLOUT), + LEVEL_UP_MOVE(74, MOVE_OVERHEAT), LEVEL_UP_END }; static const struct LevelUpMove sQwilfishHisuianLevelUpLearnset[] = { + LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE( 1, MOVE_POISON_STING), - LEVEL_UP_MOVE( 5, MOVE_SPIKES), - LEVEL_UP_MOVE( 9, MOVE_PIN_MISSILE), - LEVEL_UP_MOVE(15, MOVE_BARB_BARRAGE), - LEVEL_UP_MOVE(21, MOVE_WATER_PULSE), - LEVEL_UP_MOVE(26, MOVE_DARK_PULSE), - LEVEL_UP_MOVE(29, MOVE_POISON_JAB), - LEVEL_UP_MOVE(37, MOVE_AQUA_TAIL), - LEVEL_UP_MOVE(47, MOVE_DOUBLE_EDGE), - LEVEL_UP_MOVE(57, MOVE_SELF_DESTRUCT), + LEVEL_UP_MOVE( 4, MOVE_HARDEN), + LEVEL_UP_MOVE( 8, MOVE_BITE), + LEVEL_UP_MOVE(12, MOVE_FELL_STINGER), + LEVEL_UP_MOVE(16, MOVE_MINIMIZE), + LEVEL_UP_MOVE(20, MOVE_SPIKES), + LEVEL_UP_MOVE(24, MOVE_BRINE), + LEVEL_UP_MOVE(28, MOVE_BARB_BARRAGE), + LEVEL_UP_MOVE(32, MOVE_PIN_MISSILE), + LEVEL_UP_MOVE(36, MOVE_TOXIC_SPIKES), + LEVEL_UP_MOVE(40, MOVE_STOCKPILE), + LEVEL_UP_MOVE(40, MOVE_SPIT_UP), + LEVEL_UP_MOVE(44, MOVE_TOXIC), + LEVEL_UP_MOVE(48, MOVE_CRUNCH), + LEVEL_UP_MOVE(52, MOVE_ACUPRESSURE), + LEVEL_UP_MOVE(56, MOVE_DESTINY_BOND), LEVEL_UP_END }; static const struct LevelUpMove sSneaselHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_QUICK_ATTACK), - LEVEL_UP_MOVE( 6, MOVE_ROCK_SMASH), - LEVEL_UP_MOVE(11, MOVE_SWIFT), - LEVEL_UP_MOVE(18, MOVE_SLASH), - LEVEL_UP_MOVE(25, MOVE_POISON_JAB), - LEVEL_UP_MOVE(34, MOVE_SWORDS_DANCE), - LEVEL_UP_MOVE(43, MOVE_CLOSE_COMBAT), + LEVEL_UP_MOVE( 1, MOVE_SCRATCH), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_ROCK_SMASH), + LEVEL_UP_MOVE( 6, MOVE_TAUNT), + LEVEL_UP_MOVE(12, MOVE_QUICK_ATTACK), + LEVEL_UP_MOVE(18, MOVE_METAL_CLAW), + LEVEL_UP_MOVE(24, MOVE_POISON_JAB), + LEVEL_UP_MOVE(30, MOVE_BRICK_BREAK), + LEVEL_UP_MOVE(36, MOVE_HONE_CLAWS), + LEVEL_UP_MOVE(42, MOVE_SLASH), + LEVEL_UP_MOVE(48, MOVE_AGILITY), + LEVEL_UP_MOVE(54, MOVE_SCREECH), + LEVEL_UP_MOVE(60, MOVE_CLOSE_COMBAT), LEVEL_UP_END }; #if P_GEN_5_POKEMON == TRUE static const struct LevelUpMove sSamurottHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 0, MOVE_NIGHT_SLASH), + LEVEL_UP_MOVE( 0, MOVE_CEASELESS_EDGE), + LEVEL_UP_MOVE( 1, MOVE_SLASH), + LEVEL_UP_MOVE( 1, MOVE_SUCKER_PUNCH), + LEVEL_UP_MOVE( 1, MOVE_MEGAHORN), + LEVEL_UP_MOVE( 1, MOVE_TAIL_WHIP), LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 6, MOVE_AQUA_JET), - LEVEL_UP_MOVE(11, MOVE_SWORDS_DANCE), - LEVEL_UP_MOVE(18, MOVE_WATER_PULSE), - LEVEL_UP_MOVE(21, MOVE_CEASELESS_EDGE), - LEVEL_UP_MOVE(25, MOVE_SLASH), - LEVEL_UP_MOVE(34, MOVE_AQUA_TAIL), - LEVEL_UP_MOVE(40, MOVE_DARK_PULSE), - LEVEL_UP_MOVE(43, MOVE_HYDRO_PUMP), + LEVEL_UP_MOVE( 1, MOVE_WATER_GUN), + LEVEL_UP_MOVE(13, MOVE_FOCUS_ENERGY), + LEVEL_UP_MOVE(18, MOVE_RAZOR_SHELL), + LEVEL_UP_MOVE(21, MOVE_FURY_CUTTER), + LEVEL_UP_MOVE(25, MOVE_WATER_PULSE), + LEVEL_UP_MOVE(29, MOVE_AERIAL_ACE), + LEVEL_UP_MOVE(34, MOVE_AQUA_JET), + LEVEL_UP_MOVE(39, MOVE_ENCORE), + LEVEL_UP_MOVE(46, MOVE_AQUA_TAIL), + LEVEL_UP_MOVE(51, MOVE_RETALIATE), + LEVEL_UP_MOVE(58, MOVE_SWORDS_DANCE), + LEVEL_UP_MOVE(63, MOVE_HYDRO_PUMP), LEVEL_UP_END }; static const struct LevelUpMove sLilligantHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 0, MOVE_ROCK_SMASH), + LEVEL_UP_MOVE( 0, MOVE_VICTORY_DANCE), + LEVEL_UP_MOVE( 1, MOVE_TEETER_DANCE), + LEVEL_UP_MOVE( 1, MOVE_SOLAR_BLADE), + LEVEL_UP_MOVE( 1, MOVE_PETAL_BLIZZARD), + LEVEL_UP_MOVE( 1, MOVE_AFTER_YOU), + LEVEL_UP_MOVE( 1, MOVE_ENTRAINMENT), + LEVEL_UP_MOVE( 1, MOVE_LEAF_STORM), + LEVEL_UP_MOVE( 1, MOVE_DEFOG), + LEVEL_UP_MOVE( 1, MOVE_ENERGY_BALL), + LEVEL_UP_MOVE( 1, MOVE_LEAF_BLADE), + LEVEL_UP_MOVE( 1, MOVE_MAGICAL_LEAF), + LEVEL_UP_MOVE( 1, MOVE_MEGA_KICK), + LEVEL_UP_MOVE( 1, MOVE_SUNNY_DAY), + LEVEL_UP_MOVE( 1, MOVE_SYNTHESIS), + LEVEL_UP_MOVE( 1, MOVE_GIGA_DRAIN), + LEVEL_UP_MOVE( 1, MOVE_SLEEP_POWDER), + LEVEL_UP_MOVE( 1, MOVE_STUN_SPORE), + LEVEL_UP_MOVE( 1, MOVE_GROWTH), + LEVEL_UP_MOVE( 1, MOVE_LEECH_SEED), + LEVEL_UP_MOVE( 1, MOVE_MEGA_DRAIN), LEVEL_UP_MOVE( 1, MOVE_ABSORB), - LEVEL_UP_MOVE( 5, MOVE_LEAFAGE), - LEVEL_UP_MOVE( 9, MOVE_STUN_SPORE), - LEVEL_UP_MOVE(15, MOVE_POISON_POWDER), - LEVEL_UP_MOVE(21, MOVE_ENERGY_BALL), - LEVEL_UP_MOVE(29, MOVE_SLEEP_POWDER), - LEVEL_UP_MOVE(34, MOVE_DRAIN_PUNCH), - LEVEL_UP_MOVE(37, MOVE_LEAF_BLADE), - LEVEL_UP_MOVE(37, MOVE_RECOVER), - LEVEL_UP_MOVE(42, MOVE_VICTORY_DANCE), - LEVEL_UP_MOVE(47, MOVE_LEAF_STORM), - LEVEL_UP_MOVE(53, MOVE_PETAL_DANCE), - LEVEL_UP_MOVE(57, MOVE_CLOSE_COMBAT), + LEVEL_UP_MOVE( 1, MOVE_HELPING_HAND), + LEVEL_UP_MOVE( 5, MOVE_AXE_KICK), LEVEL_UP_END }; static const struct LevelUpMove sZoruaHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_SHADOW_SNEAK), - LEVEL_UP_MOVE( 6, MOVE_SNARL), - LEVEL_UP_MOVE(11, MOVE_SWIFT), - LEVEL_UP_MOVE(18, MOVE_BITTER_MALICE), - LEVEL_UP_MOVE(25, MOVE_SLASH), - LEVEL_UP_MOVE(34, MOVE_SHADOW_CLAW), - LEVEL_UP_MOVE(43, MOVE_NASTY_PLOT), + LEVEL_UP_MOVE( 1, MOVE_SCRATCH), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 4, MOVE_TORMENT), + LEVEL_UP_MOVE( 8, MOVE_HONE_CLAWS), + LEVEL_UP_MOVE(12, MOVE_SHADOW_SNEAK), + LEVEL_UP_MOVE(16, MOVE_CURSE), + LEVEL_UP_MOVE(20, MOVE_TAUNT), + LEVEL_UP_MOVE(24, MOVE_KNOCK_OFF), + LEVEL_UP_MOVE(28, MOVE_SPITE), + LEVEL_UP_MOVE(32, MOVE_AGILITY), + LEVEL_UP_MOVE(36, MOVE_SHADOW_BALL), + LEVEL_UP_MOVE(40, MOVE_BITTER_MALICE), + LEVEL_UP_MOVE(44, MOVE_NASTY_PLOT), + LEVEL_UP_MOVE(48, MOVE_FOUL_PLAY), LEVEL_UP_END }; static const struct LevelUpMove sZoroarkHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_SHADOW_SNEAK), - LEVEL_UP_MOVE( 6, MOVE_SNARL), - LEVEL_UP_MOVE(11, MOVE_SWIFT), - LEVEL_UP_MOVE(18, MOVE_BITTER_MALICE), - LEVEL_UP_MOVE(25, MOVE_SLASH), - LEVEL_UP_MOVE(34, MOVE_SHADOW_CLAW), + LEVEL_UP_MOVE( 0, MOVE_SHADOW_CLAW), + LEVEL_UP_MOVE( 1, MOVE_SCRATCH), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_TORMENT), + LEVEL_UP_MOVE( 1, MOVE_U_TURN), + LEVEL_UP_MOVE( 1, MOVE_HONE_CLAWS), + LEVEL_UP_MOVE(12, MOVE_SHADOW_SNEAK), + LEVEL_UP_MOVE(16, MOVE_CURSE), + LEVEL_UP_MOVE(20, MOVE_TAUNT), + LEVEL_UP_MOVE(24, MOVE_KNOCK_OFF), + LEVEL_UP_MOVE(28, MOVE_SPITE), + LEVEL_UP_MOVE(34, MOVE_AGILITY), LEVEL_UP_MOVE(40, MOVE_SHADOW_BALL), - LEVEL_UP_MOVE(43, MOVE_NASTY_PLOT), - LEVEL_UP_MOVE(52, MOVE_EXTRASENSORY), + LEVEL_UP_MOVE(46, MOVE_BITTER_MALICE), + LEVEL_UP_MOVE(52, MOVE_NASTY_PLOT), + LEVEL_UP_MOVE(58, MOVE_FOUL_PLAY), LEVEL_UP_END }; static const struct LevelUpMove sBraviaryHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_QUICK_ATTACK), - LEVEL_UP_MOVE( 6, MOVE_AERIAL_ACE), - LEVEL_UP_MOVE(11, MOVE_TWISTER), - LEVEL_UP_MOVE(18, MOVE_SLASH), - LEVEL_UP_MOVE(20, MOVE_AIR_SLASH), - LEVEL_UP_MOVE(25, MOVE_ESPER_WING), - LEVEL_UP_MOVE(25, MOVE_ROOST), - LEVEL_UP_MOVE(34, MOVE_DOUBLE_EDGE), - LEVEL_UP_MOVE(43, MOVE_BRAVE_BIRD), - LEVEL_UP_MOVE(52, MOVE_HURRICANE), + LEVEL_UP_MOVE( 0, MOVE_ESPER_WING), + LEVEL_UP_MOVE( 1, MOVE_HONE_CLAWS), + LEVEL_UP_MOVE( 1, MOVE_SKY_ATTACK), + LEVEL_UP_MOVE( 1, MOVE_PECK), + LEVEL_UP_MOVE( 1, MOVE_SUPERPOWER), + LEVEL_UP_MOVE( 1, MOVE_LEER), + LEVEL_UP_MOVE( 1, MOVE_WING_ATTACK), + LEVEL_UP_MOVE(18, MOVE_TAILWIND), + LEVEL_UP_MOVE(24, MOVE_SCARY_FACE), + LEVEL_UP_MOVE(30, MOVE_AERIAL_ACE), + LEVEL_UP_MOVE(36, MOVE_SLASH), + LEVEL_UP_MOVE(42, MOVE_WHIRLWIND), + LEVEL_UP_MOVE(48, MOVE_CRUSH_CLAW), + LEVEL_UP_MOVE(57, MOVE_AIR_SLASH), + LEVEL_UP_MOVE(64, MOVE_DEFOG), + LEVEL_UP_MOVE(72, MOVE_THRASH), + LEVEL_UP_MOVE(80, MOVE_HURRICANE), LEVEL_UP_END }; #endif #if P_GEN_6_POKEMON == TRUE static const struct LevelUpMove sSliggooHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_BUBBLE), - LEVEL_UP_MOVE( 6, MOVE_ACID_SPRAY), - LEVEL_UP_MOVE(11, MOVE_ACID_ARMOR), - LEVEL_UP_MOVE(18, MOVE_WATER_PULSE), - LEVEL_UP_MOVE(25, MOVE_DRAGON_PULSE), - LEVEL_UP_MOVE(25, MOVE_IRON_HEAD), - LEVEL_UP_MOVE(34, MOVE_SHELTER), - LEVEL_UP_MOVE(43, MOVE_HYDRO_PUMP), + LEVEL_UP_MOVE( 0, MOVE_SHELTER), + LEVEL_UP_MOVE( 1, MOVE_TACKLE), + LEVEL_UP_MOVE( 1, MOVE_WATER_GUN), + LEVEL_UP_MOVE( 1, MOVE_ABSORB), + LEVEL_UP_MOVE( 1, MOVE_ACID_ARMOR), + LEVEL_UP_MOVE( 1, MOVE_DRAGON_BREATH), + LEVEL_UP_MOVE(15, MOVE_PROTECT), + LEVEL_UP_MOVE(20, MOVE_FLAIL), + LEVEL_UP_MOVE(25, MOVE_WATER_PULSE), + LEVEL_UP_MOVE(30, MOVE_RAIN_DANCE), + LEVEL_UP_MOVE(35, MOVE_DRAGON_PULSE), + LEVEL_UP_MOVE(43, MOVE_CURSE), + LEVEL_UP_MOVE(49, MOVE_IRON_HEAD), + LEVEL_UP_MOVE(56, MOVE_MUDDY_WATER), LEVEL_UP_END }; static const struct LevelUpMove sGoodraHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_BUBBLE), - LEVEL_UP_MOVE( 6, MOVE_ACID_SPRAY), - LEVEL_UP_MOVE(11, MOVE_ACID_ARMOR), - LEVEL_UP_MOVE(18, MOVE_WATER_PULSE), - LEVEL_UP_MOVE(25, MOVE_DRAGON_PULSE), - LEVEL_UP_MOVE(25, MOVE_IRON_HEAD), - LEVEL_UP_MOVE(34, MOVE_SHELTER), - LEVEL_UP_MOVE(43, MOVE_HYDRO_PUMP), + LEVEL_UP_MOVE( 0, MOVE_IRON_TAIL), + LEVEL_UP_MOVE( 1, MOVE_SHELTER), + LEVEL_UP_MOVE( 1, MOVE_ACID_SPRAY), + LEVEL_UP_MOVE( 1, MOVE_FEINT), + LEVEL_UP_MOVE( 1, MOVE_TEARFUL_LOOK), + LEVEL_UP_MOVE( 1, MOVE_DRAGON_BREATH), + LEVEL_UP_MOVE( 1, MOVE_TACKLE), + LEVEL_UP_MOVE( 1, MOVE_ABSORB), + LEVEL_UP_MOVE( 1, MOVE_WATER_GUN), + LEVEL_UP_MOVE(15, MOVE_PROTECT), + LEVEL_UP_MOVE(20, MOVE_FLAIL), + LEVEL_UP_MOVE(25, MOVE_WATER_PULSE), + LEVEL_UP_MOVE(30, MOVE_RAIN_DANCE), + LEVEL_UP_MOVE(35, MOVE_DRAGON_PULSE), + LEVEL_UP_MOVE(43, MOVE_CURSE), + LEVEL_UP_MOVE(49, MOVE_IRON_HEAD), + LEVEL_UP_MOVE(49, MOVE_BODY_SLAM), + LEVEL_UP_MOVE(58, MOVE_MUDDY_WATER), + LEVEL_UP_MOVE(67, MOVE_HEAVY_SLAM), LEVEL_UP_END }; static const struct LevelUpMove sAvaluggHisuianLevelUpLearnset[] = { LEVEL_UP_MOVE( 0, MOVE_ROCK_SLIDE), + LEVEL_UP_MOVE( 1, MOVE_POWDER_SNOW), + LEVEL_UP_MOVE( 1, MOVE_RAPID_SPIN), + LEVEL_UP_MOVE( 1, MOVE_WIDE_GUARD), + LEVEL_UP_MOVE( 1, MOVE_HARDEN), LEVEL_UP_MOVE( 1, MOVE_TACKLE), - LEVEL_UP_MOVE( 5, MOVE_POWDER_SNOW), - LEVEL_UP_MOVE( 9, MOVE_ICE_SHARD), - LEVEL_UP_MOVE(15, MOVE_BITE), - LEVEL_UP_MOVE(21, MOVE_IRON_DEFENSE), - LEVEL_UP_MOVE(29, MOVE_CRUNCH), - LEVEL_UP_MOVE(29, MOVE_EARTH_POWER), - LEVEL_UP_MOVE(37, MOVE_BLIZZARD), - LEVEL_UP_MOVE(37, MOVE_MOUNTAIN_GALE), - LEVEL_UP_MOVE(47, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE( 9, MOVE_CURSE), + LEVEL_UP_MOVE(12, MOVE_ICY_WIND), + LEVEL_UP_MOVE(15, MOVE_PROTECT), + LEVEL_UP_MOVE(18, MOVE_AVALANCHE), + LEVEL_UP_MOVE(21, MOVE_BITE), + LEVEL_UP_MOVE(24, MOVE_ICE_FANG), + LEVEL_UP_MOVE(27, MOVE_IRON_DEFENSE), + LEVEL_UP_MOVE(30, MOVE_RECOVER), + LEVEL_UP_MOVE(33, MOVE_CRUNCH), + LEVEL_UP_MOVE(36, MOVE_TAKE_DOWN), + LEVEL_UP_MOVE(41, MOVE_BLIZZARD), + LEVEL_UP_MOVE(46, MOVE_DOUBLE_EDGE), + LEVEL_UP_MOVE(51, MOVE_STONE_EDGE), + LEVEL_UP_MOVE(61, MOVE_MOUNTAIN_GALE), LEVEL_UP_END }; #endif #if P_GEN_7_POKEMON == TRUE static const struct LevelUpMove sDecidueyeHisuianLevelUpLearnset[] = { - LEVEL_UP_MOVE( 0, MOVE_ROCK_SMASH), - LEVEL_UP_MOVE( 1, MOVE_GUST), - LEVEL_UP_MOVE( 6, MOVE_LEAFAGE), - LEVEL_UP_MOVE(11, MOVE_ROOST), - LEVEL_UP_MOVE(18, MOVE_AERIAL_ACE), - LEVEL_UP_MOVE(21, MOVE_MAGICAL_LEAF), - LEVEL_UP_MOVE(25, MOVE_AIR_SLASH), - LEVEL_UP_MOVE(30, MOVE_AURA_SPHERE), - LEVEL_UP_MOVE(34, MOVE_LEAF_BLADE), - LEVEL_UP_MOVE(34, MOVE_TRIPLE_ARROWS), - LEVEL_UP_MOVE(40, MOVE_BRAVE_BIRD), - LEVEL_UP_MOVE(43, MOVE_LEAF_STORM), + LEVEL_UP_MOVE( 0, MOVE_TRIPLE_ARROWS), + LEVEL_UP_MOVE( 1, MOVE_TACKLE), + LEVEL_UP_MOVE( 1, MOVE_GROWL), + LEVEL_UP_MOVE( 1, MOVE_U_TURN), + LEVEL_UP_MOVE( 1, MOVE_LEAF_STORM), + LEVEL_UP_MOVE( 1, MOVE_LEAFAGE), + LEVEL_UP_MOVE( 9, MOVE_PECK), + LEVEL_UP_MOVE(12, MOVE_SHADOW_SNEAK), + LEVEL_UP_MOVE(15, MOVE_RAZOR_LEAF), + LEVEL_UP_MOVE(20, MOVE_SYNTHESIS), + LEVEL_UP_MOVE(25, MOVE_PLUCK), + LEVEL_UP_MOVE(30, MOVE_BULK_UP), + LEVEL_UP_MOVE(37, MOVE_SUCKER_PUNCH), + LEVEL_UP_MOVE(44, MOVE_LEAF_BLADE), + LEVEL_UP_MOVE(51, MOVE_FEATHER_DANCE), + LEVEL_UP_MOVE(58, MOVE_BRAVE_BIRD), LEVEL_UP_END }; #endif diff --git a/src/data/pokemon/species_info.h b/src/data/pokemon/species_info.h index ad4822ba47..7d1d108631 100644 --- a/src/data/pokemon/species_info.h +++ b/src/data/pokemon/species_info.h @@ -13902,7 +13902,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 80, .baseSpDefense = 55, .types = { TYPE_WATER, TYPE_WATER}, - .catchRate = 25, + .catchRate = 190, .expYield = 161, .evYield_Speed = 2, .itemRare = ITEM_DEEP_SEA_TOOTH, @@ -19467,7 +19467,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .noFlip = FALSE, }, - [SPECIES_RILLABOOM] = + [SPECIES_RILLABOOM] = { RILLABOOM_MISC_INFO, }, @@ -20996,8 +20996,9 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpDefense = 75, .types = { TYPE_NORMAL, TYPE_PSYCHIC}, .catchRate = 45, - .expYield = 184, + .expYield = 263, .evYield_Attack = 1, + .evYield_SpAttack = 1, .genderRatio = PERCENT_FEMALE(50), .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, @@ -21017,11 +21018,11 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 45, .baseSpDefense = 70, .types = { TYPE_BUG, TYPE_ROCK}, - .catchRate = 25, + .catchRate = 15, .expYield = 175, - .evYield_Attack = 2, + .evYield_Attack = 3, .genderRatio = PERCENT_FEMALE(50), - .eggCycles = 25, + .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, .eggGroups = { EGG_GROUP_BUG, EGG_GROUP_BUG}, @@ -21039,8 +21040,8 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 45, .baseSpDefense = 80, .types = { TYPE_GROUND, TYPE_NORMAL}, - .catchRate = 75, - .expYield = 194, + .catchRate = 20, + .expYield = 275, .evYield_Attack = 3, .genderRatio = PERCENT_FEMALE(50), .eggCycles = 20, @@ -21061,15 +21062,15 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 80, .baseSpDefense = 75, .types = { TYPE_WATER, TYPE_GHOST}, - .catchRate = 25, - .expYield = 186, - .evYield_HP = 2, + .catchRate = 45, + .expYield = 265, + .evYield_HP = 3, .genderRatio = MON_MALE, - .eggCycles = 40, + .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, .eggGroups = { EGG_GROUP_WATER_2, EGG_GROUP_WATER_2}, - .abilities = {ABILITY_RATTLED, ABILITY_ADAPTABILITY, ABILITY_MOLD_BREAKER}, + .abilities = {ABILITY_SWIFT_SWIM, ABILITY_ADAPTABILITY, ABILITY_MOLD_BREAKER}, .bodyColor = BODY_COLOR_GREEN, .noFlip = FALSE, }, @@ -21083,15 +21084,15 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 100, .baseSpDefense = 75, .types = { TYPE_WATER, TYPE_GHOST}, - .catchRate = 25, - .expYield = 186, - .evYield_HP = 2, + .catchRate = 45, + .expYield = 265, + .evYield_HP = 3, .genderRatio = MON_FEMALE, - .eggCycles = 40, + .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, .eggGroups = { EGG_GROUP_WATER_2, EGG_GROUP_WATER_2}, - .abilities = {ABILITY_RATTLED, ABILITY_ADAPTABILITY, ABILITY_MOLD_BREAKER}, + .abilities = {ABILITY_SWIFT_SWIM, ABILITY_ADAPTABILITY, ABILITY_MOLD_BREAKER}, .bodyColor = BODY_COLOR_GREEN, .noFlip = FALSE, }, @@ -21105,13 +21106,12 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 40, .baseSpDefense = 80, .types = { TYPE_FIGHTING, TYPE_POISON}, - .catchRate = 135, - .expYield = 179, - .evYield_Attack = 1, - .evYield_Speed = 1, + .catchRate = 20, + .expYield = 102, + .evYield_Attack = 2, .genderRatio = PERCENT_FEMALE(50), .eggCycles = 20, - .friendship = 35, + .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_SLOW, .eggGroups = { EGG_GROUP_FIELD, EGG_GROUP_FIELD}, .abilities = {ABILITY_PRESSURE, ABILITY_UNBURDEN, ABILITY_POISON_TOUCH}, @@ -21128,9 +21128,9 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 65, .baseSpDefense = 65, .types = { TYPE_DARK, TYPE_POISON}, - .catchRate = 135, - .expYield = 180, - .evYield_Attack = 1, + .catchRate = 45, + .expYield = 179, + .evYield_Attack = 2, .genderRatio = PERCENT_FEMALE(50), .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, @@ -21151,14 +21151,14 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpDefense = 80, .types = { TYPE_FAIRY, TYPE_FLYING}, .catchRate = 3, - .expYield = 261, + .expYield = 116, .evYield_SpAttack = 3, .genderRatio = MON_FEMALE, - .eggCycles = 120, - .friendship = 90, + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_SLOW, .eggGroups = { EGG_GROUP_UNDISCOVERED, EGG_GROUP_UNDISCOVERED}, - .abilities = {ABILITY_HEALER, ABILITY_NONE, ABILITY_CONTRARY}, + .abilities = {ABILITY_CUTE_CHARM, ABILITY_NONE, ABILITY_CONTRARY}, .bodyColor = BODY_COLOR_PINK, .noFlip = FALSE, .flags = SPECIES_FLAG_LEGENDARY, @@ -23348,7 +23348,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .growthRate = GROWTH_MEDIUM_FAST, .eggGroups = { EGG_GROUP_WATER_2, EGG_GROUP_WATER_2}, .abilities = {ABILITY_POISON_POINT, ABILITY_SWIFT_SWIM, ABILITY_INTIMIDATE}, - .bodyColor = BODY_COLOR_GRAY, + .bodyColor = BODY_COLOR_BLACK, .noFlip = FALSE, .flags = SPECIES_FLAG_HISUIAN_FORM, }, @@ -23372,7 +23372,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .growthRate = GROWTH_MEDIUM_SLOW, .eggGroups = { EGG_GROUP_FIELD, EGG_GROUP_FIELD}, .abilities = {ABILITY_INNER_FOCUS, ABILITY_KEEN_EYE, ABILITY_PICKPOCKET}, - .bodyColor = BODY_COLOR_BLACK, + .bodyColor = BODY_COLOR_GRAY, .noFlip = TRUE, .flags = SPECIES_FLAG_HISUIAN_FORM, }, @@ -23389,7 +23389,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .types = { TYPE_WATER, TYPE_DARK}, .catchRate = 45, .expYield = 238, - .evYield_SpAttack = 3, + .evYield_Attack = 3, .genderRatio = PERCENT_FEMALE(12.5), .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, @@ -23412,7 +23412,8 @@ const struct SpeciesInfo gSpeciesInfo[] = .types = { TYPE_GRASS, TYPE_FIGHTING}, .catchRate = 75, .expYield = 168, - .evYield_Attack = 2, + .evYield_Attack = 1, + .evYield_Speed = 1, .itemRare = ITEM_ABSORB_BULB, .genderRatio = MON_FEMALE, .eggCycles = 20, @@ -23894,7 +23895,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 80, .baseSpDefense = 55, .types = { TYPE_WATER, TYPE_WATER}, - .catchRate = 25, + .catchRate = 190, .expYield = 161, .evYield_Speed = 2, .itemRare = ITEM_DEEP_SEA_SCALE, @@ -23917,7 +23918,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpAttack = 80, .baseSpDefense = 55, .types = { TYPE_WATER, TYPE_WATER}, - .catchRate = 25, + .catchRate = 190, .expYield = 161, .evYield_Speed = 2, .itemRare = ITEM_DEEP_SEA_SCALE, @@ -24822,11 +24823,11 @@ const struct SpeciesInfo gSpeciesInfo[] = .baseSpDefense = 100, .types = { TYPE_FAIRY, TYPE_FLYING}, .catchRate = 3, - .expYield = 270, + .expYield = 116, .evYield_SpAttack = 3, .genderRatio = MON_FEMALE, - .eggCycles = 120, - .friendship = 90, + .eggCycles = 20, + .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_SLOW, .eggGroups = { EGG_GROUP_UNDISCOVERED, EGG_GROUP_UNDISCOVERED}, .abilities = {ABILITY_OVERCOAT, ABILITY_NONE},