Fixes Life Orb still activating if move was absorbed (#7521)
This commit is contained in:
parent
80a3a3b7ef
commit
7de3663f38
@ -169,7 +169,8 @@ struct ProtectStruct
|
||||
u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy
|
||||
u16 usedAllySwitch:1;
|
||||
u16 lashOutAffected:1;
|
||||
u16 padding:4;
|
||||
u16 assuranceDoubled:1;
|
||||
u16 padding:3;
|
||||
// End of 16-bit bitfield
|
||||
u16 physicalDmg;
|
||||
u16 specialDmg;
|
||||
|
||||
@ -2272,6 +2272,9 @@ static void Cmd_adjustdamage(void)
|
||||
gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1;
|
||||
gSpecialStatuses[battlerDef].enduredDamage = TRUE;
|
||||
}
|
||||
|
||||
if (gSpecialStatuses[battlerDef].enduredDamage)
|
||||
gProtectStructs[battlerDef].assuranceDoubled = TRUE;
|
||||
}
|
||||
|
||||
if (calcSpreadMoveDamage)
|
||||
@ -2726,6 +2729,7 @@ static void Cmd_datahpupdate(void)
|
||||
gProtectStructs[battler].physicalBattlerId = gBattlerAttacker;
|
||||
else
|
||||
gProtectStructs[battler].physicalBattlerId = gBattlerTarget;
|
||||
gProtectStructs[battler].assuranceDoubled = TRUE;
|
||||
}
|
||||
else if (!IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE) && effect != EFFECT_PAIN_SPLIT)
|
||||
{
|
||||
@ -2736,6 +2740,7 @@ static void Cmd_datahpupdate(void)
|
||||
gProtectStructs[battler].specialBattlerId = gBattlerAttacker;
|
||||
else
|
||||
gProtectStructs[battler].specialBattlerId = gBattlerTarget;
|
||||
gProtectStructs[battler].assuranceDoubled = TRUE;
|
||||
}
|
||||
}
|
||||
gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE;
|
||||
@ -3722,7 +3727,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
if (gBattleMons[gEffectBattler].statStages[i] != DEFAULT_STAT_STAGE)
|
||||
break;
|
||||
}
|
||||
if ((gSpecialStatuses[gEffectBattler].physicalDmg || gSpecialStatuses[gEffectBattler].specialDmg) && i != NUM_BATTLE_STATS)
|
||||
if (IsBattlerTurnDamaged(gEffectBattler) && i != NUM_BATTLE_STATS)
|
||||
{
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[gEffectBattler].statStages[i] = DEFAULT_STAT_STAGE;
|
||||
|
||||
@ -7155,10 +7155,8 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
case HOLD_EFFECT_LIFE_ORB:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& !IsBattleMoveStatus(gCurrentMove)
|
||||
&& (IsBattlerTurnDamaged(gBattlerTarget) || !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Needs the second check in case of Substitute
|
||||
&& (IsBattlerTurnDamaged(gBattlerTarget) || gBattleScripting.savedDmg > 0)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10;
|
||||
@ -8157,7 +8155,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData
|
||||
basePower = gBattleMons[battlerDef].hp * basePower / gBattleMons[battlerDef].maxHP;
|
||||
break;
|
||||
case EFFECT_ASSURANCE:
|
||||
if (gProtectStructs[battlerDef].physicalDmg != 0 || gProtectStructs[battlerDef].specialDmg != 0 || gProtectStructs[battlerDef].confusionSelfDmg)
|
||||
if (gProtectStructs[battlerDef].assuranceDoubled)
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_TRUMP_CARD:
|
||||
|
||||
@ -81,3 +81,53 @@ SINGLE_BATTLE_TEST("Life Orb doesn't cause any HP loss if user is unable to atta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate if on a confusion hit")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CONFUSE_RAY); MOVE(player, MOVE_POUND, WITH_RNG(RNG_CONFUSION, TRUE)); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
HP_BAR(player);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player);
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate if move was absorbed by target")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHOCK_WAVE); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHOCK_WAVE, player);
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb activates if move connected but no damage was dealt")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FALSE_SWIPE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, player);
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,3 +6,30 @@ TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in
|
||||
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Crash");
|
||||
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Confusion");
|
||||
TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Rocky Helmet");
|
||||
|
||||
DOUBLE_BATTLE_TEST("Assurance doubles in power if False Swipe connected but didn't do any damage")
|
||||
{
|
||||
s16 hits[2];
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_ASSURANCE, target: playerRight); }
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_FALSE_SWIPE, target: playerLeft);
|
||||
MOVE(playerLeft, MOVE_RECOVER);
|
||||
MOVE(opponentRight, MOVE_ASSURANCE, target: playerLeft);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSURANCE, opponentLeft);
|
||||
HP_BAR(playerRight, captureDamage: &hits[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSURANCE, opponentRight);
|
||||
HP_BAR(playerLeft, captureDamage: &hits[1]);
|
||||
} THEN {
|
||||
EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]);
|
||||
}
|
||||
}
|
||||
|
||||
19
test/battle/move_effect_secondary/clear_smog.c
Normal file
19
test/battle/move_effect_secondary/clear_smog.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Smog removes stat changes even if it did no damage")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SWORDS_DANCE); }
|
||||
TURN { MOVE(player, MOVE_ENDURE); MOVE(opponent, MOVE_CLEAR_SMOG); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CLEAR_SMOG, opponent);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user