From f8551830c9c735b2c3a62785ed465427307827ce Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 25 Jun 2025 15:58:30 +0200 Subject: [PATCH] Adds Gen5+ Encore config (#7051) --- data/battle_scripts_1.s | 8 ++++++++ include/battle_scripts.h | 2 ++ include/battle_util.h | 2 +- include/config/battle.h | 1 + include/constants/battle_string_ids.h | 1 + include/constants/generational_changes.h | 1 + include/generational_changes.h | 3 ++- src/battle_main.c | 2 +- src/battle_message.c | 1 + src/battle_util.c | 22 ++++++++++++++++++++-- test/battle/ai/ai_switching.c | 1 - test/battle/move_effect/encore.c | 2 ++ test/battle/move_flags/cant_use_twice.c | 1 + test/battle/sleep_clause.c | 1 + 14 files changed, 42 insertions(+), 6 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c7acc4b3bc..60d0f77b9f 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5775,6 +5775,14 @@ BattleScript_DisabledNoMore:: BattleScript_SelectingDisabledMoveInPalace:: printstring STRINGID_PKMNMOVEISDISABLED + goto BattleScript_SelectingUnusableMoveInPalace + +BattleScript_EncoredMove:: + printselectionstring STRINGID_PKMNGOTENCOREDMOVE + endselectionscript + +BattleScript_EncoredMoveInPalace:: + printselectionstring STRINGID_PKMNGOTENCOREDMOVE BattleScript_SelectingUnusableMoveInPalace:: moveendto MOVEEND_NEXT_TARGET end diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 1c0e03b245..50cfbc1420 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -72,6 +72,8 @@ extern const u8 BattleScript_RoarSuccessSwitch[]; extern const u8 BattleScript_RoarSuccessEndBattle[]; extern const u8 BattleScript_MistProtected[]; extern const u8 BattleScript_RageIsBuilding[]; +extern const u8 BattleScript_EncoredMoveInPalace[]; +extern const u8 BattleScript_EncoredMove[]; extern const u8 BattleScript_MoveUsedIsDisabled[]; extern const u8 BattleScript_SelectingDisabledMove[]; extern const u8 BattleScript_DisabledNoMore[]; diff --git a/include/battle_util.h b/include/battle_util.h index 62b959cfe3..f6c591635b 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -233,7 +233,7 @@ void BattleScriptPushCursor(void); void BattleScriptCall(const u8 *bsPtr); void BattleScriptPop(void); u32 TrySetCantSelectMoveBattleScript(u32 battler); -u8 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check); +u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check); bool32 AreAllMovesUnusable(u32 battler); u8 GetImprisonedMovesCount(u32 battler, u16 move); s32 GetDrainedBigRootHp(u32 battler, s32 hp); diff --git a/include/config/battle.h b/include/config/battle.h index f34004783f..3fdc45e490 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -129,6 +129,7 @@ #define B_DESTINY_BOND_FAIL GEN_LATEST // In Gen7+, Destiny Bond fails if used repeatedly. #define B_PURSUIT_TARGET GEN_LATEST // In Gen4+, Pursuit attacks a switching opponent even if they weren't targeting them. Before Gen4, Pursuit only attacks a switching opponent that it originally targeted. #define B_SKIP_RECHARGE GEN_LATEST // In Gen1, recharging moves such as Hyper Beam skip the recharge if the target gets KO'd +#define B_ENCORE_TARGET GEN_LATEST // In Gen5+, encored moves are allowed to choose a target // Ability settings #define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger. diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 680ea413d8..57b56d4cbe 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -138,6 +138,7 @@ enum StringID STRINGID_PKMNMOVEISDISABLED, STRINGID_PKMNMOVEDISABLEDNOMORE, STRINGID_PKMNGOTENCORE, + STRINGID_PKMNGOTENCOREDMOVE, STRINGID_PKMNENCOREENDED, STRINGID_PKMNTOOKAIM, STRINGID_PKMNSKETCHEDMOVE, diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 7a3485e2f7..143dc6e5bb 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -18,6 +18,7 @@ enum GenConfigTag GEN_CONFIG_ATE_MULTIPLIER, GEN_CONFIG_FELL_STINGER_STAT_RAISE, GEN_CONFIG_DEFIANT_STICKY_WEB, + GEN_CONFIG_ENCORE_TARGET, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index ef59c05962..146139d39e 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -18,9 +18,10 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_ABILITY_WEATHER] = B_ABILITY_WEATHER, [GEN_CONFIG_MOODY_STATS] = B_MOODY_ACC_EVASION, [GEN_CONFIG_BATTLE_BOND] = B_BATTLE_BOND, - [GEN_CONFIG_FELL_STINGER_STAT_RAISE] = B_FELL_STINGER_STAT_RAISE, [GEN_CONFIG_ATE_MULTIPLIER] = B_ATE_MULTIPLIER, + [GEN_CONFIG_FELL_STINGER_STAT_RAISE] = B_FELL_STINGER_STAT_RAISE, [GEN_CONFIG_DEFIANT_STICKY_WEB] = B_DEFIANT_STICKY_WEB, + [GEN_CONFIG_ENCORE_TARGET] = B_ENCORE_TARGET, }; #if TESTING diff --git a/src/battle_main.c b/src/battle_main.c index 6e99411ce8..b62f3d2cc9 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4237,7 +4237,7 @@ static void HandleTurnActionSelectionState(void) gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3]; return; } - else if (gDisableStructs[battler].encoredMove != 0) + else if (GetGenConfig(GEN_CONFIG_ENCORE_TARGET) < GEN_5 && gDisableStructs[battler].encoredMove != MOVE_NONE) { gChosenMoveByBattler[battler] = gDisableStructs[battler].encoredMove; gBattleStruct->chosenMovePositions[battler] = gDisableStructs[battler].encoredMovePos; diff --git a/src/battle_message.c b/src/battle_message.c index fbb36fa6d1..35d8b23083 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -297,6 +297,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNMOVEISDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} is disabled!\p"), [STRINGID_PKMNMOVEDISABLEDNOMORE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s move is no longer disabled!"), [STRINGID_PKMNGOTENCORE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} must do an encore!"), + [STRINGID_PKMNGOTENCOREDMOVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} can only use {B_CURRENT_MOVE}!\p"), [STRINGID_PKMNENCOREENDED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} ended its encore!"), [STRINGID_PKMNTOOKAIM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} took aim at {B_DEF_NAME_WITH_PREFIX2}!"), [STRINGID_PKMNSKETCHEDMOVE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} sketched {B_BUFF1}!"), diff --git a/src/battle_util.c b/src/battle_util.c index 0b6510e7a2..66e5dfd4e2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1308,6 +1308,24 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) u16 *choicedMove = &gBattleStruct->choicedMove[battler]; enum BattleMoveEffects moveEffect = GetMoveEffect(move); + if (GetGenConfig(GEN_CONFIG_ENCORE_TARGET) >= GEN_5 + && DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].encoredMove != move && gDisableStructs[battler].encoredMove != MOVE_NONE) + { + gBattleScripting.battler = battler; + gCurrentMove = gDisableStructs[battler].encoredMove; + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + gPalaceSelectionBattleScripts[battler] = BattleScript_EncoredMoveInPalace; + gProtectStructs[battler].palaceUnableToUseMove = TRUE; + } + else + { + gSelectionBattleScripts[battler] = BattleScript_EncoredMove; + limitations++; + } + return limitations; + } + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].disabledMove == move && move != MOVE_NONE) { gBattleScripting.battler = battler; @@ -1544,7 +1562,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) return limitations; } -u8 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) +u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) { u32 move; enum BattleMoveEffects moveEffect; @@ -1616,7 +1634,7 @@ u8 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) #define ALL_MOVES_MASK ((1 << MAX_MON_MOVES) - 1) bool32 AreAllMovesUnusable(u32 battler) { - u8 unusable = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL); + u32 unusable = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL); if (unusable == ALL_MOVES_MASK) // All moves are unusable. { diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 1ab0003f50..4dce36a219 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -929,7 +929,6 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will stay in if Encore'd into AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if Encore'd into neutral move with good switchin 50% of the time") { - KNOWN_FAILING; // AI still switches even if ShouldSwitch is set to immediately return FALSE, something external seems to be triggering this PASSES_RANDOMLY(SHOULD_SWITCH_ENCORE_DAMAGE_PERCENTAGE, 100, RNG_AI_SWITCH_ENCORE); GIVEN { ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE); diff --git a/test/battle/move_effect/encore.c b/test/battle/move_effect/encore.c index e2a08f7d75..2c4ade2c88 100644 --- a/test/battle/move_effect/encore.c +++ b/test/battle/move_effect/encore.c @@ -14,6 +14,7 @@ SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns: Encore used PARAMETRIZE { encoreUser = opponent; encoreTarget = player; speedPlayer = 10; speedOpponent = 20; } PARAMETRIZE { encoreUser = player; encoreTarget = opponent; speedPlayer = 20; speedOpponent = 10; } GIVEN { + WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); PLAYER(SPECIES_WOBBUFFET) { Speed(speedPlayer); } OPPONENT(SPECIES_WOBBUFFET) { Speed(speedOpponent); } } WHEN { @@ -41,6 +42,7 @@ SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for player: PARAMETRIZE { encoreUser = opponent; encoreTarget = player; speedPlayer = 20; speedOpponent = 10; } PARAMETRIZE { encoreUser = player; encoreTarget = opponent; speedPlayer = 10; speedOpponent = 20; } GIVEN { + WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); PLAYER(SPECIES_WOBBUFFET) { Speed(speedPlayer); } OPPONENT(SPECIES_WOBBUFFET) { Speed(speedOpponent); } } WHEN { diff --git a/test/battle/move_flags/cant_use_twice.c b/test/battle/move_flags/cant_use_twice.c index cba5596d26..3ed751b95d 100644 --- a/test/battle/move_flags/cant_use_twice.c +++ b/test/battle/move_flags/cant_use_twice.c @@ -32,6 +32,7 @@ SINGLE_BATTLE_TEST("Moves with the cantUseTwice flag strike again if fast encore PARAMETRIZE { move = MOVE_GIGATON_HAMMER; } PARAMETRIZE { move = MOVE_BLOOD_MOON; } GIVEN { + WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/sleep_clause.c b/test/battle/sleep_clause.c index c2c74314e5..ca416d230e 100644 --- a/test/battle/sleep_clause.c +++ b/test/battle/sleep_clause.c @@ -1771,6 +1771,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep Clause does not prevent sleeping your pa DOUBLE_BATTLE_TEST("Sleep Clause: Sleep moves used after being Encore'd are prevented when sleep clause is active") { GIVEN { + WITH_CONFIG(GEN_CONFIG_ENCORE_TARGET, GEN_3); FLAG_SET(B_FLAG_SLEEP_CLAUSE); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP);