Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added missing redirect abilities Gen 3-4 config #4920

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1507,18 +1507,10 @@
.4byte \jumpInstr
.endm

.macro jumpifrodaffected battler:req, jumpInstr:req
callnative BS_JumpIfRod
.4byte \jumpInstr
.endm

.macro jumpifabsorbaffected battler:req, jumpInstr:req
callnative BS_JumpIfAbsorb
.4byte \jumpInstr
.endm

.macro jumpifmotoraffected battler:req, jumpInstr:req
callnative BS_JumpIfMotor
.macro jumpifelectricabilityaffected battler:req, ability:req, jumpInstr:req
callnative BS_JumpIfElectricAbilityAffected
.byte \battler
.2byte \ability
.4byte \jumpInstr
.endm

Expand Down
8 changes: 4 additions & 4 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,9 @@ BattleScript_EffectTeatime::
waitanimation
setbyte gBattlerTarget, 0
BattleScript_TeatimeLoop:
jumpifrodaffected BS_TARGET, BattleScript_Teatimerod
jumpifabsorbaffected BS_TARGET, BattleScript_Teatimesorb
jumpifmotoraffected BS_TARGET, BattleScript_Teatimemotor
jumpifelectricabilityaffected BS_TARGET, ABILITY_LIGHTNING_ROD, BattleScript_Teatimerod
jumpifelectricabilityaffected BS_TARGET, ABILITY_VOLT_ABSORB, BattleScript_Teatimesorb
jumpifelectricabilityaffected BS_TARGET, ABILITY_MOTOR_DRIVE, BattleScript_Teatimemotor
jumpifteainvulnerable BS_TARGET, BattleScript_Teatimevul @ in semi-invulnerable state OR held item is not a Berry
orword gHitMarker, HITMARKER_DISABLE_ANIMATION | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE
setbyte sBERRY_OVERRIDE, TRUE @ override the requirements for eating berries
Expand Down Expand Up @@ -3609,7 +3609,7 @@ BattleScript_EffectParalyze::
BattleScript_BattleScript_EffectParalyzeNoTypeCalc:
jumpifmovehadnoeffect BattleScript_ButItFailed
jumpifstatus BS_TARGET, STATUS1_PARALYSIS, BattleScript_AlreadyParalyzed
jumpifabsorbaffected BS_TARGET, BattleScript_VoltAbsorbHeal
jumpifelectricabilityaffected BS_TARGET, ABILITY_VOLT_ABSORB, BattleScript_VoltAbsorbHeal
tryparalyzetype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
Expand Down
1 change: 1 addition & 0 deletions include/config/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
#define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms.
#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_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.
Expand Down
25 changes: 20 additions & 5 deletions src/battle_ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -943,19 +943,32 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
&& IsNonVolatileStatusMoveEffect(moveEffect))
RETURN_SCORE_MINUS(10);
break;
case ABILITY_VOLT_ABSORB:
case ABILITY_LIGHTNING_ROD:
if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5)
break;
// Fallthrough
case ABILITY_MOTOR_DRIVE:
case ABILITY_VOLT_ABSORB:
if (moveType == TYPE_ELECTRIC)
RETURN_SCORE_MINUS(20);
break;
case ABILITY_STORM_DRAIN:
if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5)
break;
// Fallthrough
case ABILITY_WATER_ABSORB:
case ABILITY_DRY_SKIN:
if (moveType == TYPE_WATER)
RETURN_SCORE_MINUS(20);
break;
case ABILITY_FLASH_FIRE:
if (moveType == TYPE_FIRE)
RETURN_SCORE_MINUS(20);
break;
case ABILITY_EARTH_EATER:
if (moveType == TYPE_GROUND)
RETURN_SCORE_MINUS(20);
break;
} // def ability checks

