diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f4ef3b8274ce..eb84d295fe00 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8198,15 +8198,12 @@ BattleScript_FlashFireBoost:: goto BattleScript_MoveEnd BattleScript_AbilityPreventsPhasingOut:: - pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUp - printstring STRINGID_PKMNANCHORSITSELFWITH - waitmessage B_WAIT_TIME_LONG + call BattleScript_AbilityPreventsPhasingOutRet goto BattleScript_MoveEnd BattleScript_AbilityPreventsPhasingOutRet:: pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpTarget printstring STRINGID_PKMNANCHORSITSELFWITH waitmessage B_WAIT_TIME_LONG return diff --git a/include/constants/regions.h b/include/constants/regions.h new file mode 100644 index 000000000000..3f7397ced6d5 --- /dev/null +++ b/include/constants/regions.h @@ -0,0 +1,21 @@ +#ifndef GUARD_CONSTANTS_REGIONS_H +#define GUARD_CONSTANTS_REGIONS_H + +// Core-series regions +enum Region +{ + REGION_NONE, + REGION_KANTO, + REGION_JOHTO, + REGION_HOENN, + REGION_SINNOH, + REGION_UNOVA, + REGION_KALOS, + REGION_ALOLA, + REGION_GALAR, + REGION_HISUI, + REGION_PALDEA, + REGIONS_COUNT, +}; + +#endif // GUARD_CONSTANTS_REGIONS_H diff --git a/include/daycare.h b/include/daycare.h index a7ef5581f91f..3023c87af008 100644 --- a/include/daycare.h +++ b/include/daycare.h @@ -34,6 +34,7 @@ void ShowDaycareLevelMenu(void); void ChooseSendDaycareMon(void); u8 GetEggMovesBySpecies(u16 species, u16 *eggMoves); bool8 SpeciesCanLearnEggMove(u16 species, u16 move); +void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon); u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves); #endif // GUARD_DAYCARE_H diff --git a/include/pokemon.h b/include/pokemon.h index bc92b73c7564..1326e8132952 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -3,6 +3,7 @@ #include "sprite.h" #include "constants/items.h" +#include "constants/regions.h" #include "constants/region_map_sections.h" #include "constants/map_groups.h" #include "contest_effect.h" @@ -806,5 +807,7 @@ void UpdateDaysPassedSinceFormChange(u16 days); void TrySetDayLimitToFormChange(struct Pokemon *mon); u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler); uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier); +u32 GetRegionalFormByRegion(u32 species, u32 region); +bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion); #endif // GUARD_POKEMON_H diff --git a/include/regions.h b/include/regions.h new file mode 100644 index 000000000000..2f44896ea2b0 --- /dev/null +++ b/include/regions.h @@ -0,0 +1,12 @@ +#ifndef GUARD_REGIONS_H +#define GUARD_REGIONS_H + +#include "constants/regions.h" + +static inline u32 GetCurrentRegion(void) +{ + // TODO: Since there's no current multi-region support, we have this constant for the purposes of regional form comparisons. + return REGION_HOENN; +} + +#endif // GUARD_REGIONS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f5af50f450b2..7ab4b181ddad 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6792,8 +6792,7 @@ static void Cmd_moveend(void) if (redCardBattlers && (moveEffect != EFFECT_HIT_SWITCH_TARGET || gBattleStruct->hitSwitchTargetFailed) && IsBattlerAlive(gBattlerAttacker) - && !TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_GUARD_DOG) + && !TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) { // Since we check if battler was damaged, we don't need to check move result. // In fact, doing so actually prevents multi-target moves from activating red card properly @@ -6818,7 +6817,8 @@ static void Cmd_moveend(void) if (moveEffect == EFFECT_HIT_ESCAPE) gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection BattleScriptPushCursor(); - if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE) + if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE + || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG) { gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; } @@ -6972,7 +6972,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_SAME_MOVE_TURNS: - if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) gBattleStruct->sameMoveTurns[gBattlerAttacker]++; diff --git a/src/battle_util.c b/src/battle_util.c index 7525bc6250cb..f43e77a1f6db 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1229,7 +1229,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move) } // Dynamax bypasses all selection prevention except Taunt and Assault Vest. -#define DYNAMAX_BYPASS_CHECK (!IsGimmickSelected(gBattlerAttacker, GIMMICK_DYNAMAX) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_DYNAMAX) +#define DYNAMAX_BYPASS_CHECK (!IsGimmickSelected(battler, GIMMICK_DYNAMAX) && GetActiveGimmick(battler) != GIMMICK_DYNAMAX) u32 TrySetCantSelectMoveBattleScript(u32 battler) { @@ -1240,7 +1240,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) u16 *choicedMove = &gBattleStruct->choicedMove[battler]; u32 moveEffect = GetMoveEffect(move); - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].disabledMove == move && move != MOVE_NONE) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].disabledMove == move && move != MOVE_NONE) { gBattleScripting.battler = battler; gCurrentMove = move; @@ -1256,7 +1256,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT)) { CancelMultiTurnMoves(battler); if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1271,9 +1271,9 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].tauntTimer != 0 && IsBattleMoveStatus(move)) + if (GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].tauntTimer != 0 && IsBattleMoveStatus(move)) { - if ((GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX)) + if ((GetActiveGimmick(battler) == GIMMICK_DYNAMAX)) gCurrentMove = MOVE_MAX_GUARD; else gCurrentMove = move; @@ -1289,7 +1289,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer != 0 && IsSoundMove(move)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer != 0 && IsSoundMove(move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1304,7 +1304,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(battler, move)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(battler, move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1319,7 +1319,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsGravityPreventingMove(move)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && IsGravityPreventingMove(move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1334,7 +1334,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsHealBlockPreventingMove(battler, move)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && IsHealBlockPreventingMove(battler, move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1349,7 +1349,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsBelchPreventingMove(battler, move)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && IsBelchPreventingMove(battler, move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1413,7 +1413,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && IsBattleMoveStatus(move) && moveEffect != EFFECT_ME_FIRST) { - if ((GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX)) + if ((GetActiveGimmick(battler) == GIMMICK_DYNAMAX)) gCurrentMove = MOVE_MAX_GUARD; else gCurrentMove = move; @@ -4828,6 +4828,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_UNNERVE: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerAtPosition(battler))); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_UNNERVE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); @@ -4838,6 +4839,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_AS_ONE_SHADOW_RIDER: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerAtPosition(battler))); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_ASONE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_ActivateAsOne); @@ -8791,7 +8793,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) else if (gProtectStructs[battlerDef].protected) isProtected = TRUE; else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_WIDE_GUARD - && GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + && GetBattlerMoveTargetType(battlerAtk, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) isProtected = TRUE; else if (gProtectStructs[battlerDef].banefulBunkered) isProtected = TRUE; @@ -8806,7 +8808,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) else if (gProtectStructs[battlerDef].maxGuarded) isProtected = TRUE; else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_QUICK_GUARD - && GetChosenMovePriority(gBattlerAttacker) > 0) + && GetChosenMovePriority(battlerAtk) > 0) isProtected = TRUE; else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MAT_BLOCK && !IsBattleMoveStatus(move)) @@ -10564,7 +10566,7 @@ static inline bool32 IsFutureSightAttackerInParty(struct DamageCalculationData * if (GetMoveEffect(damageCalcData->move) != EFFECT_FUTURE_SIGHT) return FALSE; - struct Pokemon *party = GetSideParty(GetBattlerSide(gBattlerAttacker)); + struct Pokemon *party = GetSideParty(GetBattlerSide(damageCalcData->battlerAtk)); return &party[gWishFutureKnock.futureSightPartyIndex[damageCalcData->battlerDef]] != &party[gBattlerPartyIndexes[damageCalcData->battlerAtk]]; } @@ -11258,7 +11260,7 @@ bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId) else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) return FALSE; else if (holdEffect == HOLD_EFFECT_BOOSTER_ENERGY - && (gSpeciesInfo[gBattleMons[gBattlerAttacker].species].isParadox || gSpeciesInfo[gBattleMons[gBattlerTarget].species].isParadox)) + && (gSpeciesInfo[gBattleMons[battler].species].isParadox || gSpeciesInfo[gBattleMons[gBattlerTarget].species].isParadox)) return FALSE; else return TRUE; diff --git a/src/daycare.c b/src/daycare.c index 4e69dd9012a2..8d2bf135456a 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -21,6 +21,7 @@ #include "list_menu.h" #include "overworld.h" #include "item.h" +#include "regions.h" #include "constants/form_change_types.h" #include "constants/items.h" #include "constants/hold_effects.h" @@ -243,7 +244,7 @@ static void TransferEggMoves(void) } } -static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon) +void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon) { if (MonHasMail(mon)) { @@ -986,9 +987,12 @@ STATIC_ASSERT(P_SCATTERBUG_LINE_FORM_BREED == SPECIES_SCATTERBUG_ICY_SNOW || (P_ static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parentSlots) { - u16 i; - u16 species[DAYCARE_MON_COUNT]; - u16 eggSpecies; + u32 i; + u32 species[DAYCARE_MON_COUNT]; + u32 eggSpecies, parentSpecies; + bool32 hasMotherEverstone, hasFatherEverstone, motherIsForeign, fatherIsForeign; + bool32 motherEggSpecies, fatherEggSpecies; + u32 currentRegion = GetCurrentRegion(); for (i = 0; i < DAYCARE_MON_COUNT; i++) { @@ -1005,7 +1009,24 @@ static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parent } } - eggSpecies = GetEggSpecies(species[parentSlots[0]]); + motherEggSpecies = GetEggSpecies(species[parentSlots[0]]); + fatherEggSpecies = GetEggSpecies(species[parentSlots[1]]); + hasMotherEverstone = ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[parentSlots[0]].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE; + hasFatherEverstone = ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[parentSlots[1]].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE; + motherIsForeign = IsSpeciesForeignRegionalForm(motherEggSpecies, currentRegion); + fatherIsForeign = IsSpeciesForeignRegionalForm(fatherEggSpecies, currentRegion); + + if (hasMotherEverstone) + parentSpecies = motherEggSpecies; + else if (fatherIsForeign && hasFatherEverstone) + parentSpecies = fatherEggSpecies; + else if (motherIsForeign) + parentSpecies = GetRegionalFormByRegion(motherEggSpecies, currentRegion); + else + parentSpecies = motherEggSpecies; + + eggSpecies = GetEggSpecies(parentSpecies); + if (eggSpecies == SPECIES_NIDORAN_F && daycare->offspringPersonality & EGG_GENDER_MALE) eggSpecies = SPECIES_NIDORAN_M; else if (eggSpecies == SPECIES_ILLUMISE && daycare->offspringPersonality & EGG_GENDER_MALE) @@ -1050,6 +1071,9 @@ static void _GiveEggFromDaycare(struct DayCare *daycare) u8 parentSlots[DAYCARE_MON_COUNT] = {0}; bool8 isEgg; + if (GetDaycareCompatibilityScore(daycare) == PARENTS_INCOMPATIBLE) + return; + species = DetermineEggSpeciesAndParentSlots(daycare, parentSlots); if (P_INCENSE_BREEDING < GEN_9) AlterEggSpeciesWithIncenseItem(&species, daycare); diff --git a/src/pokemon.c b/src/pokemon.c index 829b0b119263..830b1878f15e 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -59,6 +59,7 @@ #include "constants/items.h" #include "constants/layouts.h" #include "constants/moves.h" +#include "constants/regions.h" #include "constants/songs.h" #include "constants/trainers.h" #include "constants/union_room.h" @@ -6987,3 +6988,70 @@ uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier) return UQ_4_12(1.0/(1.5 + 0.05 * dynamaxLevel)); return UQ_4_12(1.5 + 0.05 * dynamaxLevel); } + +bool32 IsSpeciesRegionalForm(u32 species) +{ + return gSpeciesInfo[species].isAlolanForm + || gSpeciesInfo[species].isGalarianForm + || gSpeciesInfo[species].isHisuianForm + || gSpeciesInfo[species].isPaldeanForm; +} + +bool32 IsSpeciesRegionalFormFromRegion(u32 species, u32 region) +{ + switch (region) + { + case REGION_ALOLA: return gSpeciesInfo[species].isAlolanForm; + case REGION_GALAR: return gSpeciesInfo[species].isGalarianForm; + case REGION_HISUI: return gSpeciesInfo[species].isHisuianForm; + case REGION_PALDEA: return gSpeciesInfo[species].isPaldeanForm; + default: return FALSE; + } +} + +bool32 SpeciesHasRegionalForm(u32 species) +{ + u32 formId; + const u16 *formTable = GetSpeciesFormTable(species); + for (formId = 0; formTable != NULL && formTable[formId] != FORM_SPECIES_END; formId++) + { + if (IsSpeciesRegionalForm(formTable[formId])) + return TRUE; + } + return FALSE; +} + +u32 GetRegionalFormByRegion(u32 species, u32 region) +{ + u32 formId = 0; + u32 firstFoundSpecies = 0; + const u16 *formTable = GetSpeciesFormTable(species); + + if (formTable != NULL) + { + for (formId = 0; formTable[formId] != FORM_SPECIES_END; formId++) + { + if (firstFoundSpecies == 0) + firstFoundSpecies = formTable[formId]; + + if (IsSpeciesRegionalFormFromRegion(formTable[formId], region)) + return formTable[formId]; + } + if (firstFoundSpecies != 0) + return firstFoundSpecies; + } + return species; +} + +bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion) +{ + u32 i; + for (i = 0; i < REGIONS_COUNT; i++) + { + if (currentRegion != i && IsSpeciesRegionalFormFromRegion(species, i)) + return TRUE; + else if (currentRegion == i && SpeciesHasRegionalForm(species) && !IsSpeciesRegionalFormFromRegion(species, i)) + return TRUE; + } + return FALSE; +} diff --git a/test/battle/ability/unnerve.c b/test/battle/ability/unnerve.c index 9ad4ee7e5fdd..ce35cf72c1c6 100644 --- a/test/battle/ability/unnerve.c +++ b/test/battle/ability/unnerve.c @@ -2,5 +2,73 @@ #include "test/battle.h" // Remember to add a PARAMETRIZE for As One in the following tests: -TO_DO_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own berries"); -TO_DO_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural Gift"); +SINGLE_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own berries") +{ + u16 mon; + u16 ability; + PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } + PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } + GIVEN { + ASSUME(gItemsInfo[ITEM_RAWST_BERRY].holdEffect == HOLD_EFFECT_CURE_BRN); + PLAYER(mon) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RAWST_BERRY); Status1(STATUS1_BURN); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(player, ability); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + HP_BAR(opponent); + } +} + +SINGLE_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural Gift") +{ + u16 mon; + u16 ability; + PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } + PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } + GIVEN { + ASSUME(gMovesInfo[MOVE_NATURAL_GIFT].effect == EFFECT_NATURAL_GIFT); + PLAYER(mon) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ORAN_BERRY); } + } WHEN { + TURN { MOVE(opponent, MOVE_NATURAL_GIFT); } + } SCENE { + ABILITY_POPUP(player, ability); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Unnerve prints the correct string (player)") +{ + u16 mon; + u16 ability; + PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } + PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } + GIVEN { + PLAYER(mon) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN {} + } SCENE { + ABILITY_POPUP(player, ability); + MESSAGE("The opposing team is too nervous to eat Berries!"); + } +} + +SINGLE_BATTLE_TEST("Unnerve prints the correct string (opponent)") +{ + u16 mon; + u16 ability; + PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; } + PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(mon) { Ability(ability); } + } WHEN { + TURN {} + } SCENE { + ABILITY_POPUP(opponent, ability); + MESSAGE("Your team is too nervous to eat Berries!"); + } +} diff --git a/test/battle/hold_effect/red_card.c b/test/battle/hold_effect/red_card.c index 7b14d8748de9..88b208cf508e 100644 --- a/test/battle/hold_effect/red_card.c +++ b/test/battle/hold_effect/red_card.c @@ -273,12 +273,13 @@ DOUBLE_BATTLE_TEST("Red Card activates but fails if the attacker is rooted") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); MESSAGE("Wobbuffet held up its Red Card against the opposing Wobbuffet!"); MESSAGE("The opposing Wobbuffet anchored itself with its roots!"); + NOT MESSAGE("The opposing Unown was dragged out!"); // Red Card already consumed so cannot activate. ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight); NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); - MESSAGE("Wynaut held up its Red Card against the opposing Wynaut!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Wobbuffet held up its Red Card against the opposing Wynaut!"); } } } @@ -301,12 +302,41 @@ DOUBLE_BATTLE_TEST("Red Card activates but fails if the attacker has Suction Cup ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); MESSAGE("Wobbuffet held up its Red Card against the opposing Octillery!"); MESSAGE("The opposing Octillery anchors itself with Suction Cups!"); + NOT MESSAGE("The opposing Unown was dragged out!"); // Red Card already consumed so cannot activate. ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight); NONE_OF { - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); - MESSAGE("Wynaut held up its Red Card against the opposing Wynaut!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Wobbuffet held up its Red Card against the opposing Wynaut!"); + } + } +} + +DOUBLE_BATTLE_TEST("Red Card activates but fails if the attacker has Guard Dog") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_OKIDOGI) { Ability(ABILITY_GUARD_DOG); } + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_UNOWN); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_TACKLE, target: playerLeft); + MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Wobbuffet held up its Red Card against the opposing Okidogi!"); + NOT MESSAGE("The opposing Unown was dragged out!"); + + // Red Card already consumed so cannot activate. + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Wobbuffet held up its Red Card against the opposing Wynaut!"); } } } diff --git a/test/battle/move_effect/electrify.c b/test/battle/move_effect/electrify.c index 71373cdd5866..e60bbdaf2288 100644 --- a/test/battle/move_effect/electrify.c +++ b/test/battle/move_effect/electrify.c @@ -1,5 +1,74 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn"); -TO_DO_BATTLE_TEST("Electrify can change status moves to Electric-type"); // Test type immunity +SINGLE_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn (single move)") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND); + ASSUME(gMovesInfo[MOVE_TACKLE].type != TYPE_ELECTRIC); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SANDSLASH); + } WHEN { + TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + } +} + +DOUBLE_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn (double move)") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND); + ASSUME(gMovesInfo[MOVE_TACKLE].type != TYPE_ELECTRIC); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_SANDSLASH); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft); MOVE(playerRight, MOVE_INSTRUCT, target: playerLeft); MOVE(opponentRight, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponentLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, playerRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + } +} + +SINGLE_BATTLE_TEST("Electrify can change status moves to Electric-type") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND); + ASSUME(gMovesInfo[MOVE_LEER].category == DAMAGE_CATEGORY_STATUS); + ASSUME(gMovesInfo[MOVE_LEER].type != TYPE_ELECTRIC); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SANDSLASH); + } WHEN { + TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_LEER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, player); + } +} + +SINGLE_BATTLE_TEST("Electrify changes the type of foreseen moves") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND); + ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].effect == EFFECT_FUTURE_SIGHT); + ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].type != TYPE_ELECTRIC); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SANDSLASH); + } WHEN { + TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_FUTURE_SIGHT); } + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + NOT HP_BAR(opponent); + } +} diff --git a/test/battle/move_effect/hit_switch_target.c b/test/battle/move_effect/hit_switch_target.c index a21cb467e3a4..61c92d227e27 100644 --- a/test/battle/move_effect/hit_switch_target.c +++ b/test/battle/move_effect/hit_switch_target.c @@ -90,7 +90,7 @@ SINGLE_BATTLE_TEST("Dragon Tail switches the target after Rocky Helmet and Iron } } -SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Guard Dog ability") +SINGLE_BATTLE_TEST("Dragon Tail effect fails against target with Guard Dog") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Guard Dog ability") } } -SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Suction Cups ability") +SINGLE_BATTLE_TEST("Dragon Tail effect fails against target with Suction Cups") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -114,6 +114,7 @@ SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Suction Cups ability") TURN { MOVE(player, MOVE_DRAGON_TAIL); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, player); + ABILITY_POPUP(opponent, ABILITY_SUCTION_CUPS); MESSAGE("The opposing Octillery anchors itself with Suction Cups!"); NOT MESSAGE("The opposing Charmander was dragged out!"); } diff --git a/test/battle/move_effect/roar.c b/test/battle/move_effect/roar.c index ef6439088f5e..525e75b6dfb8 100644 --- a/test/battle/move_effect/roar.c +++ b/test/battle/move_effect/roar.c @@ -68,3 +68,38 @@ SINGLE_BATTLE_TEST("Roar fails if replacements fainted") MESSAGE("But it failed!"); } } + +SINGLE_BATTLE_TEST("Roar fails against target with Guard Dog") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_OKIDOGI) { Ability(ABILITY_GUARD_DOG); } + OPPONENT(SPECIES_CHARMANDER); + } WHEN { + TURN { MOVE(player, MOVE_ROAR); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, player); + MESSAGE("The opposing Charmander was dragged out!"); + } + MESSAGE("Wobbuffet used Roar!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Roar fails to switch out target with Suction Cups") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_OCTILLERY) { Ability(ABILITY_SUCTION_CUPS); } + OPPONENT(SPECIES_CHARMANDER); + } WHEN { + TURN { MOVE(player, MOVE_ROAR); } + } SCENE { + MESSAGE("Wobbuffet used Roar!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, player); + ABILITY_POPUP(opponent, ABILITY_SUCTION_CUPS); + MESSAGE("The opposing Octillery anchors itself with Suction Cups!"); + NOT MESSAGE("The opposing Charmander was dragged out!"); + } +} diff --git a/test/daycare.c b/test/daycare.c new file mode 100644 index 000000000000..1f142f115495 --- /dev/null +++ b/test/daycare.c @@ -0,0 +1,164 @@ +#include "global.h" +#include "daycare.h" +#include "event_data.h" +#include "malloc.h" +#include "party_menu.h" +#include "regions.h" +#include "test/overworld_script.h" +#include "test/test.h" + +// We don't run the StoreSelectedPokemonInDaycare special because it relies on calling the +// party select screen and the GetCursorSelectionMonId function, so we store directly to the struct. +#define STORE_IN_DAYCARE_AND_GET_EGG() \ + StorePokemonInDaycare(&gPlayerParty[0], &gSaveBlock1Ptr->daycare.mons[0]); \ + StorePokemonInDaycare(&gPlayerParty[0], &gSaveBlock1Ptr->daycare.mons[1]); \ + RUN_OVERWORLD_SCRIPT( special GiveEggFromDaycare; ); + +TEST("(Daycare) Pokémon generate Eggs of the lowest member of the evolutionary family") +{ + ASSUME(P_FAMILY_PIKACHU == TRUE); + ASSUME(P_GEN_2_CROSS_EVOS == TRUE); + + ZeroPlayerPartyMons(); + RUN_OVERWORLD_SCRIPT( + givemon SPECIES_PIKACHU, 100, gender=MON_MALE; + givemon SPECIES_PIKACHU, 100, gender=MON_FEMALE; + ); + STORE_IN_DAYCARE_AND_GET_EGG(); + + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_PICHU); +} + +TEST("(Daycare) Pokémon offspring species is based off the mother's species") +{ + u32 offspring = 0; + ASSUME(P_FAMILY_PIKACHU == TRUE); + ASSUME(P_GEN_2_CROSS_EVOS == TRUE); + ASSUME(P_FAMILY_RIOLU == TRUE); + + ZeroPlayerPartyMons(); + PARAMETRIZE { offspring = SPECIES_RIOLU; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PIKACHU, 100, gender=MON_MALE; givemon SPECIES_LUCARIO, 100, gender=MON_FEMALE, item=ITEM_NONE; ); } + PARAMETRIZE { offspring = SPECIES_PICHU; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PIKACHU, 100, gender=MON_FEMALE; givemon SPECIES_LUCARIO, 100, gender=MON_MALE;); } + STORE_IN_DAYCARE_AND_GET_EGG(); + + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring); +} + +TEST("(Daycare) Pokémon can breed with Ditto if they don't belong to the Ditto or No Eggs Discovered group") +{ + u32 j = 0; + u32 parentSpecies = 0; + + ZeroPlayerPartyMons(); + for (j = 1; j < NUM_SPECIES; j++) + PARAMETRIZE { parentSpecies = j; } + VarSet(VAR_TEMP_C, parentSpecies); + RUN_OVERWORLD_SCRIPT( + givemon SPECIES_DITTO, 100; givemon VAR_TEMP_C, 100; + ); + STORE_IN_DAYCARE_AND_GET_EGG(); + + if (gSpeciesInfo[parentSpecies].eggGroups[0] != EGG_GROUP_NO_EGGS_DISCOVERED + && gSpeciesInfo[parentSpecies].eggGroups[0] != EGG_GROUP_DITTO) + EXPECT_NE(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_NONE); + else + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_NONE); +} + +TEST("(Daycare) Shellos' form is always based on the mother's form") +{ + u32 offspring = 0; + ASSUME(P_FAMILY_MEOWTH == TRUE); + ASSUME(P_ALOLAN_FORMS == TRUE); + ASSUME(P_GALARIAN_FORMS == TRUE); + + ZeroPlayerPartyMons(); + PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); } + PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); } + PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); } + PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); } + PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); } + PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); } + STORE_IN_DAYCARE_AND_GET_EGG(); + + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring); +} + +TEST("(Daycare) Pokémon with regional forms give the correct offspring") +{ + u32 region = 0, offspring = 0, species1 = 0, item1 = 0, species2 = 0, item2 = 0; + + ZeroPlayerPartyMons(); + + region = GetCurrentRegion(); + if (region == REGION_ALOLA) { + PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERSIAN_ALOLA; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; } + } else if (region == REGION_GALAR) { + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERSIAN_ALOLA; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; } + } else { + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERSIAN_ALOLA; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN, item2=ITEM_EVERSTONE; } + } + + if (region == REGION_HISUI) { + PARAMETRIZE { offspring=SPECIES_SNEASEL_HISUI; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASEL; item1=ITEM_EVERSTONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_SNEASEL_HISUI; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASLER; item1=ITEM_EVERSTONE; species2=SPECIES_WEAVILE, item2=ITEM_EVERSTONE; } + } else { + PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASEL; item1=ITEM_EVERSTONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_SNEASEL_HISUI; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASLER; item1=ITEM_EVERSTONE; species2=SPECIES_WEAVILE, item2=ITEM_EVERSTONE; } + } + + if (region == REGION_PALDEA) { + PARAMETRIZE { offspring=SPECIES_WOOPER_PALDEA; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_WOOPER; item1=ITEM_EVERSTONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_WOOPER_PALDEA; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_CLODSIRE; item1=ITEM_EVERSTONE; species2=SPECIES_QUAGSIRE, item2=ITEM_EVERSTONE; } + } else { + PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_WOOPER; item1=ITEM_EVERSTONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; } + PARAMETRIZE { offspring=SPECIES_WOOPER_PALDEA; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_EVERSTONE; } + PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_CLODSIRE; item1=ITEM_EVERSTONE; species2=SPECIES_QUAGSIRE, item2=ITEM_EVERSTONE; } + } + ASSUME(IsSpeciesEnabled(species1) == TRUE); + ASSUME(IsSpeciesEnabled(species2) == TRUE); + ASSUME(IsSpeciesEnabled(offspring) == TRUE); + + VarSet(VAR_0x8000, species1); + VarSet(VAR_0x8001, item1); + VarSet(VAR_0x8002, species2); + VarSet(VAR_0x8003, item2); + + RUN_OVERWORLD_SCRIPT(givemon VAR_0x8000, 1, gender=MON_MALE, item=VAR_0x8001;); + RUN_OVERWORLD_SCRIPT(givemon VAR_0x8002, 1, gender=MON_FEMALE, item=VAR_0x8003;); + + STORE_IN_DAYCARE_AND_GET_EGG(); + + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring); +}