diff --git a/include/config/battle.h b/include/config/battle.h index cdb0caacfe..8853d04324 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -142,6 +142,7 @@ #define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply. #define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases. #define B_REDIRECT_ABILITY_IMMUNITY GEN_LATEST // In Gen5+, Pokémon with Lightning Rod/Storm Drain become immune to Electric/Water-type moves and increase their Sp. Attack by 1 stage on top of the redirecting effect. +#define B_REDIRECT_ABILITY_ALLIES GEN_LATEST // In Gen4+, Lightning Rod/Storm Drain redirect ally's moves as well. #define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight. #define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail. #define B_TRANSISTOR_BOOST GEN_LATEST // In Gen9+, Transistor will only boost Electric-type moves by 1.3x as opposed to 1.5x. diff --git a/src/battle_util.c b/src/battle_util.c index 2c53b2282d..6d56a40e53 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -126,7 +126,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) // Functions void HandleAction_UseMove(void) { - u32 battler, i, side, moveType, var = 4; + u32 battler, i, side, moveType, ability, var = MAX_BATTLERS_COUNT; u16 moveTarget; gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; @@ -217,6 +217,7 @@ void HandleAction_UseMove(void) // choose target side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); + ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]); if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove) && moveTarget == MOVE_TARGET_SELECTED && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget)) @@ -226,16 +227,18 @@ void HandleAction_UseMove(void) else if (IsDoubleBattle() && gSideTimers[side].followmeTimer == 0 && (!IS_MOVE_STATUS(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS)) - && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) + && ((ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) + || (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { - side = GetBattlerSide(gBattlerAttacker); + // Find first battler that redirects the move (in turn order) for (battler = 0; battler < gBattlersCount; battler++) { - if (side != GetBattlerSide(battler) - && *(gBattleStruct->moveTarget + gBattlerAttacker) != battler - && ((GetBattlerAbility(battler) == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (GetBattlerAbility(battler) == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) + ability = GetBattlerAbility(battler); + if ((B_REDIRECT_ABILITY_ALLIES >= GEN_4 || !IsAlly(gBattlerAttacker, battler)) + && battler != gBattlerAttacker + && gBattleStruct->moveTarget[gBattlerAttacker] != battler + && ((ability == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) + || (ability == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) && GetBattlerTurnOrderNum(battler) < var && gMovesInfo[gCurrentMove].effect != EFFECT_SNIPE_SHOT && gMovesInfo[gCurrentMove].effect != EFFECT_PLEDGE @@ -245,7 +248,7 @@ void HandleAction_UseMove(void) var = GetBattlerTurnOrderNum(battler); } } - if (var == 4) + if (var == MAX_BATTLERS_COUNT) { if (moveTarget & MOVE_TARGET_RANDOM) { @@ -8446,22 +8449,36 @@ u32 GetMoveTarget(u16 move, u8 setTarget) } else { + u32 battlerAbilityOnField = 0; + targetBattler = SetRandomTarget(gBattlerAttacker); - if (moveType == TYPE_ELECTRIC - && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD) - && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) + if (moveType == TYPE_ELECTRIC && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) { - targetBattler ^= BIT_FLANK; - RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + if (B_REDIRECT_ABILITY_ALLIES >= GEN_4) + battlerAbilityOnField = IsAbilityOnField(ABILITY_LIGHTNING_ROD); + else + battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_LIGHTNING_ROD); + + if (battlerAbilityOnField > 0) + { + targetBattler = battlerAbilityOnField - 1; + RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); + gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + } } - else if (moveType == TYPE_WATER - && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_STORM_DRAIN) - && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) + else if (moveType == TYPE_WATER && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) { - targetBattler ^= BIT_FLANK; - RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].stormDrainRedirected = TRUE; + if (B_REDIRECT_ABILITY_ALLIES >= GEN_4) + battlerAbilityOnField = IsAbilityOnField(ABILITY_STORM_DRAIN); + else + battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_STORM_DRAIN); + + if (battlerAbilityOnField > 0) + { + targetBattler = battlerAbilityOnField - 1; + RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); + gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + } } } break; diff --git a/test/battle/ability/lightning_rod.c b/test/battle/ability/lightning_rod.c index c719ee145d..38903f373b 100644 --- a/test/battle/ability/lightning_rod.c +++ b/test/battle/ability/lightning_rod.c @@ -71,3 +71,29 @@ DOUBLE_BATTLE_TEST("Lightning Rod forces single-target Electric-type moves to ta ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); } } + +DOUBLE_BATTLE_TEST("Lightning Rod redirects an ally's attack") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, MOVE_THUNDERBOLT, target: playerLeft); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Thunderbolt!"); + if (B_REDIRECT_ABILITY_ALLIES >= GEN_5) + { + NOT HP_BAR(playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_LIGHTNING_ROD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Raichu's Sp. Atk rose!"); + } + else + { + HP_BAR(playerLeft); + } + } +} diff --git a/test/battle/move_effect/pledge.c b/test/battle/move_effect/pledge.c index 726adc8152..4441fdccb9 100644 --- a/test/battle/move_effect/pledge.c +++ b/test/battle/move_effect/pledge.c @@ -886,7 +886,7 @@ DOUBLE_BATTLE_TEST("Pledge move combo doesn't trigger on opponent's Pledge move { GIVEN { ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY); - PLAYER(SPECIES_MAROWAK) { Ability(ABILITY_LIGHTNING_ROD); } + PLAYER(SPECIES_ELECTIVIRE) { Ability(ABILITY_MOTOR_DRIVE); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT);