Fixes Tera Shell activating on moves that have no effect on target (#6271)
This commit is contained in:
parent
bf263efa4b
commit
3dd0f95ddd
@ -51,7 +51,6 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem);
|
||||
u8 GetCatchingBattler(void);
|
||||
u32 GetHighestStatId(u32 battlerId);
|
||||
bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType);
|
||||
bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef);
|
||||
bool32 IsMoveNotAllowedInSkyBattles(u32 move);
|
||||
bool32 DoSwitchInAbilities(u32 battlerId);
|
||||
u8 GetFirstFaintedPartyIndex(u8 battlerId);
|
||||
|
||||
@ -1148,19 +1148,6 @@ bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef)
|
||||
{
|
||||
if (!gSpecialStatuses[battlerDef].distortedTypeMatchups
|
||||
&& gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL
|
||||
&& gBattleMons[battlerDef].hp == gBattleMons[battlerDef].maxHP
|
||||
&& !IsBattleMoveStatus(move)
|
||||
&& !(gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT)
|
||||
&& GetBattlerAbility(battlerDef) == ABILITY_TERA_SHELL)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsMoveNotAllowedInSkyBattles(u32 move)
|
||||
{
|
||||
return (gBattleStruct->isSkyBattle && IsMoveSkyBattleBanned(gCurrentMove));
|
||||
@ -2009,10 +1996,21 @@ static void Cmd_critcalc(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static inline void GetShellSideArmCategory(u32 battlerDef)
|
||||
static inline void CalculateAndSetMoveDamage(struct DamageCalculationData *damageCalcData, u32 battlerDef)
|
||||
{
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_SHELL_SIDE_ARM)
|
||||
gBattleStruct->swapDamageCategory = (gBattleStruct->shellSideArmCategory[gBattlerAttacker][battlerDef] != GetMoveCategory(gCurrentMove));
|
||||
|
||||
damageCalcData->battlerDef = battlerDef;
|
||||
damageCalcData->isCrit = gSpecialStatuses[battlerDef].criticalHit;
|
||||
gBattleStruct->moveDamage[battlerDef] = CalculateMoveDamage(damageCalcData, 0);
|
||||
|
||||
// Slighly hacky but we need to check move result flags for distortion match-up as well but it can only be done after damage calcs
|
||||
if (gSpecialStatuses[battlerDef].distortedTypeMatchups && gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT)
|
||||
{
|
||||
gSpecialStatuses[battlerDef].distortedTypeMatchups = FALSE;
|
||||
gSpecialStatuses[battlerDef].teraShellAbilityDone = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_damagecalc(void)
|
||||
@ -2044,28 +2042,12 @@ static void Cmd_damagecalc(void)
|
||||
|| gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT)
|
||||
continue;
|
||||
|
||||
if (ShouldTeraShellDistortTypeMatchups(gCurrentMove, battlerDef))
|
||||
{
|
||||
gSpecialStatuses[battlerDef].distortedTypeMatchups = TRUE;
|
||||
gSpecialStatuses[battlerDef].teraShellAbilityDone = TRUE;
|
||||
}
|
||||
GetShellSideArmCategory(battlerDef);
|
||||
damageCalcData.battlerDef = battlerDef;
|
||||
damageCalcData.isCrit = gSpecialStatuses[battlerDef].criticalHit;
|
||||
gBattleStruct->moveDamage[battlerDef] = CalculateMoveDamage(&damageCalcData, 0);
|
||||
CalculateAndSetMoveDamage(&damageCalcData, battlerDef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ShouldTeraShellDistortTypeMatchups(gCurrentMove, gBattlerTarget))
|
||||
{
|
||||
gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = TRUE;
|
||||
gSpecialStatuses[gBattlerTarget].teraShellAbilityDone = TRUE;
|
||||
}
|
||||
GetShellSideArmCategory(gBattlerTarget);
|
||||
damageCalcData.battlerDef = gBattlerTarget;
|
||||
damageCalcData.isCrit = gSpecialStatuses[gBattlerTarget].criticalHit;
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = CalculateMoveDamage(&damageCalcData, 0);
|
||||
CalculateAndSetMoveDamage(&damageCalcData, gBattlerTarget);
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
||||
@ -65,6 +65,7 @@ static u32 GetFlingPowerFromItemId(u32 itemId);
|
||||
static void SetRandomMultiHitCounter();
|
||||
static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item);
|
||||
static bool32 CanBeInfinitelyConfused(u32 battler);
|
||||
|
||||
ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent);
|
||||
ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent);
|
||||
|
||||
@ -201,10 +202,10 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] =
|
||||
},
|
||||
};
|
||||
|
||||
static u8 CalcBeatUpPower(void)
|
||||
static u32 CalcBeatUpPower(void)
|
||||
{
|
||||
u8 basePower;
|
||||
u16 species;
|
||||
u32 basePower;
|
||||
u32 species;
|
||||
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
|
||||
|
||||
// Party slot is incremented by the battle script for Beat Up after this damage calculation
|
||||
@ -214,6 +215,18 @@ static u8 CalcBeatUpPower(void)
|
||||
return basePower;
|
||||
}
|
||||
|
||||
static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, u32 abilityDef)
|
||||
{
|
||||
if (!gSpecialStatuses[battlerDef].distortedTypeMatchups
|
||||
&& gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL
|
||||
&& gBattleMons[battlerDef].hp == gBattleMons[battlerDef].maxHP
|
||||
&& !IsBattleMoveStatus(move)
|
||||
&& abilityDef == ABILITY_TERA_SHELL)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
|
||||
{
|
||||
u32 ability = GetBattlerAbility(battlerAtk);
|
||||
@ -10562,7 +10575,7 @@ s32 CalculateMoveDamageVars(struct DamageCalculationData *damageCalcData, u32 fi
|
||||
holdEffectAtk, holdEffectDef, abilityAtk, abilityDef);
|
||||
}
|
||||
|
||||
static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 moveType, u32 battlerDef, u32 defType, u32 battlerAtk, bool32 recordAbilities)
|
||||
static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 moveType, u32 battlerDef, u32 defAbility, u32 defType, u32 battlerAtk, bool32 recordAbilities)
|
||||
{
|
||||
uq4_12_t mod = GetTypeModifier(moveType, defType);
|
||||
u32 abilityAtk = GetBattlerAbility(battlerAtk);
|
||||
@ -10602,11 +10615,15 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
|
||||
mod = UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
if (gSpecialStatuses[battlerDef].distortedTypeMatchups || (AI_DATA->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef)))
|
||||
if (gSpecialStatuses[battlerDef].distortedTypeMatchups || (mod > UQ_4_12(0.0) && ShouldTeraShellDistortTypeMatchups(move, battlerDef, defAbility)))
|
||||
{
|
||||
mod = UQ_4_12(0.5);
|
||||
if (recordAbilities)
|
||||
RecordAbilityBattle(battlerDef, GetBattlerAbility(battlerDef));
|
||||
{
|
||||
RecordAbilityBattle(battlerDef, defAbility);
|
||||
gSpecialStatuses[battlerDef].distortedTypeMatchups = TRUE;
|
||||
gSpecialStatuses[battlerDef].teraShellAbilityDone = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
*modifier = uq4_12_multiply(*modifier, mod);
|
||||
@ -10616,9 +10633,9 @@ static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType,
|
||||
{
|
||||
// Check if the type effectiveness would've been different if the pokemon really had the types as the disguise.
|
||||
uq4_12_t presumedModifier = UQ_4_12(1.0);
|
||||
MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, gSpeciesInfo[illusionSpecies].types[0], battlerAtk, FALSE);
|
||||
MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, ABILITY_ILLUSION, gSpeciesInfo[illusionSpecies].types[0], battlerAtk, FALSE);
|
||||
if (gSpeciesInfo[illusionSpecies].types[1] != gSpeciesInfo[illusionSpecies].types[0])
|
||||
MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, gSpeciesInfo[illusionSpecies].types[1], battlerAtk, FALSE);
|
||||
MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, ABILITY_ILLUSION, gSpeciesInfo[illusionSpecies].types[1], battlerAtk, FALSE);
|
||||
|
||||
if (presumedModifier != resultingModifier)
|
||||
RecordAbilityBattle(battlerDef, ABILITY_ILLUSION);
|
||||
@ -10654,11 +10671,11 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov
|
||||
u32 types[3];
|
||||
GetBattlerTypes(battlerDef, FALSE, types);
|
||||
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, types[0], battlerAtk, recordAbilities);
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, defAbility, types[0], battlerAtk, recordAbilities);
|
||||
if (types[1] != types[0])
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, types[1], battlerAtk, recordAbilities);
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, defAbility, types[1], battlerAtk, recordAbilities);
|
||||
if (types[2] != TYPE_MYSTERY && types[2] != types[1] && types[2] != types[0])
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, types[2], battlerAtk, recordAbilities);
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, defAbility, types[2], battlerAtk, recordAbilities);
|
||||
if (moveType == TYPE_FIRE && gDisableStructs[battlerDef].tarShot)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
|
||||
|
||||
@ -10740,9 +10757,9 @@ uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 a
|
||||
|
||||
if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY)
|
||||
{
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, 0, gSpeciesInfo[speciesDef].types[0], 0, FALSE);
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, 0, 0, gSpeciesInfo[speciesDef].types[0], 0, FALSE);
|
||||
if (gSpeciesInfo[speciesDef].types[1] != gSpeciesInfo[speciesDef].types[0])
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, 0, gSpeciesInfo[speciesDef].types[1], 0, FALSE);
|
||||
MulByTypeEffectiveness(&modifier, move, moveType, 0, 0, gSpeciesInfo[speciesDef].types[1], 0, FALSE);
|
||||
|
||||
if (moveType == TYPE_GROUND && abilityDef == ABILITY_LEVITATE && !(gFieldStatuses & STATUS_FIELD_GRAVITY))
|
||||
modifier = UQ_4_12(0.0);
|
||||
@ -10778,9 +10795,9 @@ uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType)
|
||||
|
||||
if (moveType != TYPE_MYSTERY)
|
||||
{
|
||||
MulByTypeEffectiveness(&modifier, MOVE_POUND, moveType, 0, type1, 0, FALSE);
|
||||
MulByTypeEffectiveness(&modifier, MOVE_POUND, moveType, 0, 0, type1, 0, FALSE);
|
||||
if (type2 != type1)
|
||||
MulByTypeEffectiveness(&modifier, MOVE_POUND, moveType, 0, type2, 0, FALSE);
|
||||
MulByTypeEffectiveness(&modifier, MOVE_POUND, moveType, 0, 0, type2, 0, FALSE);
|
||||
|
||||
if ((modifier <= UQ_4_12(1.0) && abilityDef == ABILITY_WONDER_GUARD)
|
||||
|| (moveType == TYPE_FIRE && abilityDef == ABILITY_FLASH_FIRE)
|
||||
|
||||
@ -97,3 +97,18 @@ DOUBLE_BATTLE_TEST("Tera Shell only makes the first hit against Terapagos from a
|
||||
NOT MESSAGE("It's not very effective…");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Tera Shell respects immunity")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_TERAPAGOS_TERASTAL) { Ability(ABILITY_TERA_SHELL); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SHADOW_BALL); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_TERA_SHELL);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHADOW_BALL, opponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -704,3 +704,4 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user