Fixes Effect Spore and Baneful Bunker/Burning Bulwark (#7412)

This commit is contained in:
Alex 2025-07-30 19:54:12 +02:00 committed by GitHub
parent 6a96be8181
commit cb4450efaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 81 additions and 10 deletions

View File

@ -666,7 +666,8 @@ struct BattleStruct
u8 anyMonHasTransformed:1; // Only used in battle_tv.c
u8 multipleSwitchInState:2;
u8 multipleSwitchInCursor:3;
u8 padding1:2;
u8 sleepClauseNotBlocked:1;
u8 padding1:1;
u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT];
void (*savedCallback)(void);
u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle

View File

@ -6543,7 +6543,8 @@ static void Cmd_moveend(void)
}
break;
case PROTECT_BANEFUL_BUNKER:
if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)))
if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))
&& CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker)))
{
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
gBattleScripting.moveEffect = MOVE_EFFECT_POISON | MOVE_EFFECT_AFFECTS_USER;
@ -6554,7 +6555,8 @@ static void Cmd_moveend(void)
}
break;
case PROTECT_BURNING_BULWARK:
if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)))
if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))
&& CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)))
{
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
gBattleScripting.moveEffect = MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER;
@ -6728,6 +6730,7 @@ static void Cmd_moveend(void)
{
BestowItem(BATTLE_PARTNER(i), i);
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability;
gEffectBattler = i;
gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i);
gBattlerAttacker = i;
BattleScriptPushCursor();
@ -9231,6 +9234,7 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd)
{
BestowItem(BATTLE_PARTNER(battler), battler);
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability;
gEffectBattler = battler;
gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler);
if (moveEnd)
BattleScriptPushCursor();

View File

@ -4627,9 +4627,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
break;
case ABILITY_EFFECT_SPORE:
{
u32 ability = GetBattlerAbility(gBattlerAttacker);
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
if ((!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS) || B_POWDER_GRASS < GEN_6)
&& ability != ABILITY_OVERCOAT
&& abilityAtk != ABILITY_OVERCOAT
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES)
{
u32 poison, paralysis, sleep;
@ -4657,7 +4657,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& IsBattlerAlive(gBattlerAttacker)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& IsBattlerTurnDamaged(gBattlerTarget)
&& CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE)
&& CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE)
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
{
if (IsSleepClauseEnabled())
@ -5553,17 +5553,23 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag)
bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause)
{
if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause)
if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause != NOT_BLOCKED_BY_SLEEP_CLAUSE)
return FALSE;
if (isBlockedBySleepClause == NOT_BLOCKED_BY_SLEEP_CLAUSE)
gBattleStruct->sleepClauseNotBlocked = TRUE;
bool32 effect = FALSE;
if (CanSetNonVolatileStatus(battlerAtk,
battlerDef,
ABILITY_NONE, // attacker ability does not matter
abilityDef,
MOVE_EFFECT_SLEEP, // also covers yawn
STATUS_CHECK_TRIGGER))
return TRUE;
return FALSE;
effect = TRUE;
gBattleStruct->sleepClauseNotBlocked = FALSE;
return effect;
}
bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef)
@ -5714,7 +5720,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u
{
battleScript = BattleScript_CantMakeAsleep;
}
else if (CanSleepDueToSleepClause(battlerAtk, battlerDef, option))
else if (!gBattleStruct->sleepClauseNotBlocked && CanSleepDueToSleepClause(battlerAtk, battlerDef, option))
{
battleScript = BattleScript_SleepClauseBlocked;
}

View File

@ -88,3 +88,21 @@ SINGLE_BATTLE_TEST("Effect Spore causes sleep 11% of the time")
STATUS_ICON(player, sleep: TRUE);
}
}
SINGLE_BATTLE_TEST("Effect Spore will check if it can inflict status onto attacker, not itself")
{
PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE);
GIVEN {
ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5);
ASSUME(MoveMakesContact(MOVE_SCRATCH));
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_BRELOOM) { Status1(STATUS1_BURN); Ability(ABILITY_EFFECT_SPORE); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player);
MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!");
STATUS_ICON(player, sleep: TRUE);
}
}

View File

@ -194,6 +194,27 @@ SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons pokemon for moves making con
}
}
SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison pokemon if they are already statused")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_WILL_O_WISP); }
TURN { MOVE(opponent, MOVE_BANEFUL_BUNKER); MOVE(player, MOVE_SCRATCH); }
TURN {}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, opponent);
STATUS_ICON(player, STATUS1_BURN);
ANIMATION(ANIM_TYPE_MOVE, MOVE_BANEFUL_BUNKER, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
HP_BAR(opponent);
STATUS_ICON(player, STATUS1_POISON);
}
}
}
SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making contact")
{
u16 usedMove = MOVE_NONE;
@ -226,6 +247,27 @@ SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making cont
}
}
SINGLE_BATTLE_TEST("Protect: Burning Bulwark can't burn pokemon if they are already statused")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TOXIC); }
TURN { MOVE(opponent, MOVE_BURNING_BULWARK); MOVE(player, MOVE_SCRATCH); }
TURN {}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent);
STATUS_ICON(player, STATUS1_TOXIC_POISON);
ANIMATION(ANIM_TYPE_MOVE, MOVE_BURNING_BULWARK, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
HP_BAR(opponent);
STATUS_ICON(player, STATUS1_BURN);
}
}
}
SINGLE_BATTLE_TEST("Protect: Recoil damage is not applied if target was protected")
{
u32 j, k;