// target partner ability checks & not attacking partner
Expand Down Expand Up @@ -2820,7 +2833,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
break;
case ABILITY_LIGHTNING_ROD:
if (moveType == TYPE_ELECTRIC
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5
&& moveType == TYPE_ELECTRIC
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_SPECIAL)
&& BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_SPATK))
{
Expand All @@ -2836,7 +2850,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
break; // handled in AI_HPAware
case ABILITY_STORM_DRAIN:
if (moveType == TYPE_WATER
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5
&& moveType == TYPE_WATER
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_SPECIAL)
&& BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_SPATK))
{
Expand Down Expand Up @@ -4266,7 +4281,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
case EFFECT_ION_DELUGE:
if ((aiData->abilities[battlerAtk] == ABILITY_VOLT_ABSORB
|| aiData->abilities[battlerAtk] == ABILITY_MOTOR_DRIVE
|| aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD)
|| (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD))
&& gMovesInfo[predictedMove].type == TYPE_NORMAL)
ADJUST_SCORE(DECENT_EFFECT);
break;
Expand Down Expand Up @@ -4325,7 +4340,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
if (predictedMove != MOVE_NONE
&& (aiData->abilities[battlerAtk] == ABILITY_VOLT_ABSORB
|| aiData->abilities[battlerAtk] == ABILITY_MOTOR_DRIVE
|| aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD))
|| (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && aiData->abilities[battlerAtk] == ABILITY_LIGHTNING_ROD)))
{
ADJUST_SCORE(DECENT_EFFECT);
}
Expand Down
25 changes: 11 additions & 14 deletions src/battle_ai_switch_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,32 +334,29 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler, bool32 emitResult)
// Create an array of possible absorb abilities so the AI considers all of them
if (gMovesInfo[gLastLandedMoves[battler]].type == TYPE_FIRE)
{
absorbingTypeAbilities[0] = ABILITY_FLASH_FIRE;
numAbsorbingAbilities = 1;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_FLASH_FIRE;
}
else if (gMovesInfo[gLastLandedMoves[battler]].type == TYPE_WATER)
{
absorbingTypeAbilities[0] = ABILITY_WATER_ABSORB;
absorbingTypeAbilities[1] = ABILITY_STORM_DRAIN;
absorbingTypeAbilities[2] = ABILITY_DRY_SKIN;
numAbsorbingAbilities = 3;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_WATER_ABSORB;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_DRY_SKIN;
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5)
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_STORM_DRAIN;
}
else if (gMovesInfo[gLastLandedMoves[battler]].type == TYPE_ELECTRIC)
{
absorbingTypeAbilities[0] = ABILITY_VOLT_ABSORB;
absorbingTypeAbilities[1] = ABILITY_MOTOR_DRIVE;
absorbingTypeAbilities[2] = ABILITY_LIGHTNING_ROD;
numAbsorbingAbilities = 3;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_VOLT_ABSORB;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_MOTOR_DRIVE;
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5)
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_LIGHTNING_ROD;
}
else if (gMovesInfo[gLastLandedMoves[battler]].type == TYPE_GRASS)
{
absorbingTypeAbilities[0] = ABILITY_SAP_SIPPER;
numAbsorbingAbilities = 1;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_SAP_SIPPER;
}
else if (gMovesInfo[gLastLandedMoves[battler]].type == TYPE_GROUND)
{
absorbingTypeAbilities[0] = ABILITY_EARTH_EATER;
numAbsorbingAbilities = 1;
absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_EARTH_EATER;
}
else
{
Expand Down
10 changes: 8 additions & 2 deletions src/battle_ai_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,21 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef)

switch (battlerDefAbility)
{
case ABILITY_LIGHTNING_ROD:
if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5)
break;
// Fallthrough
case ABILITY_VOLT_ABSORB:
case ABILITY_MOTOR_DRIVE:
case ABILITY_LIGHTNING_ROD:
if (moveType == TYPE_ELECTRIC)
return TRUE;
break;
case ABILITY_STORM_DRAIN:
if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5)
break;
// Fallthrough
case ABILITY_WATER_ABSORB:
case ABILITY_DRY_SKIN:
case ABILITY_STORM_DRAIN:
if (moveType == TYPE_WATER)
return TRUE;
break;
Expand Down
30 changes: 8 additions & 22 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -8699,7 +8699,7 @@ static bool32 IsRototillerAffected(u32 battler)
return TRUE;
}

