diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e8eda2bc1..7bc76f55c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7328,6 +7328,7 @@ BattleScript_RockyHelmetActivatesDmg: return BattleScript_SpikyShieldEffect:: + jumpifabsent BS_ATTACKER, BattleScript_SpikyShieldRet orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000 bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT healthbarupdate BS_ATTACKER @@ -7335,6 +7336,7 @@ BattleScript_SpikyShieldEffect:: printstring STRINGID_PKMNHURTSWITH waitmessage 0x40 tryfaintmon BS_ATTACKER, FALSE, NULL +BattleScript_SpikyShieldRet:: return BattleScript_KingsShieldEffect:: @@ -7555,6 +7557,11 @@ BattleScript_WhiteHerbRet:: return BattleScript_ItemHealHP_RemoveItemRet:: + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp + goto BattleScript_ItemHealHP_RemoveItemRet_Anim +BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp: + call BattleScript_AbilityPopUp +BattleScript_ItemHealHP_RemoveItemRet_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage 0x40 @@ -7563,7 +7570,13 @@ BattleScript_ItemHealHP_RemoveItemRet:: datahpupdate BS_SCRIPTING removeitem BS_SCRIPTING return + BattleScript_ItemHealHP_RemoveItemEnd2:: + jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemEnd2_AbilityPopUp + goto BattleScript_ItemHealHP_RemoveItemEnd2_Anim +BattleScript_ItemHealHP_RemoveItemEnd2_AbilityPopUp: + call BattleScript_AbilityPopUp +BattleScript_ItemHealHP_RemoveItemEnd2_Anim: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage 0x40 @@ -7574,6 +7587,11 @@ BattleScript_ItemHealHP_RemoveItemEnd2:: end2 BattleScript_BerryPPHealEnd2:: + jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryPPHealEnd2_AbilityPopup + goto BattleScript_BerryPPHealEnd2_Anim +BattleScript_BerryPPHealEnd2_AbilityPopup: + call BattleScript_AbilityPopUp +BattleScript_BerryPPHealEnd2_Anim: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDPP waitmessage 0x40 @@ -7637,6 +7655,11 @@ BattleScript_HangedOnMsgRet: return BattleScript_BerryConfuseHealEnd2:: + jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryConfuseHealEnd2_AbilityPopup + goto BattleScript_BerryConfuseHealEnd2_Anim +BattleScript_BerryConfuseHealEnd2_AbilityPopup: + call BattleScript_AbilityPopUp +BattleScript_BerryConfuseHealEnd2_Anim: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage 0x40 @@ -7650,7 +7673,31 @@ BattleScript_BerryConfuseHealEnd2:: removeitem BS_ATTACKER end2 +BattleScript_BerryConfuseHealRet:: + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup + goto BattleScript_BerryConfuseHealRet_Anim +BattleScript_BerryConfuseHealRet_AbilityPopup: + call BattleScript_AbilityPopUp +BattleScript_BerryConfuseHealRet_Anim: + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + printstring STRINGID_PKMNSITEMRESTOREDHEALTH + waitmessage 0x40 + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING + printstring STRINGID_FORXCOMMAYZ + waitmessage 0x40 + setmoveeffect MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER + seteffectprimary + removeitem BS_SCRIPTING + return + BattleScript_BerryStatRaiseEnd2:: + jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryStatRaiseEnd2_AbilityPopup + goto BattleScript_BerryStatRaiseEnd2_Anim +BattleScript_BerryStatRaiseEnd2_AbilityPopup: + call BattleScript_AbilityPopUp +BattleScript_BerryStatRaiseEnd2_Anim: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_82DB85B BattleScript_82DB85B:: @@ -7659,6 +7706,20 @@ BattleScript_82DB85B:: removeitem BS_ATTACKER end2 +BattleScript_BerryStatRaiseRet:: + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryStatRaiseRet_AbilityPopup + goto BattleScript_BerryStatRaiseRet_Anim +BattleScript_BerryStatRaiseRet_AbilityPopup: + call BattleScript_AbilityPopUp +BattleScript_BerryStatRaiseRet_Anim: + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseRet_End +BattleScript_BerryStatRaiseRet_End: + setbyte cMULTISTRING_CHOOSER, 0x4 + call BattleScript_StatUp + removeitem BS_SCRIPTING + return + BattleScript_BerryFocusEnergyEnd2:: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNUSEDXTOGETPUMPED @@ -7828,6 +7889,63 @@ BattleScript_AnnounceAirLockCloudNine:: call BattleScript_WeatherFormChanges end3 +BattleScript_QuickClawActivation:: + printstring STRINGID_EMPTYSTRING3 + waitmessage 0x1 + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + waitanimation + printstring STRINGID_CANACTFASTERTHANKSTO + waitmessage 0x40 + end2 + +BattleScript_CustapBerryActivation:: + printstring STRINGID_EMPTYSTRING3 + waitmessage 0x1 + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + waitanimation + printstring STRINGID_CANACTFASTERTHANKSTO + waitmessage 0x40 + removeitem BS_ATTACKER + end2 + +BattleScript_MicleBerryActivateEnd2:: + jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_MicleBerryActivateEnd2_Ripen + goto BattleScript_MicleBerryActivateEnd2_Anim +BattleScript_MicleBerryActivateEnd2_Ripen: + call BattleScript_AbilityPopUp +BattleScript_MicleBerryActivateEnd2_Anim: + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + printstring STRINGID_MICLEBERRYACTIVATES + waitmessage 0x40 + removeitem BS_ATTACKER + end2 + +BattleScript_MicleBerryActivateRet:: + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_MicleBerryActivateRet_Ripen + goto BattleScript_MicleBerryActivateRet_Anim +BattleScript_MicleBerryActivateRet_Ripen: + call BattleScript_AbilityPopUp +BattleScript_MicleBerryActivateRet_Anim: + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + printstring STRINGID_MICLEBERRYACTIVATES + waitmessage 0x40 + removeitem BS_SCRIPTING + return + +BattleScript_JabocaRowapBerryActivates:: + jumpifability BS_TARGET, ABILITY_RIPEN, BattleScript_JabocaRowapBerryActivate_Ripen + goto BattleScript_JabocaRowapBerryActivate_Anim +BattleScript_JabocaRowapBerryActivate_Ripen: + call BattleScript_AbilityPopUp +BattleScript_JabocaRowapBerryActivate_Anim: + jumpifabsent BS_TARGET, BattleScript_JabocaRowapBerryActivate_Dmg @ dont play the animation for a fainted target + playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL + waitanimation +BattleScript_JabocaRowapBerryActivate_Dmg: + call BattleScript_HurtAttacker + removeitem BS_TARGET + return + @ z moves / effects BattleScript_ZMoveActivateDamaging:: printstring STRINGID_ZPOWERSURROUNDS @@ -7943,4 +8061,3 @@ BattleScript_EffectTerrainHit: BattleScript_TryFaint: tryfaintmon BS_TARGET, FALSE, NULL goto BattleScript_MoveEnd - diff --git a/include/battle.h b/include/battle.h index 0970f36fc..f4c944c57 100644 --- a/include/battle.h +++ b/include/battle.h @@ -140,6 +140,8 @@ struct ProtectStruct u32 usedGravityPreventedMove:1; u32 powderSelfDmg:1; u32 usedThroatChopPreventedMove:1; + u32 micle:1; + u32 custap:1; // also quick claw u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; @@ -563,6 +565,7 @@ struct BattleStruct u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used. u16 moveEffect2; // For Knock Off u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon. + u8 quickClawBattlerId; }; #define GET_MOVE_TYPE(move, typeArg) \ diff --git a/include/battle_interface.h b/include/battle_interface.h index 512f031f1..236db67b8 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -76,7 +76,7 @@ void SetHealthboxSpriteInvisible(u8 healthboxSpriteId); void SetHealthboxSpriteVisible(u8 healthboxSpriteId); void DestoryHealthboxSprite(u8 healthboxSpriteId); void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly); -void UpdateOamPriorityInAllHealthboxes(u8 priority); +void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHpBoxes); void InitBattlerHealthboxCoords(u8 battler); void UpdateHpTextInHealthbox(u8 healthboxSpriteId, s16 value, u8 maxOrCurrent); void SwapHpBarsWithHpText(void); diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 4d274d212..5a367983d 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -209,7 +209,9 @@ extern const u8 BattleScript_ItemHealHP_Ret[]; extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItem[]; extern const u8 BattleScript_HangedOnMsg[]; extern const u8 BattleScript_BerryConfuseHealEnd2[]; +extern const u8 BattleScript_BerryConfuseHealRet[]; extern const u8 BattleScript_BerryStatRaiseEnd2[]; +extern const u8 BattleScript_BerryStatRaiseRet[]; extern const u8 BattleScript_BerryFocusEnergyEnd2[]; extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[]; extern const u8 BattleScript_ArenaTurnBeginning[]; @@ -360,6 +362,11 @@ extern const u8 BattleScript_SandSpitActivates[]; extern const u8 BattleScript_PerishBodyActivates[]; extern const u8 BattleScript_ActivateAsOne[]; extern const u8 BattleScript_RaiseStatOnFaintingTarget[]; +extern const u8 BattleScript_QuickClawActivation[]; +extern const u8 BattleScript_CustapBerryActivation[]; +extern const u8 BattleScript_MicleBerryActivateEnd2[]; +extern const u8 BattleScript_MicleBerryActivateRet[]; +extern const u8 BattleScript_JabocaRowapBerryActivates[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/battle_util.h b/include/battle_util.h index 5d8cb0cc5..16ebdceae 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -131,6 +131,7 @@ void ClearIllusionMon(u32 battlerId); bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId); bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); u8 GetBattleMoveSplit(u32 moveId); +bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId); bool32 IsPartnerMonFromSameTrainer(u8 battlerId); u8 GetSplitBasedOnStats(u8 battlerId); diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 32a00fd6d..b8e95379a 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -148,6 +148,7 @@ #define B_CAN_SPITE_FAIL GEN_6 // In Gen4+, Spite can no longer fail if the foe's last move only has 1 remaining PP. #define B_CRASH_IF_TARGET_IMMUNE GEN_6 // In Gen4+, The user of Jump Kick or Hi Jump Kick will "keep going and crash" if it attacks a target that is immune to the move. #define B_TAILWIND_TIMER GEN_5 // In Gen5+, Tailwind lasts 4 turns instead of 3. +#define B_MEMENTO_FAIL GEN_4 // In Gen4+, memento fails if there is no target or if the target is protected or behind substitute. But not if atk/sp.atk are at -6 // Ability settings #define B_ABILITY_WEATHER GEN_6 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move. diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 78644f466..1c5166dde 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -566,17 +566,19 @@ #define STRINGID_AURAFLAREDTOLIFE 562 #define STRINGID_ASONEENTERS 563 #define STRINGID_CURIOUSMEDICINEENTERS 564 -#define STRINGID_ZPOWERSURROUNDS 565 -#define STRINGID_ZMOVEUNLEASHED 566 -#define STRINGID_ZMOVERESETSSTATS 567 -#define STRINGID_ZMOVEALLSTATSUP 568 -#define STRINGID_ZMOVEZBOOSTCRIT 569 -#define STRINGID_ZMOVERESTOREHP 570 -#define STRINGID_ZMOVESTATUP 571 -#define STRINGID_ZMOVEHPTRAP 572 -#define STRINGID_TERRAINREMOVED 573 +#define STRINGID_CANACTFASTERTHANKSTO 565 +#define STRINGID_MICLEBERRYACTIVATES 566 +#define STRINGID_ZPOWERSURROUNDS 567 +#define STRINGID_ZMOVEUNLEASHED 568 +#define STRINGID_ZMOVERESETSSTATS 569 +#define STRINGID_ZMOVEALLSTATSUP 570 +#define STRINGID_ZMOVEZBOOSTCRIT 571 +#define STRINGID_ZMOVERESTOREHP 572 +#define STRINGID_ZMOVESTATUP 573 +#define STRINGID_ZMOVEHPTRAP 574 +#define STRINGID_TERRAINREMOVED 575 -#define BATTLESTRINGS_COUNT 574 +#define BATTLESTRINGS_COUNT 576 //// multichoice message IDs // switch in ability message diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 54c1d004a..ddbb51c65 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -104,6 +104,12 @@ #define HOLD_EFFECT_RESIST_BERRY 98 #define HOLD_EFFECT_POWER_ITEM 99 #define HOLD_EFFECT_RESTORE_PCT_HP 100 +#define HOLD_EFFECT_MICLE_BERRY 101 +#define HOLD_EFFECT_CUSTAP_BERRY 102 +#define HOLD_EFFECT_JABOCA_BERRY 103 +#define HOLD_EFFECT_ROWAP_BERRY 104 +#define HOLD_EFFECT_KEE_BERRY 105 +#define HOLD_EFFECT_MARANGA_BERRY 106 // Gen5 hold effects #define HOLD_EFFECT_FLOAT_STONE 115 diff --git a/src/battle_anim.c b/src/battle_anim.c index cb7ea5bea..6613c3639 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -18,6 +18,7 @@ #include "task.h" #include "constants/battle_anim.h" #include "constants/battle_config.h" +#include "constants/moves.h" #define ANIM_SPRITE_INDEX_COUNT 8 @@ -2198,11 +2199,32 @@ void DoMoveAnim(u16 move) void LaunchBattleAnimation(const u8 *const animsTable[], u16 tableId, bool8 isMoveAnim) { s32 i; + bool32 hideHpBoxes = (tableId == MOVE_TRANSFORM) ? FALSE : TRUE; + + if (!isMoveAnim) + { + switch (tableId) + { + case B_ANIM_TURN_TRAP: + case B_ANIM_LEECH_SEED_DRAIN: + case B_ANIM_MON_HIT: + case B_ANIM_SNATCH_MOVE: + case B_ANIM_FUTURE_SIGHT_HIT: + case B_ANIM_DOOM_DESIRE_HIT: + case B_ANIM_WISH_HEAL: + case B_ANIM_MEGA_EVOLUTION: + hideHpBoxes = TRUE; + break; + default: + hideHpBoxes = FALSE; + break; + } + } if (!IsContest()) { sub_80A8278(); - UpdateOamPriorityInAllHealthboxes(0); + UpdateOamPriorityInAllHealthboxes(0, hideHpBoxes); for (i = 0; i < MAX_BATTLERS_COUNT; i++) { if (GetBattlerSide(i) != B_SIDE_PLAYER) @@ -2511,7 +2533,7 @@ static void ScriptCmd_end(void) if (!IsContest()) { sub_80A8278(); - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, TRUE); } gAnimScriptActive = FALSE; } diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index cd686af5c..869daf030 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -1332,7 +1332,7 @@ static void SpriteCB_Ball_Capture_Step(struct Sprite *sprite) else if (sprite->sTimer == 95) { gDoingBattleAnim = FALSE; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); m4aMPlayAllStop(); PlaySE(MUS_RG_CAUGHT_INTRO); } @@ -1515,7 +1515,7 @@ static void SpriteCB_Ball_Release_Wait(struct Sprite *sprite) sprite->sFrame = 0; sprite->callback = DestroySpriteAfterOneFrame; gDoingBattleAnim = 0; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); } } @@ -1557,7 +1557,7 @@ static void SpriteCB_Ball_Block_Step(struct Sprite *sprite) sprite->sFrame = 0; sprite->callback = DestroySpriteAfterOneFrame; gDoingBattleAnim = 0; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); } } diff --git a/src/battle_interface.c b/src/battle_interface.c index c79bbc108..e99ace498 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -945,36 +945,6 @@ static void TryToggleHealboxVisibility(u8 priority, u8 healthboxLeftSpriteId, u8 u8 spriteIds[4] = {healthboxLeftSpriteId, healthboxRightSpriteId, healthbarSpriteId, indicatorSpriteId}; int i; - switch (gBattleResources->bufferA[gBattleAnimAttacker][0]) - { - case CONTROLLER_MOVEANIMATION: - if (gBattleResources->bufferA[gBattleAnimAttacker][1] == MOVE_TRANSFORM) - return; - break; - case CONTROLLER_BALLTHROWANIM: - return; //throwing ball does not hide hp boxes - case CONTROLLER_BATTLEANIMATION: - //check special anims that hide health boxes - switch (gBattleResources->bufferA[gBattleAnimAttacker][1]) - { - case B_ANIM_TURN_TRAP: - case B_ANIM_LEECH_SEED_DRAIN: - case B_ANIM_MON_HIT: - case B_ANIM_SNATCH_MOVE: - case B_ANIM_FUTURE_SIGHT_HIT: - case B_ANIM_DOOM_DESIRE_HIT: - case B_ANIM_WISH_HEAL: - //new - case B_ANIM_MEGA_EVOLUTION: - case B_ANIM_RESTORE_BG: - break; - } - return; //all other special anims dont hide - default: - return; - } - - // if we've reached here, we should hide hp boxes for (i = 0; i < NELEMS(spriteIds); i++) { if (spriteIds[i] == 0xFF) @@ -992,7 +962,7 @@ static void TryToggleHealboxVisibility(u8 priority, u8 healthboxLeftSpriteId, u8 } } -void UpdateOamPriorityInAllHealthboxes(u8 priority) +void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) { s32 i; @@ -1010,7 +980,7 @@ void UpdateOamPriorityInAllHealthboxes(u8 priority) gSprites[indicatorSpriteId].oam.priority = priority; #if B_HIDE_HEALTHBOXES_DURING_ANIMS - if (IsBattlerAlive(i)) + if (hideHPBoxes && IsBattlerAlive(i)) TryToggleHealboxVisibility(priority, healthboxLeftSpriteId, healthboxRightSpriteId, healthbarSpriteId, indicatorSpriteId); #endif } diff --git a/src/battle_main.c b/src/battle_main.c index d64ce4acf..49cfb7fe6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -107,6 +107,7 @@ static void sub_803CDF8(void); static bool8 AllAtActionConfirmed(void); static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void); static void CheckMegaEvolutionBeforeTurn(void); +static void CheckQuickClaw_CustapBerryActivation(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); static void ReturnFromBattleToOverworld(void); static void TryEvolvePokemon(void); @@ -4352,20 +4353,23 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves) u8 strikesFirst = 0; u32 speedBattler1 = 0, speedBattler2 = 0; u32 holdEffectBattler1 = 0, holdEffectBattler2 = 0; - bool32 quickClawBattler1 = FALSE, quickClawBattler2 = FALSE; s8 priority1 = 0, priority2 = 0; speedBattler1 = GetBattlerTotalSpeedStat(battler1); holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE); - if (holdEffectBattler1 == HOLD_EFFECT_QUICK_CLAW - && gRandomTurnNumber < (0xFFFF * GetBattlerHoldEffectParam(battler1)) / 100) - quickClawBattler1 = TRUE; + if ((holdEffectBattler1 == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * GetBattlerHoldEffectParam(battler1)) / 100) + || (!IsAbilityOnOpposingSide(battler1, ABILITY_UNNERVE) + && holdEffectBattler1 == HOLD_EFFECT_CUSTAP_BERRY + && HasEnoughHpToEatBerry(battler1, 4, gBattleMons[battler1].item))) + gProtectStructs[battler1].custap = TRUE; speedBattler2 = GetBattlerTotalSpeedStat(battler2); holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE); - if (holdEffectBattler2 == HOLD_EFFECT_QUICK_CLAW - && gRandomTurnNumber < (0xFFFF * GetBattlerHoldEffectParam(battler2)) / 100) - quickClawBattler2 = TRUE; + if ((holdEffectBattler2 == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * GetBattlerHoldEffectParam(battler2)) / 100) + || (!IsAbilityOnOpposingSide(battler2, ABILITY_UNNERVE) + && holdEffectBattler2 == HOLD_EFFECT_CUSTAP_BERRY + && HasEnoughHpToEatBerry(battler2, 4, gBattleMons[battler2].item))) + gProtectStructs[battler2].custap = TRUE; if (!ignoreChosenMoves) { @@ -4377,13 +4381,13 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves) if (priority1 == priority2) { - // QUICK CLAW - always first + // QUICK CLAW / CUSTAP - always first // LAGGING TAIL - always last // STALL - always last - if (quickClawBattler1 && !quickClawBattler2) + if (gProtectStructs[battler1].custap && !gProtectStructs[battler2].custap) strikesFirst = 0; - else if (quickClawBattler2 && !quickClawBattler1) + else if (gProtectStructs[battler2].custap && !gProtectStructs[battler1].custap) strikesFirst = 1; else if (holdEffectBattler1 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler2 != HOLD_EFFECT_LAGGING_TAIL) strikesFirst = 1; @@ -4620,6 +4624,45 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) } } + gBattleMainFunc = CheckQuickClaw_CustapBerryActivation; + gBattleStruct->quickClawBattlerId = 0; +} + +static void CheckQuickClaw_CustapBerryActivation(void) +{ + u32 i; + + if (!(gHitMarker & HITMARKER_RUN)) + { + while (gBattleStruct->quickClawBattlerId < gBattlersCount) + { + gActiveBattler = gBattlerAttacker = gBattleStruct->quickClawBattlerId; + gBattleStruct->quickClawBattlerId++; + if (gChosenActionByBattler[gActiveBattler] == B_ACTION_USE_MOVE + && gChosenMoveByBattler[gActiveBattler] != MOVE_FOCUS_PUNCH // quick claw message doesn't need to activate here + && gProtectStructs[gActiveBattler].custap + && !(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP) + && !(gDisableStructs[gBattlerAttacker].truantCounter) + && !(gProtectStructs[gActiveBattler].noValidMoves)) + { + gProtectStructs[gActiveBattler].custap = FALSE; + gLastUsedItem = gBattleMons[gActiveBattler].item; + if (GetBattlerHoldEffect(gActiveBattler, FALSE) == HOLD_EFFECT_CUSTAP_BERRY) + { + // don't record berry since its gone now + BattleScriptExecute(BattleScript_CustapBerryActivation); + } + else + { + RecordItemEffectBattle(gActiveBattler, GetBattlerHoldEffect(gActiveBattler, FALSE)); + BattleScriptExecute(BattleScript_QuickClawActivation); + } + return; + } + } + } + + // setup stuff before turns/actions TryClearRageAndFuryCutter(); gCurrentTurnActionNumber = 0; gCurrentActionFuncId = gActionsByTurnOrder[0]; diff --git a/src/battle_message.c b/src/battle_message.c index ae7ec7721..207d352ba 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -693,6 +693,8 @@ static const u8 sText_PkmnsWillPerishIn3Turns[] = _("Both Pokémon will perish\n static const u8 sText_AbilityRaisedStatDrastically[] = _("{B_DEF_ABILITY} raised {B_DEF_NAME_WITH_PREFIX}'s\n{B_BUFF1} drastically!"); static const u8 sText_AsOneEnters[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} has two Abilities!"); static const u8 sText_CuriousMedicineEnters[] = _("{B_EFF_NAME_WITH_PREFIX}'s\nstat changes were reset!"); +static const u8 sText_CanActFaster[] = _("{B_ATK_NAME_WITH_PREFIX} can act faster,\nthanks to {B_LAST_ITEM}!"); +static const u8 sText_MicleBerryActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted the accuracy of its\nnext move using {B_LAST_ITEM}!"); static const u8 sText_ZPowerSurrounds[] = _("{B_ATK_NAME_WITH_PREFIX} surrounds\nitself with its Z-Power!"); static const u8 sText_ZPowerUnleashed[] = _("{B_ATK_NAME_WITH_PREFIX} unleashes\nits full-force Z-Move!"); static const u8 sText_ZMoveResetsStats[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} returned its\ndecreased stats to normal using\lits Z-Power!"); @@ -713,6 +715,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_ZMOVERESTOREHP - 12] = sText_ZMoveRestoreHp, [STRINGID_ZMOVESTATUP - 12] = sText_ZMoveStatUp, [STRINGID_ZMOVEHPTRAP - 12] = sText_ZMoveHpSwitchInTrap, + [STRINGID_MICLEBERRYACTIVATES - 12] = sText_MicleBerryActivates, + [STRINGID_CANACTFASTERTHANKSTO - 12] = sText_CanActFaster, [STRINGID_CURIOUSMEDICINEENTERS - 12] = sText_CuriousMedicineEnters, [STRINGID_ASONEENTERS - 12] = sText_AsOneEnters, [STRINGID_ABILITYRAISEDSTATDRASTICALLY - 12] = sText_AbilityRaisedStatDrastically, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index dd0cf3686..216e3c6a7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1570,6 +1570,15 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move) calc = (calc * (100 + atkParam)) / 100; else if (atkHoldEffect == HOLD_EFFECT_ZOOM_LENS && GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef)); calc = (calc * (100 + atkParam)) / 100; + + if (gProtectStructs[battlerAtk].micle) + { + gProtectStructs[battlerAtk].micle = FALSE; + if (atkAbility == ABILITY_RIPEN) + calc = (calc * 140) / 100; // ripen gives 40% acc boost + else + calc = (calc * 120) / 100; // 20% acc boost + } return calc; } @@ -11048,9 +11057,16 @@ static void Cmd_sethail(void) static void Cmd_jumpifattackandspecialattackcannotfall(void) // memento { + #if B_MEMENTO_FAIL == GEN_3 if (gBattleMons[gBattlerTarget].statStages[STAT_ATK] == MIN_STAT_STAGE && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] == MIN_STAT_STAGE && gBattleCommunication[6] != 1) + #else + if (gBattleCommunication[6] != 1 + || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE + || IsBattlerProtected(gBattlerTarget, gCurrentMove) + || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + #endif { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } diff --git a/src/battle_util.c b/src/battle_util.c index 9d9ee1a2d..45b358da7 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5170,10 +5170,16 @@ u32 IsAbilityPreventingEscape(u32 battlerId) bool32 CanBattlerEscape(u32 battlerId) // no ability check { - return (GetBattlerHoldEffect(battlerId, TRUE) == HOLD_EFFECT_SHED_SHELL - || !((gBattleMons[battlerId].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) - || (gStatuses3[battlerId] & STATUS3_ROOTED) - || gFieldStatuses & STATUS_FIELD_FAIRY_LOCK)); + if (GetBattlerHoldEffect(battlerId, TRUE) == HOLD_EFFECT_SHED_SHELL) + return TRUE; + else if ((B_GHOSTS_ESCAPE >= GEN_6 && !IS_BATTLER_OF_TYPE(battlerId, TYPE_GHOST)) && gBattleMons[battlerId].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) + return FALSE; + else if (gStatuses3[battlerId] & STATUS3_ROOTED) + return FALSE; + else if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) + return FALSE; + else + return TRUE; } void BattleScriptExecute(const u8 *BS_ptr) @@ -5203,7 +5209,7 @@ enum }; // second argument is 1/X of current hp compared to max hp -static bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) +bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) { bool32 isBerry = (ItemId_GetPocket(itemId) == POCKET_BERRIES); @@ -5225,7 +5231,7 @@ static bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) return FALSE; } -static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId) +static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId, bool32 end2) { if (HasEnoughHpToEatBerry(battlerId, 2, itemId)) { @@ -5235,17 +5241,35 @@ static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId) if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; gBattleMoveDamage *= -1; - if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0) - BattleScriptExecute(BattleScript_BerryConfuseHealEnd2); + + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + { + gBattleMoveDamage *= 2; + gBattlerAbility = battlerId; + } + + if (end2) + { + if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0) + BattleScriptExecute(BattleScript_BerryConfuseHealEnd2); + else + BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); + } else - BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); + { + BattleScriptPushCursor(); + if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0) + gBattlescriptCurrInstr = BattleScript_BerryConfuseHealRet; + else + gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet; + } return ITEM_HP_CHANGE; } return 0; } -static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId) +static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2) { if (gBattleMons[battlerId].statStages[statId] < 0xC && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId)) { @@ -5253,16 +5277,29 @@ static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId) PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); gEffectBattler = battlerId; - SET_STATCHANGER(statId, 1, FALSE); + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + SET_STATCHANGER(statId, 2, FALSE); + else + SET_STATCHANGER(statId, 1, FALSE); + gBattleScripting.animArg1 = 0xE + statId; gBattleScripting.animArg2 = 0; - BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + + if (end2) + { + BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; + } return ITEM_STATS_CHANGE; } return 0; } -static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId) +static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) { s32 i; @@ -5290,10 +5327,71 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId) gBattleTextBuff2[7] = EOS; gEffectBattler = battlerId; - SET_STATCHANGER(i + 1, 2, FALSE); + + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + SET_STATCHANGER(i + 1, 4, FALSE); + else + SET_STATCHANGER(i + 1, 2, FALSE); + gBattleScripting.animArg1 = 0x21 + i + 6; gBattleScripting.animArg2 = 0; - BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + + if (end2) + { + BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; + } + return ITEM_STATS_CHANGE; + } + return 0; +} + +static u8 TrySetMicleBerry(u32 battlerId, u32 itemId, bool32 end2) +{ + if (HasEnoughHpToEatBerry(battlerId, 4, itemId)) + { + gProtectStructs[battlerId].micle = TRUE; // battler's next attack has increased accuracy + + if (end2) + { + BattleScriptExecute(BattleScript_MicleBerryActivateEnd2); + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MicleBerryActivateRet; + } + return ITEM_EFFECT_OTHER; + } + return 0; +} + +static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split) +{ + if (IsBattlerAlive(battlerId) + && TARGET_TURN_DAMAGED + && gBattleMons[battlerId].statStages[statId] < MAX_STAT_STAGE + && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) + && GetBattleMoveSplit(gCurrentMove) == split) + { + + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); + + gEffectBattler = battlerId; + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + SET_STATCHANGER(statId, 2, FALSE); + else + SET_STATCHANGER(statId, 1, FALSE); + + gBattleScripting.animArg1 = 0xE + statId; + gBattleScripting.animArg2 = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; return ITEM_STATS_CHANGE; } return 0; @@ -5307,7 +5405,12 @@ static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal) gBattleMoveDamage = (gBattleMons[battlerId].maxHP * GetBattlerHoldEffectParam(battlerId) / 100) * -1; else gBattleMoveDamage = GetBattlerHoldEffectParam(battlerId) * -1; - + + // check ripen + if (ItemId_GetPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battlerId) == ABILITY_RIPEN) + gBattleMoveDamage *= 2; + + gBattlerAbility = battlerId; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here if (end2) { BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2); @@ -5375,43 +5478,43 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) break; case HOLD_EFFECT_CONFUSE_SPICY: if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SPICY); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SPICY, TRUE); break; case HOLD_EFFECT_CONFUSE_DRY: if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_DRY); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_DRY, TRUE); break; case HOLD_EFFECT_CONFUSE_SWEET: if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SWEET); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SWEET, TRUE); break; case HOLD_EFFECT_CONFUSE_BITTER: if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_BITTER); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_BITTER, TRUE); break; case HOLD_EFFECT_CONFUSE_SOUR: if (B_BERRIES_INSTANT >= GEN_4) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SOUR); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SOUR, TRUE); break; case HOLD_EFFECT_ATTACK_UP: if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_ATK); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_ATK, TRUE); break; case HOLD_EFFECT_DEFENSE_UP: if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_DEF); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_DEF, TRUE); break; case HOLD_EFFECT_SPEED_UP: if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPEED); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPEED, TRUE); break; case HOLD_EFFECT_SP_ATTACK_UP: if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPATK); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPATK, TRUE); break; case HOLD_EFFECT_SP_DEFENSE_UP: if (B_BERRIES_INSTANT >= GEN_4) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPDEF); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPDEF, TRUE); break; case HOLD_EFFECT_CRITICAL_UP: if (B_BERRIES_INSTANT >= GEN_4 && !(gBattleMons[battlerId].status2 & STATUS2_FOCUS_ENERGY) && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), gLastUsedItem)) @@ -5423,7 +5526,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) break; case HOLD_EFFECT_RANDOM_STAT_UP: if (B_BERRIES_INSTANT >= GEN_4) - effect = RandomStatRaiseBerry(battlerId, gLastUsedItem); + effect = RandomStatRaiseBerry(battlerId, gLastUsedItem, TRUE); break; case HOLD_EFFECT_CURE_PAR: if (B_BERRIES_INSTANT >= GEN_4 && gBattleMons[battlerId].status1 & STATUS1_PARALYSIS && !UnnerveOn(battlerId, gLastUsedItem)) @@ -5555,7 +5658,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) effect = ItemHealHp(battlerId, gLastUsedItem, TRUE, FALSE); break; case HOLD_EFFECT_RESTORE_PCT_HP: - if (B_BERRIES_INSTANT >= GEN_4) + if (!moveTurn) effect = ItemHealHp(battlerId, gLastUsedItem, TRUE, TRUE); break; case HOLD_EFFECT_RESTORE_PP: @@ -5580,10 +5683,17 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) if (i != MAX_MON_MOVES) { u8 maxPP = CalculatePPWithBonus(move, ppBonuses, i); - if (changedPP + GetBattlerHoldEffectParam(battlerId) > maxPP) + u8 ppRestored = GetBattlerHoldEffectParam(battlerId); + + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + { + ppRestored *= 2; + gBattlerAbility = battlerId; + } + if (changedPP + ppRestored > maxPP) changedPP = maxPP; else - changedPP = changedPP + GetBattlerHoldEffectParam(battlerId); + changedPP = changedPP + ppRestored; PREPARE_MOVE_BUFFER(gBattleTextBuff1, move); @@ -5641,43 +5751,43 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) break; case HOLD_EFFECT_CONFUSE_SPICY: if (!moveTurn) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SPICY); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SPICY, TRUE); break; case HOLD_EFFECT_CONFUSE_DRY: if (!moveTurn) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_DRY); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_DRY, TRUE); break; case HOLD_EFFECT_CONFUSE_SWEET: if (!moveTurn) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SWEET); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SWEET, TRUE); break; case HOLD_EFFECT_CONFUSE_BITTER: if (!moveTurn) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_BITTER); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_BITTER, TRUE); break; case HOLD_EFFECT_CONFUSE_SOUR: if (!moveTurn) - effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SOUR); + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SOUR, TRUE); break; case HOLD_EFFECT_ATTACK_UP: if (!moveTurn) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_ATK); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_ATK, TRUE); break; case HOLD_EFFECT_DEFENSE_UP: if (!moveTurn) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_DEF); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_DEF, TRUE); break; case HOLD_EFFECT_SPEED_UP: if (!moveTurn) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPEED); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPEED, TRUE); break; case HOLD_EFFECT_SP_ATTACK_UP: if (!moveTurn) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPATK); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPATK, TRUE); break; case HOLD_EFFECT_SP_DEFENSE_UP: if (!moveTurn) - effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPDEF); + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPDEF, TRUE); break; case HOLD_EFFECT_CRITICAL_UP: if (!moveTurn && !(gBattleMons[battlerId].status2 & STATUS2_FOCUS_ENERGY) && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), gLastUsedItem)) @@ -5689,7 +5799,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) break; case HOLD_EFFECT_RANDOM_STAT_UP: if (!moveTurn) - effect = RandomStatRaiseBerry(battlerId, gLastUsedItem); + effect = RandomStatRaiseBerry(battlerId, gLastUsedItem, TRUE); break; case HOLD_EFFECT_CURE_PAR: if (gBattleMons[battlerId].status1 & STATUS1_PARALYSIS && !UnnerveOn(battlerId, gLastUsedItem)) @@ -5795,6 +5905,10 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) effect = ITEM_EFFECT_OTHER; } break; + case HOLD_EFFECT_MICLE_BERRY: + if (!moveTurn) + effect = TrySetMicleBerry(battlerId, gLastUsedItem, TRUE); + break; } if (effect) @@ -5821,6 +5935,10 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) battlerHoldEffect = GetBattlerHoldEffect(battlerId, TRUE); switch (battlerHoldEffect) { + case HOLD_EFFECT_MICLE_BERRY: + if (B_HP_BERRIES >= GEN_4) + effect = TrySetMicleBerry(battlerId, gLastUsedItem, FALSE); + break; case HOLD_EFFECT_RESTORE_HP: if (B_HP_BERRIES >= GEN_4) effect = ItemHealHp(battlerId, gLastUsedItem, FALSE, FALSE); @@ -5829,6 +5947,50 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) if (B_BERRIES_INSTANT >= GEN_4) effect = ItemHealHp(battlerId, gLastUsedItem, FALSE, TRUE); break; + case HOLD_EFFECT_CONFUSE_SPICY: + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SPICY, FALSE); + break; + case HOLD_EFFECT_CONFUSE_DRY: + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_DRY, FALSE); + break; + case HOLD_EFFECT_CONFUSE_SWEET: + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SWEET, FALSE); + break; + case HOLD_EFFECT_CONFUSE_BITTER: + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_BITTER, FALSE); + break; + case HOLD_EFFECT_CONFUSE_SOUR: + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battlerId, gLastUsedItem, FLAVOR_SOUR, FALSE); + break; + case HOLD_EFFECT_ATTACK_UP: + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_ATK, FALSE); + break; + case HOLD_EFFECT_DEFENSE_UP: + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_DEF, FALSE); + break; + case HOLD_EFFECT_SPEED_UP: + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPEED, FALSE); + break; + case HOLD_EFFECT_SP_ATTACK_UP: + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPATK, FALSE); + break; + case HOLD_EFFECT_SP_DEFENSE_UP: + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battlerId, gLastUsedItem, STAT_SPDEF, FALSE); + break; + case HOLD_EFFECT_RANDOM_STAT_UP: + if (B_BERRIES_INSTANT >= GEN_4) + effect = RandomStatRaiseBerry(battlerId, gLastUsedItem, FALSE); + break; case HOLD_EFFECT_CURE_PAR: if (gBattleMons[battlerId].status1 & STATUS1_PARALYSIS && !UnnerveOn(battlerId, gLastUsedItem)) { @@ -6088,6 +6250,52 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE); } break; + case HOLD_EFFECT_JABOCA_BERRY: // consume and damage attacker if used physical move + if (IsBattlerAlive(battlerId) + && TARGET_TURN_DAMAGED + && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) + && IS_MOVE_PHYSICAL(gCurrentMove) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + gBattleMoveDamage *= 2; + + effect = ITEM_HP_CHANGE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates; + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); + RecordItemEffectBattle(battlerId, HOLD_EFFECT_ROCKY_HELMET); + } + break; + case HOLD_EFFECT_ROWAP_BERRY: // consume and damage attacker if used special move + if (IsBattlerAlive(battlerId) + && TARGET_TURN_DAMAGED + && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) + && IS_MOVE_SPECIAL(gCurrentMove) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) + gBattleMoveDamage *= 2; + + effect = ITEM_HP_CHANGE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates; + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); + RecordItemEffectBattle(battlerId, HOLD_EFFECT_ROCKY_HELMET); + } + break; + case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move + effect = DamagedStatBoostBerryEffect(battlerId, STAT_DEF, SPLIT_PHYSICAL); + break; + case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move + effect = DamagedStatBoostBerryEffect(battlerId, STAT_SPDEF, SPLIT_SPECIAL); + break; } } break; @@ -7568,7 +7776,10 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move if (moveType == GetBattlerHoldEffectParam(battlerDef) && (moveType == TYPE_NORMAL || typeEffectivenessModifier >= UQ_4_12(2.0))) { - MulModifier(&finalModifier, UQ_4_12(0.5)); + if (abilityDef == ABILITY_RIPEN) + MulModifier(&finalModifier, UQ_4_12(0.25)); + else + MulModifier(&finalModifier, UQ_4_12(0.5)); if (updateFlags) gSpecialStatuses[battlerDef].berryReduced = 1; }