Skip to content

Commit

Permalink
Merge branch 'master' into master-to-upcoming
Browse files Browse the repository at this point in the history
  • Loading branch information
Hedara committed Feb 6, 2025
2 parents 4359cbb + f6d1773 commit 27da389
Show file tree
Hide file tree
Showing 15 changed files with 534 additions and 39 deletions.
7 changes: 2 additions & 5 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions include/constants/regions.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions include/daycare.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions include/pokemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
12 changes: 12 additions & 0 deletions include/regions.h
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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]++;
Expand Down
32 changes: 17 additions & 15 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
Expand All @@ -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)
Expand All @@ -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;
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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))
Expand Down Expand Up @@ -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]];
}
Expand Down Expand Up @@ -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;
Expand Down
34 changes: 29 additions & 5 deletions src/daycare.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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))
{
Expand Down Expand Up @@ -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++)
{
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
68 changes: 68 additions & 0 deletions src/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
Loading

0 comments on commit 27da389

Please sign in to comment.