Fixes Beak Blast burning after Beak Blast was already used (#8361)

This commit is contained in:
PhallenTree 2025-11-27 19:07:45 +00:00 committed by GitHub
parent 7085d30263
commit c36fc5c4b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 31 additions and 20 deletions

View File

@ -1766,10 +1766,6 @@
callnative BS_WaitFanfare callnative BS_WaitFanfare
.endm .endm
.macro setbeakblast
callnative BS_SetBeakBlast
.endm
.macro cantarshotwork failInstr:req .macro cantarshotwork failInstr:req
callnative BS_CanTarShotWork callnative BS_CanTarShotWork
.4byte \failInstr .4byte \failInstr

View File

@ -671,7 +671,6 @@ BattleScript_EffectCourtChange::
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_BeakBlastSetUp:: BattleScript_BeakBlastSetUp::
setbeakblast
flushtextbox flushtextbox
playanimation BS_ATTACKER, B_ANIM_BEAK_BLAST_SETUP, NULL playanimation BS_ATTACKER, B_ANIM_BEAK_BLAST_SETUP, NULL
printstring STRINGID_HEATUPBEAK printstring STRINGID_HEATUPBEAK

View File

@ -158,19 +158,18 @@ struct ProtectStruct
u32 disableEjectPack:1; u32 disableEjectPack:1;
u32 pranksterElevated:1; u32 pranksterElevated:1;
u32 quickDraw:1; u32 quickDraw:1;
u32 beakBlastCharge:1;
u32 quash:1; u32 quash:1;
u32 shellTrap:1; u32 shellTrap:1;
u32 eatMirrorHerb:1; u32 eatMirrorHerb:1;
u32 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u32 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy
u16 usedAllySwitch:1; u16 usedAllySwitch:1;
u16 lashOutAffected:1;
// End of 32-bit bitfield // End of 32-bit bitfield
u32 helpingHand:3; u32 helpingHand:3;
u16 lashOutAffected:1;
u16 assuranceDoubled:1; u16 assuranceDoubled:1;
u16 myceliumMight:1; u16 myceliumMight:1;
u16 laggingTail:1; u16 laggingTail:1;
u16 padding:9; u16 padding:10;
// End of 16-bit bitfield // End of 16-bit bitfield
u16 physicalDmg; u16 physicalDmg;
u16 specialDmg; u16 specialDmg;

View File

@ -1069,6 +1069,15 @@ bool32 EmergencyExitCanBeTriggered(u32 battler)
return FALSE; return FALSE;
} }
static inline bool32 IsBattlerUsingBeakBlast(u32 battler)
{
if (gChosenActionByBattler[battler] != B_ACTION_USE_MOVE)
return FALSE;
if (GetMoveEffect(gChosenMoveByBattler[battler]) != EFFECT_BEAK_BLAST)
return FALSE;
return !HasBattlerActedThisTurn(battler);
}
static void Cmd_attackcanceler(void) static void Cmd_attackcanceler(void)
{ {
CMD_ARGS(); CMD_ARGS();
@ -1295,7 +1304,8 @@ static void Cmd_attackcanceler(void)
gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED;
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
else if (gProtectStructs[gBattlerTarget].beakBlastCharge && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)) else if (IsBattlerUsingBeakBlast(gBattlerTarget)
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove))
{ {
gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE;
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
@ -6116,7 +6126,7 @@ static void Cmd_moveend(void)
} }
// Not strictly a protect effect, but works the same way // Not strictly a protect effect, but works the same way
if (gProtectStructs[gBattlerTarget].beakBlastCharge if (IsBattlerUsingBeakBlast(gBattlerTarget)
&& CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
{ {
@ -16299,13 +16309,6 @@ void BS_WaitFanfare(void)
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
void BS_SetBeakBlast(void)
{
NATIVE_ARGS();
gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE;
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_RemoveTerrain(void) void BS_RemoveTerrain(void)
{ {
NATIVE_ARGS(); NATIVE_ARGS();

View File

@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used")
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
TURN { MOVE(player, MOVE_BEAK_BLAST); MOVE(opponent, move); } TURN { MOVE(opponent, move); MOVE(player, MOVE_BEAK_BLAST); }
TURN {} TURN {}
} SCENE { } SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_BEAK_BLAST_SETUP, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_BEAK_BLAST_SETUP, player);
@ -115,11 +115,11 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used")
SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types") SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types")
{ {
GIVEN { GIVEN {
ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1]); ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1] == TYPE_FIRE);
PLAYER(SPECIES_ARCANINE); PLAYER(SPECIES_ARCANINE);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_SCRATCH); } TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_BEAK_BLAST); }
} SCENE { } SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
NOT STATUS_ICON(player, burn: TRUE); NOT STATUS_ICON(player, burn: TRUE);
@ -127,6 +127,20 @@ SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types")
} }
} }
SINGLE_BATTLE_TEST("Beak Blast doesn't burn after being used")
{
GIVEN {
ASSUME(GetMovePriority(MOVE_COUNTER) < GetMovePriority(MOVE_BEAK_BLAST));
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_COUNTER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAK_BLAST, opponent);
NOT STATUS_ICON(player, burn: TRUE);
}
}
TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed"); TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed");
TO_DO_BATTLE_TEST("Beak Blast fails if it's forced by Encore after choosing a different move"); TO_DO_BATTLE_TEST("Beak Blast fails if it's forced by Encore after choosing a different move");
TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes"); TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes");