Skip to content

Commit

Permalink
Added missing redirect abilities Gen 3-4 config (rh-hideout#4920)
Browse files Browse the repository at this point in the history
* Added missing redirect abilities Gen 3-4 config

* Combined 3 Battle Script Natives into 1

* Cleaner FindMonThatAbsorbsOpponentsMove
  • Loading branch information
AsparagusEduardo authored Jul 7, 2024
1 parent 60c7588 commit de609a2
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 63 deletions.
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 @@ -16346,28 +16348,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

0 comments on commit de609a2

Please sign in to comment.