diff --git a/.gitignore b/.gitignore index 5f9172181d..301fc8ca29 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ prefabs.json /pokeemerald-*.png src/data/map_group_count.h tools/trainerproc/trainerproc +*.Identifier +*.smol +*.fastSmol +*.smolTM diff --git a/src/battle_main.c b/src/battle_main.c index 7919329ee5..3d3c70b37b 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -6015,9 +6015,17 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost) break; } - if (moveType == TYPE_NORMAL - && ((!gMain.inBattle || TrySetAteType(move, battler, ability)) - && GetActiveGimmick(battler) != GIMMICK_DYNAMAX)) + if (IsSoundMove(move) && ability == ABILITY_LIQUID_VOICE) + { + return TYPE_WATER; + } + else if (moveEffect == EFFECT_AURA_WHEEL && species == SPECIES_MORPEKO_HANGRY) + { + return TYPE_DARK; + } + else if (moveType == TYPE_NORMAL + && ((!gMain.inBattle || TrySetAteType(move, battler, ability)) + && GetActiveGimmick(battler) != GIMMICK_DYNAMAX)) { if (gMain.inBattle && ateBoost != NULL) *ateBoost = TRUE; @@ -6032,14 +6040,6 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost) *ateBoost = TRUE; return TYPE_NORMAL; } - else if (IsSoundMove(move) && ability == ABILITY_LIQUID_VOICE) - { - return TYPE_WATER; - } - else if (moveEffect == EFFECT_AURA_WHEEL && species == SPECIES_MORPEKO_HANGRY) - { - return TYPE_DARK; - } return TYPE_NONE; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b9d07b9946..2faa37564d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6999,7 +6999,7 @@ static void Cmd_moveend(void) gBattleStruct->pledgeMove = FALSE; if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE); - if (B_CHARGE <= GEN_8 || moveType == TYPE_ELECTRIC) + if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || !MoveResultHasEffect(gBattlerTarget))) gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP); memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); ClearDamageCalcResults(); diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h index a7239d1c32..6dbc8de104 100644 --- a/src/data/pokemon/species_info/gen_8_families.h +++ b/src/data/pokemon/species_info/gen_8_families.h @@ -7819,6 +7819,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .levelUpLearnset = sEnamorusLevelUpLearnset, .teachableLearnset = sEnamorusTeachableLearnset, .formSpeciesIdTable = sEnamorusFormSpeciesIdTable, + .formChangeTable = sEnamorusFormChangeTable, }, [SPECIES_ENAMORUS_THERIAN] = @@ -7884,6 +7885,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .levelUpLearnset = sEnamorusLevelUpLearnset, .teachableLearnset = sEnamorusTeachableLearnset, .formSpeciesIdTable = sEnamorusFormSpeciesIdTable, + .formChangeTable = sEnamorusFormChangeTable, }, #endif //P_FAMILY_ENAMORUS diff --git a/src/shop.c b/src/shop.c index dae2ea86ff..2ec414ed42 100644 --- a/src/shop.c +++ b/src/shop.c @@ -1067,7 +1067,11 @@ static void Task_BuyHowManyDialogueInit(u8 taskId) BuyMenuPrintItemQuantityAndPrice(taskId); ScheduleBgCopyTilemapToVram(0); - maxQuantity = GetMoney(&gSaveBlock1Ptr->money) / sShopData->totalCost; + // Avoid division by zero in-case something costs 0 pokedollars. + if (sShopData->totalCost == 0) + maxQuantity = MAX_BAG_ITEM_CAPACITY; + else + maxQuantity = GetMoney(&gSaveBlock1Ptr->money) / sShopData->totalCost; if (maxQuantity > MAX_BAG_ITEM_CAPACITY) sShopData->maxQuantity = MAX_BAG_ITEM_CAPACITY; diff --git a/test/battle/ability/liquid_voice.c b/test/battle/ability/liquid_voice.c new file mode 100644 index 0000000000..79fec2f2a6 --- /dev/null +++ b/test/battle/ability/liquid_voice.c @@ -0,0 +1,21 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_HYPER_VOICE].type == TYPE_NORMAL); + ASSUME(gMovesInfo[MOVE_HYPER_VOICE].power > 0); +} + +SINGLE_BATTLE_TEST("Liquid voice turns a sound move into a Water-type move") +{ + GIVEN { + PLAYER(SPECIES_TYPHLOSION); + OPPONENT(SPECIES_PRIMARINA) { Ability(ABILITY_LIQUID_VOICE); } + } WHEN { + TURN { MOVE(opponent, MOVE_HYPER_VOICE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, opponent); + MESSAGE("It's super effective!"); + } +} diff --git a/test/battle/move_effect/charge.c b/test/battle/move_effect/charge.c index bd84a9b4e2..dfbbc82283 100644 --- a/test/battle/move_effect/charge.c +++ b/test/battle/move_effect/charge.c @@ -9,9 +9,7 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Charge doubles the damage of the next Electric move of the user") { - s16 normalDamage = 0; - s16 chargedUpDamage = 0; - + s16 damage[2] = {0}; GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -21,20 +19,18 @@ SINGLE_BATTLE_TEST("Charge doubles the damage of the next Electric move of the u TURN { MOVE(player, MOVE_THUNDERBOLT); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &normalDamage); + HP_BAR(opponent, captureDamage: &damage[0]); ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &chargedUpDamage); + HP_BAR(opponent, captureDamage: &damage[1]); } THEN { - EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage); + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); } } SINGLE_BATTLE_TEST("Charge's effect is kept until the user uses an Electric move (Gen 9+)") { - s16 normalDamage = 0; - s16 chargedUpDamage = 0; - + s16 damage[2] = {0}; GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -45,20 +41,19 @@ SINGLE_BATTLE_TEST("Charge's effect is kept until the user uses an Electric move TURN { MOVE(player, MOVE_THUNDERBOLT); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &normalDamage); + HP_BAR(opponent, captureDamage: &damage[0]); ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &chargedUpDamage); + HP_BAR(opponent, captureDamage: &damage[1]); } THEN { - EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage); + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); } } SINGLE_BATTLE_TEST("Charge's effect is removed if the user fails using an Electric move (Gen 9+)") { s16 damage[2]; - GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -81,8 +76,7 @@ SINGLE_BATTLE_TEST("Charge's effect is removed if the user fails using an Electr SINGLE_BATTLE_TEST("Charge's effect does not stack with Electromorphosis or Wind Power") { u32 species, ability; - s16 normalDamage = 0; - s16 chargedUpDamage = 0; + s16 damage[2]; PARAMETRIZE { species = SPECIES_WATTREL; ability = ABILITY_WIND_POWER; } PARAMETRIZE { species = SPECIES_TADBULB; ability = ABILITY_ELECTROMORPHOSIS; } @@ -97,22 +91,20 @@ SINGLE_BATTLE_TEST("Charge's effect does not stack with Electromorphosis or Wind TURN { MOVE(player, MOVE_THUNDERBOLT); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &normalDamage); + HP_BAR(opponent, captureDamage: &damage[0]); ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_AIR_CUTTER, opponent); ABILITY_POPUP(player, ability); ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &chargedUpDamage); + HP_BAR(opponent, captureDamage: &damage[1]); } THEN { - EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage); + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); } } SINGLE_BATTLE_TEST("Charge's effect is removed regardless if the next move is Electric or not (Gen 3-8)") { - s16 normalDamage = 0; - s16 chargedUpDamage = 0; - + s16 damage[2]; GIVEN { ASSUME(GetMoveType(MOVE_TACKLE) != TYPE_ELECTRIC); ASSUME(!IsBattleMoveStatus(MOVE_TACKLE)); @@ -125,26 +117,25 @@ SINGLE_BATTLE_TEST("Charge's effect is removed regardless if the next move is El TURN { MOVE(player, MOVE_THUNDERBOLT); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &normalDamage); + HP_BAR(opponent, captureDamage: &damage[0]); ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &chargedUpDamage); + HP_BAR(opponent, captureDamage: &damage[1]); } THEN { if (B_CHARGE < GEN_9) - EXPECT_EQ(normalDamage, chargedUpDamage); + EXPECT_EQ(damage[0], damage[1]); else - EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage); + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); } } SINGLE_BATTLE_TEST("Charge will not expire if it flinches twice in a row") { - s16 normalDamage = 0; - s16 chargedUpDamage = 0; - + s16 damage[2]; GIVEN { - PLAYER(SPECIES_WOBBUFFET); + ASSUME(gMovesInfo[MOVE_IRON_HEAD].additionalEffects[0].moveEffect == MOVE_EFFECT_FLINCH); + PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); } } WHEN { TURN { MOVE(player, MOVE_THUNDERBOLT); } @@ -154,14 +145,14 @@ SINGLE_BATTLE_TEST("Charge will not expire if it flinches twice in a row") TURN { MOVE(player, MOVE_THUNDERBOLT); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &normalDamage); + HP_BAR(opponent, captureDamage: &damage[0]); ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARGE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); - HP_BAR(opponent, captureDamage: &chargedUpDamage); + HP_BAR(opponent, captureDamage: &damage[1]); } THEN { if (B_CHARGE < GEN_9) - EXPECT_EQ(normalDamage, chargedUpDamage); + EXPECT_EQ(damage[0], damage[1]); else - EXPECT_MUL_EQ(normalDamage, Q_4_12(2.0), chargedUpDamage); + EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]); } }