From f671b130a6ca5d5d853ea7cb3c7e7abf8e59a185 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:40:40 +0200 Subject: [PATCH] Fixes Beat Up incorrect slots usage (#7741) --- asm/macros/battle_script.inc | 2 +- data/battle_scripts_1.s | 10 ---------- include/battle.h | 1 + src/battle_script_commands.c | 7 ------- src/battle_util.c | 20 +++++++++----------- src/data/battle_move_effects.h | 2 +- test/battle/move_effect/beat_up.c | 27 ++++++++++++++++++++++++++- 7 files changed, 38 insertions(+), 31 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index a689c8a94d..a301f0feb2 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1050,7 +1050,7 @@ .4byte \failInstr .endm - .macro trydobeatup endInstr, failInstr + .macro trydobeatup endInstr:req, failInstr:req .byte 0xc4 .4byte \endInstr .4byte \failInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 895735a154..2afd6f26a2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4286,15 +4286,6 @@ BattleScript_DoEffectTeleport:: BattleScript_EffectBeatUp:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -.if B_BEAT_UP >= GEN_5 - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - trydobeatup - goto BattleScript_HitFromAtkAnimation -.else attackstring pause B_WAIT_TIME_SHORT ppreduce @@ -4324,7 +4315,6 @@ BattleScript_BeatUpAttack:: goto BattleScript_BeatUpLoop BattleScript_BeatUpEnd:: end -.endif BattleScript_EffectDefenseCurl:: attackcanceler diff --git a/include/battle.h b/include/battle.h index 60c2d85b6a..ed3f4de6af 100644 --- a/include/battle.h +++ b/include/battle.h @@ -736,6 +736,7 @@ struct BattleStruct u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. + u16 beatUpSpecies[PARTY_SIZE]; u8 attackerBeforeBounce:2; u8 beatUpSlot:3; u8 pledgeMove:1; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6eab4e819b..d74ec3f956 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12470,12 +12470,6 @@ static void Cmd_trysetfutureattack(void) static void Cmd_trydobeatup(void) { -#if B_BEAT_UP >= GEN_5 - CMD_ARGS(); - - gBattleStruct->beatUpSlot++; - gBattlescriptCurrInstr = cmd->nextInstr; -#else CMD_ARGS(const u8 *endInstr, const u8 *failInstr); struct Pokemon *party = GetBattlerParty(gBattlerAttacker); @@ -12520,7 +12514,6 @@ static void Cmd_trydobeatup(void) gBattlescriptCurrInstr = cmd->failInstr; } } -#endif } static void Cmd_setsemiinvulnerablebit(void) diff --git a/src/battle_util.c b/src/battle_util.c index 4352a900d1..76ed12a9be 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -267,15 +267,8 @@ bool32 EndOrContinueWeather(void) static u32 CalcBeatUpPower(void) { - u32 basePower; - u32 species; - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - - // Party slot is incremented by the battle script for Beat Up after this damage calculation - species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES); - basePower = (GetSpeciesBaseAttack(species) / 10) + 5; - - return basePower; + u32 species = gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++]; + return (GetSpeciesBaseAttack(species) / 10) + 5; } static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, u32 abilityDef) @@ -2485,14 +2478,19 @@ static enum MoveCanceller CancellerMultihitMoves(void) { struct Pokemon* party = GetBattlerParty(gBattlerAttacker); int i; + gBattleStruct->beatUpSlot = 0; for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) - && GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + u32 species = GetMonData(&party[i], MON_DATA_SPECIES); + if (species != SPECIES_NONE + && GetMonData(&party[i], MON_DATA_HP) && !GetMonData(&party[i], MON_DATA_IS_EGG) && !GetMonData(&party[i], MON_DATA_STATUS)) + { + gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++] = species; gMultiHitCounter++; + } } gBattleStruct->beatUpSlot = 0; diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 88d4075570..51bbdba0eb 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -791,7 +791,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_BEAT_UP] = { - .battleScript = BattleScript_EffectBeatUp, + .battleScript = (B_BEAT_UP >= GEN_5) ? BattleScript_EffectHit : BattleScript_EffectBeatUp, .battleTvScore = 2, }, diff --git a/test/battle/move_effect/beat_up.c b/test/battle/move_effect/beat_up.c index dd0d19925f..e584ccc0f9 100644 --- a/test/battle/move_effect/beat_up.c +++ b/test/battle/move_effect/beat_up.c @@ -2,7 +2,32 @@ #include "test/battle.h" // General -TO_DO_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party"); +SINGLE_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_PICHU) + PLAYER(SPECIES_PIKACHU) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_RAICHU) + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + MESSAGE("The Pokémon was hit 4 time(s)!"); + } THEN { + EXPECT_EQ(gBattleStruct->beatUpSpecies[0], SPECIES_WOBBUFFET); + EXPECT_EQ(gBattleStruct->beatUpSpecies[1], SPECIES_WYNAUT); + EXPECT_EQ(gBattleStruct->beatUpSpecies[2], SPECIES_PICHU); + EXPECT_EQ(gBattleStruct->beatUpSpecies[3], SPECIES_RAICHU); + } +} + TO_DO_BATTLE_TEST("Beat Up doesn't consider Comatose as a status") TO_DO_BATTLE_TEST("Beat Up's strikes have each an independent chance of a critical hit");