diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index 3c946aaa0a..4eb1b9ddc3 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -48,7 +48,7 @@ u32 GetBattlerTurnOrderNum(u32 battler); bool32 NoAliveMonsForBattlerSide(u32 battler); bool32 NoAliveMonsForPlayer(void); bool32 NoAliveMonsForEitherParty(void); -void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, bool32 primary, bool32 certain); +void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, enum SetMoveEffectFlags effectFlags); bool32 CanBattlerSwitch(u32 battlerId); void BattleDestroyYesNoCursorAt(u8 cursorPosition); void BattleCreateYesNoCursorAt(u8 cursorPosition); diff --git a/include/constants/battle.h b/include/constants/battle.h index 7e7de5bcf8..19ee13e478 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -252,7 +252,7 @@ enum SemiInvulnerableExclusion #define HITMARKER_UNUSED_10 (1 << 10) #define HITMARKER_UNUSED_11 (1 << 11) #define HITMARKER_UNUSED_12 (1 << 12) -#define HITMARKER_STATUS_ABILITY_EFFECT (1 << 13) +#define HITMARKER_UNUSED_13 (1 << 13) #define HITMARKER_UNUSED_14 (1 << 14) #define HITMARKER_RUN (1 << 15) #define HITMARKER_UNUSED_16 (1 << 16) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 16d7f75d56..dbde3e06d9 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -125,6 +125,13 @@ enum CmdVarious #define PARTY_SCREEN_OPTIONAL (1 << 7) // Flag for first argument to openpartyscreen +enum SetMoveEffectFlags +{ + NO_FLAGS = 0, + EFFECT_PRIMARY = (1 << 0), + EFFECT_CERTAIN = (1 << 1), +}; + // cases for Cmd_moveend - Order matters! enum MoveEndEffects { diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 2de422baa9..817267936b 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -369,7 +369,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleMons[battler].volatiles.multipleTurns = FALSE; if (!gBattleMons[battler].volatiles.confusionTurns) { - SetMoveEffect(battler, battler, MOVE_EFFECT_CONFUSION, gBattlescriptCurrInstr, TRUE, FALSE); + SetMoveEffect(battler, battler, MOVE_EFFECT_CONFUSION, gBattlescriptCurrInstr, EFFECT_PRIMARY); if (gBattleMons[battler].volatiles.confusionTurns) BattleScriptExecute(BattleScript_ThrashConfuses); effect = TRUE; diff --git a/src/battle_hold_effects.c b/src/battle_hold_effects.c index bb92caa763..d262e024a7 100644 --- a/src/battle_hold_effects.c +++ b/src/battle_hold_effects.c @@ -218,7 +218,7 @@ static enum ItemEffect TryKingsRock(u32 battlerAtk, u32 battlerDef, u32 item) && RandomPercentage(RNG_HOLD_EFFECT_FLINCH, holdEffectParam) && ability != ABILITY_STENCH) { - SetMoveEffect(battlerAtk, battlerDef, MOVE_EFFECT_FLINCH, gBattlescriptCurrInstr, FALSE, FALSE); + SetMoveEffect(battlerAtk, battlerDef, MOVE_EFFECT_FLINCH, gBattlescriptCurrInstr, NO_FLAGS); effect = ITEM_EFFECT_OTHER; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a24a0d23a6..59b4bebd90 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2931,9 +2931,11 @@ static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, cons } // To avoid confusion the arguments are naned battler/effectBattler since they can be different from gBattlerAttacker/gBattlerTarget -void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, bool32 primary, bool32 certain) +void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, const u8 *battleScript, enum SetMoveEffectFlags effectFlags) { s32 i; + bool32 primary = effectFlags & EFFECT_PRIMARY; + bool32 certain = effectFlags & EFFECT_CERTAIN; bool32 affectsUser = (battler == effectBattler); bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR); union StatChangeFlags flags = {0}; @@ -2967,14 +2969,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c gEffectBattler = effectBattler; battlerAbility = GetBattlerAbility(gEffectBattler); - if (!primary && !affectsUser - && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && IsMoveEffectBlockedByTarget(battlerAbility)) + if (!primary && !affectsUser && IsMoveEffectBlockedByTarget(battlerAbility)) moveEffect = MOVE_EFFECT_NONE; - else if (!(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) + else if (!primary && TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove) - && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE) - && !primary) + && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE)) moveEffect = MOVE_EFFECT_NONE; else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint) moveEffect = MOVE_EFFECT_NONE; @@ -2982,7 +2981,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c moveEffect = MOVE_EFFECT_NONE; gBattleScripting.moveEffect = moveEffect; // ChangeStatBuffs still needs the global moveEffect - + switch (moveEffect) { case MOVE_EFFECT_NONE: @@ -2995,7 +2994,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c case MOVE_EFFECT_PARALYSIS: case MOVE_EFFECT_TOXIC: case MOVE_EFFECT_FROSTBITE: - if (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && !primary) + if (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !primary) gBattlescriptCurrInstr = battleScript; else if (CanSetNonVolatileStatus( gBattlerAttacker, @@ -3009,7 +3008,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c case MOVE_EFFECT_CONFUSION: if (!CanBeConfused(gEffectBattler) || gBattleMons[gEffectBattler].volatiles.confusionTurns - || (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && !primary)) + || (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !primary)) { gBattlescriptCurrInstr = battleScript; } @@ -3126,7 +3125,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c MOVE_EFFECT_FREEZE_OR_FROSTBITE, MOVE_EFFECT_PARALYSIS }; - SetMoveEffect(battler, effectBattler, RandomElement(RNG_TRI_ATTACK, sTriAttackEffects), battleScript, primary, certain); + SetMoveEffect(battler, effectBattler, RandomElement(RNG_TRI_ATTACK, sTriAttackEffects), battleScript, effectFlags); } break; case MOVE_EFFECT_WRAP: @@ -3477,7 +3476,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c if (!gBattleMons[gEffectBattler].status1) { static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP }; - SetMoveEffect(battler, effectBattler, RandomElement(RNG_DIRE_CLAW, sDireClawEffects), battleScript, primary, certain); + SetMoveEffect(battler, effectBattler, RandomElement(RNG_DIRE_CLAW, sDireClawEffects), battleScript, effectFlags); } break; case MOVE_EFFECT_STEALTH_ROCK: @@ -3524,7 +3523,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c } } else - SetMoveEffect(battler, effectBattler, gBattleEnvironmentInfo[gBattleEnvironment].secretPowerEffect, battleScript, primary, certain); + SetMoveEffect(battler, effectBattler, gBattleEnvironmentInfo[gBattleEnvironment].secretPowerEffect, battleScript, effectFlags); break; case MOVE_EFFECT_PSYCHIC_NOISE: battlerAbility = IsAbilityOnSide(gEffectBattler, ABILITY_AROMA_VEIL); @@ -4103,13 +4102,16 @@ static void Cmd_setadditionaleffects(void) { gBattleCommunication[MULTISTRING_CHOOSER] = *((u8 *) &additionalEffect->multistring); + enum SetMoveEffectFlags flags = NO_FLAGS; + if (percentChance == 0) flags |= EFFECT_PRIMARY; + if (percentChance >= 100) flags |= EFFECT_CERTAIN; + SetMoveEffect( gBattlerAttacker, additionalEffect->self ? gBattlerAttacker : gBattlerTarget, additionalEffect->moveEffect, cmd->nextInstr, - percentChance == 0, // a primary effect - percentChance >= 100 // certain to happen + flags ); } } @@ -4144,7 +4146,7 @@ static void Cmd_seteffectprimary(void) u32 battler = GetBattlerForBattleScript(cmd->battler); u32 effectBattler = GetBattlerForBattleScript(cmd->effectBattler); - SetMoveEffect(battler, effectBattler, gBattleScripting.moveEffect, cmd->nextInstr, TRUE, FALSE); + SetMoveEffect(battler, effectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY); } static void Cmd_seteffectsecondary(void) @@ -4153,7 +4155,7 @@ static void Cmd_seteffectsecondary(void) u32 battler = GetBattlerForBattleScript(cmd->battler); u32 effectBattler = GetBattlerForBattleScript(cmd->effectBattler); - SetMoveEffect(battler, effectBattler, gBattleScripting.moveEffect, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(battler, effectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY); } static void Cmd_clearvolatile(void) @@ -14331,7 +14333,7 @@ static void Cmd_setnonvolatilestatus(void) { case TRIGGER_ON_ABILITY: if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION) - SetMoveEffect(gBattleScripting.battler, gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(gBattleScripting.battler, gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, EFFECT_PRIMARY); else SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, cmd->nextInstr, TRIGGER_ON_ABILITY); break; @@ -16356,22 +16358,22 @@ void BS_TryFlingHoldEffect(void) switch (holdEffect) { case HOLD_EFFECT_FLAME_ORB: - SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_BURN, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_BURN, cmd->nextInstr, NO_FLAGS); break; case HOLD_EFFECT_TOXIC_ORB: - SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_TOXIC, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_TOXIC, cmd->nextInstr, NO_FLAGS); break; case HOLD_EFFECT_LIGHT_BALL: - SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_PARALYSIS, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_PARALYSIS, cmd->nextInstr, NO_FLAGS); break; case HOLD_EFFECT_TYPE_POWER: if (GetItemSecondaryId(gLastUsedItem) != TYPE_POISON) gBattlescriptCurrInstr = cmd->nextInstr; else - SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_POISON, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_POISON, cmd->nextInstr, NO_FLAGS); break; case HOLD_EFFECT_FLINCH: - SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_FLINCH, cmd->nextInstr, FALSE, FALSE); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_FLINCH, cmd->nextInstr, NO_FLAGS); break; case HOLD_EFFECT_MENTAL_HERB: if (ItemBattleEffects(gBattlerTarget, 0, holdEffect, IsOnFlingActivation)) diff --git a/src/battle_util.c b/src/battle_util.c index b3450ab78a..4a8b436362 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -914,7 +914,7 @@ void HandleAction_NothingIsFainted(void) gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; - gHitMarker &= ~(HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_OBEYS); + gHitMarker &= ~(HITMARKER_OBEYS); } void HandleAction_ActionFinished(void) @@ -925,7 +925,7 @@ void HandleAction_ActionFinished(void) gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; memset(&gSpecialStatuses, 0, sizeof(gSpecialStatuses)); - gHitMarker &= ~(HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_OBEYS); + gHitMarker &= ~(HITMARKER_OBEYS); ClearDamageCalcResults(); gCurrentMove = 0; @@ -4969,7 +4969,6 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab SET_STATCHANGER(STAT_SPEED, 1, TRUE); PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptCall(BattleScript_GooeyActivates); - gHitMarker |= HITMARKER_STATUS_ABILITY_EFFECT; effect++; } break; @@ -5326,7 +5325,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab && IsBattlerTurnDamaged(gBattlerTarget) && !MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_FLINCH)) { - SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_FLINCH, gBattlescriptCurrInstr, FALSE, FALSE); + SetMoveEffect(gBattlerAttacker, gBattlerTarget, MOVE_EFFECT_FLINCH, gBattlescriptCurrInstr, EFFECT_PRIMARY); effect++; } break; @@ -5349,7 +5348,6 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptCall(BattleScript_AbilityStatusEffect); - gHitMarker |= HITMARKER_STATUS_ABILITY_EFFECT; effect++; } break; diff --git a/test/battle/ability/tangling_hair.c b/test/battle/ability/tangling_hair.c index 849c83df64..fdae4de06d 100644 --- a/test/battle/ability/tangling_hair.c +++ b/test/battle/ability/tangling_hair.c @@ -97,3 +97,17 @@ SINGLE_BATTLE_TEST("Tangling Hair does not trigger on Clear Body") NOT ABILITY_POPUP(player, ABILITY_TANGLING_HAIR); } } + +SINGLE_BATTLE_TEST("Tangling Hair will trigger if move is boosted by Sheer Force") +{ + ASSUME(MoveIsAffectedBySheerForce(MOVE_POISON_JAB)); + GIVEN { + PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_TANGLING_HAIR); } + OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); }; + } WHEN { + TURN { MOVE(opponent, MOVE_POISON_JAB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_JAB, opponent); + ABILITY_POPUP(player, ABILITY_TANGLING_HAIR); + } +}