static bool32 IsElectricAbilityAffected(u32 ability)
static bool32 IsElectricAbilityAffected(u32 battler, u32 ability)
{
u32 moveType;

Expand All @@ -8710,7 +8710,9 @@ static bool32 IsElectricAbilityAffected(u32 ability)
else
moveType = gMovesInfo[gCurrentMove].type;

if (moveType == TYPE_ELECTRIC && GetBattlerAbility(gBattlerTarget) == ability)
if (moveType == TYPE_ELECTRIC
&& (ability != ABILITY_LIGHTNING_ROD || B_REDIRECT_ABILITY_IMMUNITY >= GEN_5)
&& GetBattlerAbility(battler) == ability)
return TRUE;
else
return FALSE;
Expand Down Expand Up @@ -16347,28 +16349,12 @@ void BS_JumpIfEmergencyExited(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}

void BS_JumpIfRod(void)
void BS_JumpIfElectricAbilityAffected(void)
{
NATIVE_ARGS(const u8 *jumpInstr);
if (IsElectricAbilityAffected(ABILITY_LIGHTNING_ROD))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}

void BS_JumpIfAbsorb(void)
{
NATIVE_ARGS(const u8 *jumpInstr);
if (IsElectricAbilityAffected(ABILITY_VOLT_ABSORB))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
NATIVE_ARGS(u8 battler, u16 ability, const u8 *jumpInstr);
u32 battler = GetBattlerForBattleScript(cmd->battler);

void BS_JumpIfMotor(void)
{
NATIVE_ARGS(const u8 *jumpInstr);
if (IsElectricAbilityAffected(ABILITY_MOTOR_DRIVE))
if (IsElectricAbilityAffected(battler, cmd->ability))
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
Expand Down
4 changes: 2 additions & 2 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -5080,11 +5080,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
effect = 2, statId = STAT_SPEED;
break;
case ABILITY_LIGHTNING_ROD:
if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS)
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS)
effect = 2, statId = STAT_SPATK;
break;
case ABILITY_STORM_DRAIN:
if (moveType == TYPE_WATER)
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_WATER)
effect = 2, statId = STAT_SPATK;
break;
case ABILITY_SAP_SIPPER:
Expand Down
73 changes: 73 additions & 0 deletions test/battle/ability/lightning_rod.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "global.h"
#include "test/battle.h"

SINGLE_BATTLE_TEST("Lightning Rod absorbs Electric-type moves and increases the Sp. Attack [Gen5+]")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); }
} WHEN {
TURN { MOVE(player, MOVE_THUNDERBOLT); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5) {
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent);
};
ABILITY_POPUP(opponent, ABILITY_LIGHTNING_ROD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Raichu's Sp. Atk rose!");
} else {
NONE_OF {
ABILITY_POPUP(opponent, ABILITY_LIGHTNING_ROD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Raichu's Sp. Atk rose!");
};
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
HP_BAR(opponent);
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
}
}

DOUBLE_BATTLE_TEST("Lightning Rod forces single-target Electric-type moves to target the Pokémon with this Ability.")
{
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(playerLeft, MOVE_THUNDERBOLT, target: opponentRight);
MOVE(playerRight, MOVE_THUNDERBOLT, target: opponentRight);
MOVE(opponentLeft, MOVE_CELEBRATE);
MOVE(opponentRight, MOVE_CELEBRATE);
}
} SCENE {
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5) {
NONE_OF {
HP_BAR(opponentLeft);
HP_BAR(opponentRight);
};
ABILITY_POPUP(opponentLeft, ABILITY_LIGHTNING_ROD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Foe Raichu's Sp. Atk rose!");
ABILITY_POPUP(opponentLeft, ABILITY_LIGHTNING_ROD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Foe Raichu's Sp. Atk rose!");
} else {
NONE_OF {
HP_BAR(opponentRight);
};
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, playerLeft);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, playerRight);
HP_BAR(opponentLeft);
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
}
}
Loading
Loading