From be045fdc0cb48fa0f2bb565a0c9638886a829239 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 15 Dec 2023 00:03:59 +0100 Subject: [PATCH] Fixes Quick Draw (#3724) * Fixes Quick Draw * Fixes Custap and rest of Quick Draw * review applied --- include/battle.h | 1 - include/random.h | 1 + src/battle_main.c | 66 ++++++++++++++------------ test/battle/ability/quick_draw.c | 15 ++++++ test/battle/hold_effect/custap_berry.c | 14 ++++++ test/battle/hold_effect/quick_claw.c | 21 ++++++++ 6 files changed, 87 insertions(+), 31 deletions(-) create mode 100644 test/battle/hold_effect/quick_claw.c diff --git a/include/battle.h b/include/battle.h index 0ad6c172a4..ca9236d29a 100644 --- a/include/battle.h +++ b/include/battle.h @@ -982,7 +982,6 @@ extern u32 gStatuses4[MAX_BATTLERS_COUNT]; extern struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT]; extern u16 gPauseCounterBattle; extern u16 gPaydayMoney; -extern u16 gRandomTurnNumber; extern u8 gBattleCommunication[BATTLE_COMMUNICATION_ENTRIES_COUNT]; extern u8 gBattleOutcome; extern struct ProtectStruct gProtectStructs[MAX_BATTLERS_COUNT]; diff --git a/include/random.h b/include/random.h index 4500d77403..17e75f6de0 100644 --- a/include/random.h +++ b/include/random.h @@ -93,6 +93,7 @@ enum RandomTag RNG_TRIPLE_ARROWS_DEFENSE_DOWN, RNG_TRIPLE_ARROWS_FLINCH, RNG_QUICK_DRAW, + RNG_QUICK_CLAW, RNG_TRACE, }; diff --git a/src/battle_main.c b/src/battle_main.c index 4dac65df90..9d9ad4cf44 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -105,7 +105,8 @@ static bool8 AllAtActionConfirmed(void); static void TryChangeTurnOrder(void); static void CheckChosenMoveForEffectsBeforeTurnStarts(void); static void CheckMegaEvolutionBeforeTurn(void); -static void CheckQuickClaw_CustapBerryActivation(void); +static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2); +static void CheckChangingTurnOrderEffects(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); static void ReturnFromBattleToOverworld(void); static void TryEvolvePokemon(void); @@ -203,7 +204,6 @@ EWRAM_DATA u32 gStatuses4[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gPauseCounterBattle = 0; EWRAM_DATA u16 gPaydayMoney = 0; -EWRAM_DATA u16 gRandomTurnNumber = 0; EWRAM_DATA u8 gBattleCommunication[BATTLE_COMMUNICATION_ENTRIES_COUNT] = {0}; EWRAM_DATA u8 gBattleOutcome = 0; EWRAM_DATA struct ProtectStruct gProtectStructs[MAX_BATTLERS_COUNT] = {0}; @@ -3096,8 +3096,6 @@ static void BattleStartClearSetData(void) gBattleStruct->givenExpMons = 0; gBattleStruct->palaceFlags = 0; - gRandomTurnNumber = Random(); - gBattleResults.shinyWildMon = IsMonShiny(&gEnemyParty[0]); gBattleStruct->arenaLostPlayerMons = 0; @@ -3854,8 +3852,6 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleStruct->turnCountersTracker = 0; gMoveResultFlags = 0; - gRandomTurnNumber = Random(); - SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers if (gBattleTypeFlags & BATTLE_TYPE_ARENA) @@ -3950,7 +3946,6 @@ void BattleTurnPassed(void) BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG); SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers gBattleMainFunc = HandleTurnActionSelectionState; - gRandomTurnNumber = Random(); if (gBattleTypeFlags & BATTLE_TYPE_PALACE) BattleScriptExecute(BattleScript_PalacePrintFlavorText); @@ -4746,26 +4741,6 @@ u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov { u32 strikesFirst = 0; - // Battler 1 - // Quick Draw - if (!ignoreChosenMoves && ability1 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler1]) && RandomPercentage(RNG_QUICK_DRAW, 30)) - gProtectStructs[battler1].quickDraw = TRUE; - // Quick Claw and Custap Berry - if (!gProtectStructs[battler1].quickDraw - && ((holdEffectBattler1 == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * GetBattlerHoldEffectParam(battler1)) / 100) - || (holdEffectBattler1 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler1, 4, gBattleMons[battler1].item)))) - gProtectStructs[battler1].usedCustapBerry = TRUE; - - // Battler 2 - // Quick Draw - if (!ignoreChosenMoves && ability2 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler2]) && RandomPercentage(RNG_QUICK_DRAW, 30)) - gProtectStructs[battler2].quickDraw = TRUE; - // Quick Claw and Custap Berry - if (!gProtectStructs[battler2].quickDraw - && ((holdEffectBattler2 == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * GetBattlerHoldEffectParam(battler2)) / 100) - || (holdEffectBattler2 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler2, 4, gBattleMons[battler2].item)))) - gProtectStructs[battler2].usedCustapBerry = TRUE; - if (priority1 == priority2) { // QUICK CLAW / CUSTAP - always first @@ -4936,6 +4911,7 @@ static void SetActionsAndBattlersTurnOrder(void) { u8 battler1 = gBattlerByTurnOrder[i]; u8 battler2 = gBattlerByTurnOrder[j]; + TryChangingTurnOrderEffects(battler1, battler2); if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM && gActionsByTurnOrder[j] != B_ACTION_USE_ITEM && gActionsByTurnOrder[i] != B_ACTION_SWITCH @@ -4950,7 +4926,7 @@ static void SetActionsAndBattlersTurnOrder(void) } } } - gBattleMainFunc = CheckQuickClaw_CustapBerryActivation; + gBattleMainFunc = CheckChangingTurnOrderEffects; gBattleStruct->quickClawBattlerId = 0; } @@ -4968,6 +4944,7 @@ static void TurnValuesCleanUp(bool8 var0) gProtectStructs[i].banefulBunkered = FALSE; gProtectStructs[i].quash = FALSE; gProtectStructs[i].usedCustapBerry = FALSE; + gProtectStructs[i].quickDraw = FALSE; } else { @@ -5115,7 +5092,37 @@ static void TryChangeTurnOrder(void) } } -static void CheckQuickClaw_CustapBerryActivation(void) +static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2) +{ + u32 ability1 = GetBattlerAbility(battler1); + u32 speedBattler1 = GetBattlerTotalSpeedStat(battler1); + u32 holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE); + u32 speedBattler2 = GetBattlerTotalSpeedStat(battler2); + u32 holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE); + u32 ability2 = GetBattlerAbility(battler2); + + // Battler 1 + // Quick Draw + if (ability1 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler1]) && RandomPercentage(RNG_QUICK_DRAW, 30)) + gProtectStructs[battler1].quickDraw = TRUE; + // Quick Claw and Custap Berry + if (!gProtectStructs[battler1].quickDraw + && ((holdEffectBattler1 == HOLD_EFFECT_QUICK_CLAW && RandomPercentage(RNG_QUICK_CLAW, 10)) + || (holdEffectBattler1 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler1, 4, gBattleMons[battler1].item)))) + gProtectStructs[battler1].usedCustapBerry = TRUE; + + // Battler 2 + // Quick Draw + if (ability2 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler2]) && RandomPercentage(RNG_QUICK_DRAW, 30)) + gProtectStructs[battler2].quickDraw = TRUE; + // Quick Claw and Custap Berry + if (!gProtectStructs[battler2].quickDraw + && ((holdEffectBattler2 == HOLD_EFFECT_QUICK_CLAW && RandomPercentage(RNG_QUICK_CLAW, 10)) + || (holdEffectBattler2 == HOLD_EFFECT_CUSTAP_BERRY && HasEnoughHpToEatBerry(battler2, 4, gBattleMons[battler2].item)))) + gProtectStructs[battler2].usedCustapBerry = TRUE; +} + +static void CheckChangingTurnOrderEffects(void) { u32 i, battler; @@ -5150,7 +5157,6 @@ static void CheckQuickClaw_CustapBerryActivation(void) else if (gProtectStructs[battler].quickDraw) { gBattlerAbility = battler; - gProtectStructs[battler].quickDraw = FALSE; gLastUsedAbility = gBattleMons[battler].ability; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); RecordAbilityBattle(battler, gLastUsedAbility); diff --git a/test/battle/ability/quick_draw.c b/test/battle/ability/quick_draw.c index 7dd918e5d3..cdf237475b 100644 --- a/test/battle/ability/quick_draw.c +++ b/test/battle/ability/quick_draw.c @@ -15,3 +15,18 @@ SINGLE_BATTLE_TEST("Quick Draw has a 30% chance of going first") MESSAGE("Foe Wobbuffet used Celebrate!"); } } + +SINGLE_BATTLE_TEST("Quick Draw does not activate 70% of the time") +{ + PASSES_RANDOMLY(7, 10, RNG_QUICK_DRAW); + GIVEN { + PLAYER(SPECIES_SLOWBRO_GALARIAN) { Ability(ABILITY_QUICK_DRAW); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_TACKLE); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_QUICK_DRAW); + MESSAGE("Foe Wobbuffet used Celebrate!"); + MESSAGE("Slowbro used Tackle!"); + } +} diff --git a/test/battle/hold_effect/custap_berry.c b/test/battle/hold_effect/custap_berry.c index 8b6c7832d4..039e55fb81 100644 --- a/test/battle/hold_effect/custap_berry.c +++ b/test/battle/hold_effect/custap_berry.c @@ -35,3 +35,17 @@ SINGLE_BATTLE_TEST("Custap Berry allows the holder to move first in its priority ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); } } + +SINGLE_BATTLE_TEST("Custap Berry activates even if the opposing mon switches out") +{ + GIVEN { + PLAYER(SPECIES_REGIROCK) { HP(1); Item(ITEM_CUSTAP_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Regirock can act faster, thanks to Custap Berry!"); + } +} diff --git a/test/battle/hold_effect/quick_claw.c b/test/battle/hold_effect/quick_claw.c new file mode 100644 index 0000000000..181cac99f2 --- /dev/null +++ b/test/battle/hold_effect/quick_claw.c @@ -0,0 +1,21 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_QUICK_CLAW].holdEffect == HOLD_EFFECT_QUICK_CLAW); +} + +SINGLE_BATTLE_TEST("Quick Claw activates 10% of the time") +{ + PASSES_RANDOMLY(1, 10, RNG_QUICK_CLAW); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(1); Item(ITEM_QUICK_CLAW); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + MESSAGE("Wobbuffet used Tackle!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } +}