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
.endm
.macro setbeakblast
callnative BS_SetBeakBlast
.endm
.macro cantarshotwork failInstr:req
callnative BS_CanTarShotWork
.4byte \failInstr

View File

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

View File

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

View File

@ -1069,6 +1069,15 @@ bool32 EmergencyExitCanBeTriggered(u32 battler)
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)
{
CMD_ARGS();
@ -1295,7 +1304,8 @@ static void Cmd_attackcanceler(void)
gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED;
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;
gBattlescriptCurrInstr = cmd->nextInstr;
@ -6116,7 +6126,7 @@ static void Cmd_moveend(void)
}
// Not strictly a protect effect, but works the same way
if (gProtectStructs[gBattlerTarget].beakBlastCharge
if (IsBattlerUsingBeakBlast(gBattlerTarget)
&& CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
{
@ -16299,13 +16309,6 @@ void BS_WaitFanfare(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_SetBeakBlast(void)
{
NATIVE_ARGS();
gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE;
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_RemoveTerrain(void)
{
NATIVE_ARGS();

View File

@ -86,7 +86,7 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used")
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_BEAK_BLAST); MOVE(opponent, move); }
TURN { MOVE(opponent, move); MOVE(player, MOVE_BEAK_BLAST); }
TURN {}
} SCENE {
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")
{
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);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_SCRATCH); }
TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_BEAK_BLAST); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
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 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");