From 1dadc79b8bb60d72af7e145f003b2d96e65171b9 Mon Sep 17 00:00:00 2001 From: Nephrite Date: Mon, 20 Nov 2023 19:39:13 +0900 Subject: [PATCH] Triple Arrows redo Sorry, Lunos --- data/battle_scripts_1.s | 6 +--- include/battle_util.h | 1 + include/constants/battle.h | 5 ++- include/constants/battle_move_effects.h | 2 +- include/random.h | 2 -- src/battle_ai_main.c | 5 +-- src/battle_ai_util.c | 32 +++++++++--------- src/battle_script_commands.c | 43 +++++++++---------------- src/battle_util.c | 13 +++++++- src/data/battle_moves.h | 7 ++-- test/battle/move.c | 2 +- test/battle/move_effect/triple_arrows.c | 7 ++-- 12 files changed, 61 insertions(+), 64 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a6c9d54eed..0c74162e81 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -425,7 +425,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectRevivalBlessing @ EFFECT_REVIVAL_BLESSING .4byte BattleScript_EffectFrostbiteHit @ EFFECT_FROSTBITE_HIT .4byte BattleScript_EffectSnow @ EFFECT_SNOWSCAPE - .4byte BattleScript_EffectTripleArrows @ EFFECT_TRIPLE_ARROWS + .4byte BattleScript_EffectHit @ EFFECT_UNUSED_399 .4byte BattleScript_EffectInfernalParade @ EFFECT_INFERNAL_PARADE .4byte BattleScript_EffectTakeHeart @ EFFECT_TAKE_HEART .4byte BattleScript_EffectAxeKick @ EFFECT_AXE_KICK @@ -565,10 +565,6 @@ BattleScript_EffectTakeHeart:: jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_CalmMindStatRaise goto BattleScript_CantRaiseMultipleStats -BattleScript_EffectTripleArrows:: - setmoveeffect MOVE_EFFECT_TRIPLE_ARROWS - goto BattleScript_EffectHit - BattleScript_EffectRevivalBlessing:: attackcanceler attackstring diff --git a/include/battle_util.h b/include/battle_util.h index 91362bbeaf..6e3f6a09d6 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -221,6 +221,7 @@ void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon); void RecalcBattlerStats(u32 battler, struct Pokemon *mon); bool32 IsAlly(u32 battlerAtk, u32 battlerDef); bool32 IsGen6ExpShareEnabled(void); +bool32 MoveHasMoveEffect(u16 move, u16 moveEffect); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/include/constants/battle.h b/include/constants/battle.h index c8b53f4ca8..1beb9f490c 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -385,10 +385,9 @@ #define MOVE_EFFECT_DIRE_CLAW 74 #define MOVE_EFFECT_STEALTH_ROCK 75 #define MOVE_EFFECT_SPIKES 76 -#define MOVE_EFFECT_TRIPLE_ARROWS 77 -#define MOVE_EFFECT_SYRUP_BOMB 78 +#define MOVE_EFFECT_SYRUP_BOMB 77 -#define NUM_MOVE_EFFECTS 79 +#define NUM_MOVE_EFFECTS 78 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 4e21557766..f403a79254 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -402,7 +402,7 @@ #define EFFECT_REVIVAL_BLESSING 396 #define EFFECT_FROSTBITE_HIT 397 #define EFFECT_SNOWSCAPE 398 -#define EFFECT_TRIPLE_ARROWS 399 +#define EFFECT_UNUSED_399 399 #define EFFECT_INFERNAL_PARADE 400 #define EFFECT_TAKE_HEART 401 #define EFFECT_AXE_KICK 402 diff --git a/include/random.h b/include/random.h index 2fe536d66b..0f60dd7ad5 100644 --- a/include/random.h +++ b/include/random.h @@ -96,8 +96,6 @@ enum RandomTag RNG_STATIC, RNG_STENCH, RNG_TRI_ATTACK, - RNG_TRIPLE_ARROWS_DEFENSE_DOWN, - RNG_TRIPLE_ARROWS_FLINCH, RNG_QUICK_DRAW, }; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 651329c766..19c8feebef 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4881,10 +4881,11 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score break; } // move effect checks - // check move additional effects + // check move additional effects that are certain/100% likely to happen for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++) { - if (gBattleMoves[move].additionalEffects[i].self) + if (gBattleMoves[move].additionalEffects[i].self + || gBattleMoves[move].additionalEffects[i].chance % 100) continue; switch (gBattleMoves[move].additionalEffects[i].moveEffect) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 4f2aa642a0..810d52fe17 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -843,6 +843,22 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 u32 abilityDef = AI_DATA->abilities[battlerDef]; u32 abilityAtk = AI_DATA->abilities[battlerAtk]; + // check ADDITIONAL_EFFECTS + for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++) + { + // Obviously ignore moves that target self + if (gBattleMoves[move].additionalEffects[i].self) + continue; + + switch (gBattleMoves[move].additionalEffects[i].moveEffect) + { + case MOVE_EFFECT_PARALYSIS: + if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE)) + return TRUE; + break; + } + } + switch (gBattleMoves[move].effect) { case EFFECT_HIT: @@ -947,22 +963,6 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 } return FALSE; - - // check ADDITIONAL_EFFECTS - for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++) - { - // Obviously ignore moves that target self - if (gBattleMoves[move].additionalEffects[i].self) - continue; - - switch (gBattleMoves[move].additionalEffects[i].moveEffect) - { - case MOVE_EFFECT_PARALYSIS: - if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE)) - return TRUE; - break; - } - } } static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s32 noOfHitsToKo) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5f6ae074e7..2b4a86aea8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3078,13 +3078,17 @@ void SetMoveEffect(bool32 primary, u32 certain) } break; case MOVE_EFFECT_FLINCH: - if (battlerAbility == ABILITY_INNER_FOCUS - && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + if (battlerAbility == ABILITY_INNER_FOCUS) { - gLastUsedAbility = ABILITY_INNER_FOCUS; - gBattlerAbility = gEffectBattler; - RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS); - gBattlescriptCurrInstr = BattleScript_FlinchPrevention; + // Inner Focus ALWAYS prevents flinching but only activates + // on a move that's supposed to flinch, like Fake Out + if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN) + { + gLastUsedAbility = ABILITY_INNER_FOCUS; + gBattlerAbility = gEffectBattler; + RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS); + gBattlescriptCurrInstr = BattleScript_FlinchPrevention; + } } else if (GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber && !IsDynamaxed(gEffectBattler)) @@ -3595,26 +3599,6 @@ void SetMoveEffect(bool32 primary, u32 certain) BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_SpikesActivates; } - break; - case MOVE_EFFECT_TRIPLE_ARROWS: - { - u8 randomLowerDefenseChance = RandomPercentage(RNG_TRIPLE_ARROWS_DEFENSE_DOWN, CalcSecondaryEffectChance(gBattlerAttacker, 50)); - u8 randomFlinchChance = RandomPercentage(RNG_TRIPLE_ARROWS_FLINCH, CalcSecondaryEffectChance(gBattlerAttacker, 30)); - - if (randomFlinchChance && battlerAbility != ABILITY_INNER_FOCUS && GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber) - gBattleMons[gEffectBattler].status2 |= sStatusFlagsForMoveEffects[MOVE_EFFECT_FLINCH]; - - if (randomLowerDefenseChance) - { - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_DefDown; - } - else - { - gBattlescriptCurrInstr++; - } - } - break; case MOVE_EFFECT_SYRUP_BOMB: if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB)) @@ -3669,12 +3653,15 @@ static void Cmd_seteffectwithchance(void) // In reverse array order so that effects are applied in correct order for (i = gBattleMoves[gCurrentMove].numAdditionalEffects; i > 0; i--) { - percentChance = gBattleMoves[gCurrentMove].additionalEffects[i - 1].chance; + percentChance = CalcSecondaryEffectChance( + gBattlerAttacker, + gBattleMoves[gCurrentMove].additionalEffects[i - 1].chance + ); // Each effect needs its own RNG_SECONDARY_EFFECT tag if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + i - 1, percentChance)) { gBattleScripting.moveEffect = gBattleMoves[gCurrentMove].additionalEffects[i - 1].moveEffect; - SetMoveEffect((percentChance == 0), 0); + SetMoveEffect((percentChance == 0), gBattleMoves[gCurrentMove].additionalEffects[i - 1].chance == 100); } } } diff --git a/src/battle_util.c b/src/battle_util.c index d32c30b1e6..fc2f794653 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5680,7 +5680,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !IS_MOVE_STATUS(move) && gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_HIT && gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_STATUS - && gBattleMoves[gCurrentMove].effect != EFFECT_TRIPLE_ARROWS) + && !MoveHasMoveEffect(gCurrentMove, MOVE_EFFECT_FLINCH)) { gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; BattleScriptPushCursor(); @@ -11136,6 +11136,17 @@ bool32 IsGen6ExpShareEnabled(void) #endif } +bool32 MoveHasMoveEffect(u16 move, u16 moveEffect) +{ + u8 i; + for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++) + { + if (gBattleMoves[move].additionalEffects[i].moveEffect == moveEffect) + return TRUE; + } + return FALSE; +} + u8 GetBattlerType(u32 battler, u8 typeIndex) { diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 6f0157b672..14755a4cf9 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -13385,16 +13385,19 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .power = 50, .pp = 15, #endif - .effect = EFFECT_TRIPLE_ARROWS, + .effect = EFFECT_HIT, .type = TYPE_FIGHTING, .accuracy = 100, - .secondaryEffectChance = 100, // 50% Defense down, 30% Flinch. Can be modified in 'SetMoveEffect' .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .highCritRatio = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_DEF_MINUS_1, 50), + SECONDARY_EFFECT(MOVE_EFFECT_FLINCH, 30) + ) }, [MOVE_INFERNAL_PARADE] = diff --git a/test/battle/move.c b/test/battle/move.c index 4766414e41..54c7221f07 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Accuracy controls the proportion of misses") } } -SINGLE_BATTLE_TEST("AdditionalEffect.effect controls the proportion of secondary effects") +SINGLE_BATTLE_TEST("AdditionalEffect.chance controls the proportion of secondary effects") { u32 move; PARAMETRIZE { move = MOVE_THUNDER_SHOCK; } diff --git a/test/battle/move_effect/triple_arrows.c b/test/battle/move_effect/triple_arrows.c index eb8e1c666f..39b453ab56 100644 --- a/test/battle/move_effect/triple_arrows.c +++ b/test/battle/move_effect/triple_arrows.c @@ -3,7 +3,8 @@ ASSUMPTIONS { - ASSUME(gBattleMoves[MOVE_TRIPLE_ARROWS].effect == EFFECT_TRIPLE_ARROWS); + ASSUME(gBattleMoves[MOVE_TRIPLE_ARROWS].additionalEffects[0].moveEffect == MOVE_EFFECT_DEF_MINUS_1); + ASSUME(gBattleMoves[MOVE_TRIPLE_ARROWS].additionalEffects[1].moveEffect == MOVE_EFFECT_FLINCH); } SINGLE_BATTLE_TEST("Triple Arrows may lower Defense by one stage") @@ -12,7 +13,7 @@ SINGLE_BATTLE_TEST("Triple Arrows may lower Defense by one stage") u32 chance; PARAMETRIZE { ability = ABILITY_HUSTLE; chance = 50; } PARAMETRIZE { ability = ABILITY_SERENE_GRACE; chance = 100; } - PASSES_RANDOMLY(chance, 100, RNG_TRIPLE_ARROWS_DEFENSE_DOWN); + PASSES_RANDOMLY(chance, 100, RNG_SECONDARY_EFFECT); GIVEN { PLAYER(SPECIES_TOGEPI) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); @@ -31,7 +32,7 @@ SINGLE_BATTLE_TEST("Triple Arrows makes the foe flinch 30% of the time") u32 chance; PARAMETRIZE { ability = ABILITY_HUSTLE; chance = 30; } PARAMETRIZE { ability = ABILITY_SERENE_GRACE; chance = 60; } - PASSES_RANDOMLY(chance, 100, RNG_TRIPLE_ARROWS_FLINCH); + PASSES_RANDOMLY(chance, 100, RNG_SECONDARY_EFFECT_2); GIVEN { PLAYER(SPECIES_TOGEPI) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET);