From d5d2cac60c9e8733648787ae674be1a0d1a5bd89 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 14:42:45 -0700 Subject: [PATCH 01/49] init branch --- include/constants/battle_script_commands.h | 55 ++++++++++++---------- include/constants/hold_effects.h | 8 ++++ src/battle_script_commands.c | 13 +++++ 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 2f52da319..5e27fe300 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -193,32 +193,35 @@ #define STAT_CHANGE_CANT_PREVENT 0x8 // cases for Cmd_moveend -#define MOVEEND_PROTECT_LIKE_EFFECT 0 -#define MOVEEND_RAGE 1 -#define MOVEEND_DEFROST 2 -#define MOVEEND_SYNCHRONIZE_TARGET 3 -#define MOVEEND_ABILITIES 4 -#define MOVEEND_ABILITIES_ATTACKER 5 -#define MOVEEND_STATUS_IMMUNITY_ABILITIES 6 -#define MOVEEND_SYNCHRONIZE_ATTACKER 7 -#define MOVEEND_CHOICE_MOVE 8 -#define MOVEEND_CHANGED_ITEMS 9 -#define MOVEEND_ATTACKER_INVISIBLE 10 -#define MOVEEND_ATTACKER_VISIBLE 11 -#define MOVEEND_TARGET_VISIBLE 12 -#define MOVEEND_ITEM_EFFECTS_TARGET 13 -#define MOVEEND_MOVE_EFFECTS2 14 -#define MOVEEND_ITEM_EFFECTS_ALL 15 -#define MOVEEND_KINGSROCK_SHELLBELL 16 -#define MOVEEND_SUBSTITUTE 17 -#define MOVEEND_UPDATE_LAST_MOVES 18 -#define MOVEEND_MIRROR_MOVE 19 -#define MOVEEND_NEXT_TARGET 20 -#define MOVEEND_LIFE_ORB 21 -#define MOVEEND_DANCER 22 -#define MOVEEND_EMERGENCY_EXIT 23 -#define MOVEEND_CLEAR_BITS 24 -#define MOVEEND_COUNT 25 +#define MOVEEND_PROTECT_LIKE_EFFECT 0 +#define MOVEEND_RAGE 1 +#define MOVEEND_DEFROST 2 +#define MOVEEND_SYNCHRONIZE_TARGET 3 +#define MOVEEND_ABILITIES 4 +#define MOVEEND_ABILITIES_ATTACKER 5 +#define MOVEEND_STATUS_IMMUNITY_ABILITIES 6 +#define MOVEEND_SYNCHRONIZE_ATTACKER 7 +#define MOVEEND_CHOICE_MOVE 8 +#define MOVEEND_CHANGED_ITEMS 9 +#define MOVEEND_ATTACKER_INVISIBLE 10 +#define MOVEEND_ATTACKER_VISIBLE 11 +#define MOVEEND_TARGET_VISIBLE 12 +#define MOVEEND_ITEM_EFFECTS_TARGET 13 +#define MOVEEND_MOVE_EFFECTS2 14 +#define MOVEEND_ITEM_EFFECTS_ALL 15 +#define MOVEEND_KINGSROCK_SHELLBELL 16 +#define MOVEEND_SUBSTITUTE 17 +#define MOVEEND_UPDATE_LAST_MOVES 18 +#define MOVEEND_MIRROR_MOVE 19 +#define MOVEEND_NEXT_TARGET 20 +#define MOVEEND_EJECT_BUTTON 21 +#define MOVEEND_RED_CARD 22 +#define MOVEEND_EJECT_PACK 23 +#define MOVEEND_LIFE_ORB 24 +#define MOVEEND_DANCER 25 +#define MOVEEND_EMERGENCY_EXIT 26 +#define MOVEEND_CLEAR_BITS 27 +#define MOVEEND_COUNT 28 // stat flags for Cmd_playstatchangeanimation #define BIT_HP 0x1 diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 85017cb40..c90f35651 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -136,6 +136,14 @@ #define HOLD_EFFECT_MEMORY 153 #define HOLD_EFFECT_PLATE 154 +// Gen8 hold effects +#define HOLD_EFFECT_EJECT_PACK 132 +#define HOLD_EFFECT_ROOM_SERVICE 133 +#define HOLD_EFFECT_BLUNDER_POLICY 134 +#define HOLD_EFFECT_HEAVY_DUTY_BOOTS 135 +#define HOLD_EFFECT_UTILITY_UMBRELLA 136 +#define HOLD_EFFECT_THROAT_SPRAY 137 + #define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) #endif // GUARD_HOLD_EFFECTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index bc427698e..45075ca37 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5006,6 +5006,19 @@ static void Cmd_moveend(void) RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove); gBattleScripting.moveendState++; break; + case MOVEEND_EJECT_BUTTON: + if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW) + { + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed + } + + BattleScript_ForceRandomSwitch + + case MOVEEND_RED_CARD: + + case MOVEEND_EJECT_PACK: + case MOVEEND_LIFE_ORB: if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIFE_ORB && IsBattlerAlive(gBattlerAttacker) From db6f9d05ec820177e7fe52d67b832b0e61187c02 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 15:28:58 -0700 Subject: [PATCH 02/49] add throat spray --- data/battle_scripts_1.s | 15 +++++++ include/battle_scripts.h | 1 + src/battle_script_commands.c | 13 +++--- src/battle_util.c | 81 ++++++++++++++++++++---------------- 4 files changed, 70 insertions(+), 40 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3eb1f5cbe..32ba6d128 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5616,6 +5616,21 @@ BattleScript_TargetItemStatRaise:: removeitem BS_TARGET BattleScript_TargetItemStatRaiseRemoveItemRet: return + +BattleScript_AttackerItemStatRaise:: + copybyte sBATTLER, gBattlerAttacker + statbuffchange 0, BattleScript_AttackerItemStatRaiseRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_AttackerItemStatRaiseRet + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + waitanimation + setgraphicalstatchangevalues + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + waitanimation + printstring STRINGID_USINGXTHEYOFZN + waitmessage 0x40 + removeitem BS_ATTACKER +BattleScript_AttackerItemStatRaiseRet: + return BattleScript_MistProtected:: pause 0x20 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 3566a1c4d..1efb9052d 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -350,5 +350,6 @@ extern const u8 BattleScript_EmergencyExitWild[]; extern const u8 BattleScript_EmergencyExitWildNoPopUp[]; extern const u8 BattleScript_CheekPouchActivates[]; extern const u8 BattleScript_AnnounceAirLockCloudNine[]; +extern const u8 BattleScript_AttackerItemStatRaise[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 45075ca37..b846e81ec 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5007,18 +5007,21 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_EJECT_BUTTON: - if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW) + /*if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW) { u8 battlers[4] = {0, 1, 2, 3}; SortBattlersBySpeed } - BattleScript_ForceRandomSwitch - + BattleScript_ForceRandomSwitch*/ + gBattleScripting.moveendState++; + break; case MOVEEND_RED_CARD: - + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_PACK: - + gBattleScripting.moveendState++; + break; case MOVEEND_LIFE_ORB: if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIFE_ORB && IsBattlerAlive(gBattlerAttacker) diff --git a/src/battle_util.c b/src/battle_util.c index aeeefa734..dba898693 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5738,44 +5738,55 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; case ITEMEFFECT_KINGSROCK_SHELLBELL: - if (gBattleMoveDamage) + switch (atkHoldEffect) { - switch (atkHoldEffect) + case HOLD_EFFECT_FLINCH: + if (gBattleMoveDamage != 0 // need to have done damage + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && TARGET_TURN_DAMAGED + && (Random() % 100) < atkHoldEffectParam + && gBattleMoves[gCurrentMove].flags & FLAG_KINGSROCK_AFFECTED + && gBattleMons[gBattlerTarget].hp) { - case HOLD_EFFECT_FLINCH: - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && TARGET_TURN_DAMAGED - && (Random() % 100) < atkHoldEffectParam - && gBattleMoves[gCurrentMove].flags & FLAG_KINGSROCK_AFFECTED - && gBattleMons[gBattlerTarget].hp) - { - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - BattleScriptPushCursor(); - SetMoveEffect(FALSE, 0); - BattleScriptPop(); - } - break; - case HOLD_EFFECT_SHELL_BELL: - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && gSpecialStatuses[gBattlerTarget].dmg != 0 - && gSpecialStatuses[gBattlerTarget].dmg != 0xFFFF - && gBattlerAttacker != gBattlerTarget - && gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP - && gBattleMons[gBattlerAttacker].hp != 0) - { - gLastUsedItem = atkItem; - gPotentialItemEffectBattler = gBattlerAttacker; - gBattleScripting.battler = gBattlerAttacker; - gBattleMoveDamage = (gSpecialStatuses[gBattlerTarget].dmg / atkHoldEffectParam) * -1; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = -1; - gSpecialStatuses[gBattlerTarget].dmg = 0; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret; - effect++; - } - break; + gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; + BattleScriptPushCursor(); + SetMoveEffect(FALSE, 0); + BattleScriptPop(); } + break; + case HOLD_EFFECT_SHELL_BELL: + if (gBattleMoveDamage != 0 // need to have done damage + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && gSpecialStatuses[gBattlerTarget].dmg != 0 + && gSpecialStatuses[gBattlerTarget].dmg != 0xFFFF + && gBattlerAttacker != gBattlerTarget + && gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP + && gBattleMons[gBattlerAttacker].hp != 0) + { + gLastUsedItem = atkItem; + gPotentialItemEffectBattler = gBattlerAttacker; + gBattleScripting.battler = gBattlerAttacker; + gBattleMoveDamage = (gSpecialStatuses[gBattlerTarget].dmg / atkHoldEffectParam) * -1; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = -1; + gSpecialStatuses[gBattlerTarget].dmg = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret; + effect++; + } + break; + case HOLD_EFFECT_THROAT_SPRAY: // doesn't need to be a damaging move + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && gBattleMons[gBattlerAttacker].hp != 0 + && gBattleMoves[gCurrentMove].flags & FLAG_SOUND) + { + gLastUsedItem = atkItem; + gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE); + effect = ITEM_STATS_CHANGE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; + } + break; } break; case ITEMEFFECT_TARGET: From 0cdab790dc53d9202442263a8f7a58a5e59bc280 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 15:40:20 -0700 Subject: [PATCH 03/49] add blunder policy --- include/battle.h | 1 + src/battle_script_commands.c | 3 +++ src/battle_util.c | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/battle.h b/include/battle.h index 488e0fc51..15658fdb5 100644 --- a/include/battle.h +++ b/include/battle.h @@ -542,6 +542,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. + bool8 blunderPolicy; }; #define GET_MOVE_TYPE(move, typeArg) \ diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b846e81ec..4d98390d6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1595,6 +1595,9 @@ static void Cmd_accuracycheck(void) if ((Random() % 100 + 1) > GetTotalAccuracy(gBattlerAttacker, gBattlerTarget, move)) { gMoveResultFlags |= MOVE_RESULT_MISSED; + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_BLUNDER_POLICY) + gBattleStruct->blunderPolicy = TRUE; // only activates from missing through acc/evasion checks + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && (gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY)) gBattleCommunication[6] = 2; diff --git a/src/battle_util.c b/src/battle_util.c index dba898693..bc5e6b992 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5778,7 +5778,8 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) case HOLD_EFFECT_THROAT_SPRAY: // doesn't need to be a damaging move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 - && gBattleMoves[gCurrentMove].flags & FLAG_SOUND) + && gBattleMoves[gCurrentMove].flags & FLAG_SOUND + && gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] < MAX_STAT_STAGE) { gLastUsedItem = atkItem; gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE); @@ -5787,6 +5788,19 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; } break; + case HOLD_EFFECT_BLUNDER_POLICY: + if (gBattleStruct->blunderPolicy + && gBattleMons[gBattlerAttacker].hp != 0 + && gBattleMons[gBattlerAttacker].statStages[STAT_SPEED] < MAX_STAT_STAGE) + { + gBattleStruct->blunderPolicy = FALSE; + gLastUsedItem = atkItem; + gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPEED, 2, FALSE); + effect = ITEM_STATS_CHANGE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; + } + break; } break; case ITEMEFFECT_TARGET: From c1dd3fca2112438ccfd20541a55d1677c7a9bb9f Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 18:00:14 -0700 Subject: [PATCH 04/49] add room service --- data/battle_scripts_1.s | 33 +++++++++++++++++++++++++++++++++ src/battle_util.c | 14 ++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 32ba6d128..14751559e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1842,6 +1842,39 @@ BattleScript_EffectMagnetRise: goto BattleScript_MoveEnd BattleScript_EffectTrickRoom: + attackcanceler + attackstring + ppreduce + setroom + attackanimation + waitanimation + printfromtable gRoomsStringIds + waitmessage 0x40 + savetarget + setbyte gBattlerTarget, 0 +RoomServiceLoop: + copybyte sBATTLER, gBattlerTarget + jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_ROOM_SERVICE, RoomServiceLoop_NextBattler + jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPEED, MIN_STAT_STAGE, RoomServiceLoop_NextBattler + setstatchanger STAT_SPEED, 1, TRUE + statbuffchange 0, RoomServiceLoop_NextBattler + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, RoomServiceLoop_NextBattler + playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL + waitanimation + playstatchangeanimation BS_TARGET, BIT_SPEED, STAT_CHANGE_NEGATIVE + +@ setgraphicalstatchangevalues +@ playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 +@ waitanimation + printstring STRINGID_USINGXTHEYOFZN + waitmessage 0x40 + removeitem BS_TARGET +RoomServiceLoop_NextBattler: + addbyte gBattlerTarget, 0x1 + jumpifbytenotequal gBattlerTarget, gBattlersCount, RoomServiceLoop + restoretarget + goto BattleScript_MoveEnd + BattleScript_EffectWonderRoom: BattleScript_EffectMagicRoom: attackcanceler diff --git a/src/battle_util.c b/src/battle_util.c index bc5e6b992..3c1a864d1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5299,6 +5299,20 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptPushCursorAndCallback(BattleScript_AirBaloonMsgIn); RecordItemEffectBattle(battlerId, HOLD_EFFECT_AIR_BALLOON); break; + case HOLD_EFFECT_ROOM_SERVICE: + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gBattleMons[battlerId].statStages[STAT_SPEED] > MIN_STAT_STAGE) + { + PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPEED); + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); + + gEffectBattler = battlerId; + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + gBattleScripting.animArg1 = 0xE + STAT_SPEED; + gBattleScripting.animArg2 = 0; + BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + break; } if (effect) From 7fffe23e63c7a9f81ff35f4f4b76e25cd01ea22e Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 20:22:05 -0700 Subject: [PATCH 05/49] add terrain seeds --- asm/macros/battle_script.inc | 5 +++ data/battle_scripts_1.s | 36 ++++++++++++++++-- include/battle_scripts.h | 1 + include/battle_util.h | 1 + include/constants/battle_script_commands.h | 1 + include/constants/hold_effects.h | 6 +++ src/battle_script_commands.c | 28 ++++++++++++++ src/battle_util.c | 44 ++++++++++++++++++++++ 8 files changed, 118 insertions(+), 4 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 135960c12..1de63ad16 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1760,6 +1760,11 @@ various BS_ABILITY_BATTLER, VARIOUS_DESTROY_ABILITY_POPUP .endm + .macro doterrainseed battler:req, ptr:req + various \battler, VARIOUS_TERRAIN_SEED + .4byte \ptr + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 14751559e..40f4d0d93 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1520,6 +1520,7 @@ BattleScript_EffectPsychicTerrain: waitanimation printfromtable gTerrainStringIds waitmessage 0x40 + call BattleScript_TerrainSeedLoop goto BattleScript_MoveEnd BattleScript_EffectTopsyTurvy: @@ -1862,10 +1863,6 @@ RoomServiceLoop: playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL waitanimation playstatchangeanimation BS_TARGET, BIT_SPEED, STAT_CHANGE_NEGATIVE - -@ setgraphicalstatchangevalues -@ playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 -@ waitanimation printstring STRINGID_USINGXTHEYOFZN waitmessage 0x40 removeitem BS_TARGET @@ -6882,6 +6879,19 @@ BattleScript_SnowWarningActivates:: playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES, NULL call BattleScript_WeatherFormChanges end3 + +BattleScript_TerrainSeedLoop: + savetarget + setbyte gBattlerTarget, 0 +TerrainSeedLoop: + copybyte sBATTLER, gBattlerTarget + doterrainseed BS_TARGET, TerrainSeedLoop_NextBattler + removeitem BS_TARGET +TerrainSeedLoop_NextBattler: + addbyte gBattlerTarget, 0x1 + jumpifbytenotequal gBattlerTarget, gBattlersCount, TerrainSeedLoop + restoretarget + return BattleScript_ElectricSurgeActivates:: pause 0x20 @@ -6889,6 +6899,7 @@ BattleScript_ElectricSurgeActivates:: printstring STRINGID_TERRAINBECOMESELECTRIC waitstate playanimation BS_SCRIPTING, B_ANIM_TERRAIN_ELECTRIC, NULL + call BattleScript_TerrainSeedLoop end3 BattleScript_MistySurgeActivates:: @@ -6897,6 +6908,7 @@ BattleScript_MistySurgeActivates:: printstring STRINGID_TERRAINBECOMESMISTY waitstate playanimation BS_SCRIPTING, B_ANIM_TERRAIN_MISTY, NULL + call BattleScript_TerrainSeedLoop end3 BattleScript_GrassySurgeActivates:: @@ -6905,6 +6917,7 @@ BattleScript_GrassySurgeActivates:: printstring STRINGID_TERRAINBECOMESGRASSY waitstate playanimation BS_SCRIPTING, B_ANIM_TERRAIN_GRASSY, NULL + call BattleScript_TerrainSeedLoop end3 BattleScript_PsychicSurgeActivates:: @@ -6913,6 +6926,7 @@ BattleScript_PsychicSurgeActivates:: printstring STRINGID_TERRAINBECOMESPSYCHIC waitstate playanimation BS_SCRIPTING, B_ANIM_TERRAIN_PSYCHIC, NULL + call BattleScript_TerrainSeedLoop end3 BattleScript_BadDreamsActivates:: @@ -7612,6 +7626,20 @@ BattleScript_82DB85B:: call BattleScript_StatUp 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 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 1efb9052d..7153eebb8 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -209,6 +209,7 @@ extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItem[]; extern const u8 BattleScript_HangedOnMsg[]; extern const u8 BattleScript_BerryConfuseHealEnd2[]; 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[]; diff --git a/include/battle_util.h b/include/battle_util.h index f7699fced..602901f93 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -130,5 +130,6 @@ void ClearIllusionMon(u32 battlerId); bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId); bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); u8 GetBattleMoveSplit(u32 moveId); +u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 5e27fe300..d06db22b4 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -167,6 +167,7 @@ #define VARIOUS_PARALYZE_TYPE_IMMUNITY 100 #define VARIOUS_JUMP_IF_ABSENT 101 #define VARIOUS_DESTROY_ABILITY_POPUP 102 +#define VARIOUS_TERRAIN_SEED 103 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index c90f35651..890f99a3a 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -146,4 +146,10 @@ #define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) +// terrain seed params +#define HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN 0 +#define HOLD_EFFECT_PARAM_GRASSY_TERRAIN 1 +#define HOLD_EFFECT_PARAM_MISTY_TERRAIN 2 +#define HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN 3 + #endif // GUARD_HOLD_EFFECTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4d98390d6..11326d82f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8322,6 +8322,34 @@ static void Cmd_various(void) case VARIOUS_DESTROY_ABILITY_POPUP: DestroyAbilityPopUp(gActiveBattler); break; + case VARIOUS_TERRAIN_SEED: + if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_SEEDS) + { + u8 effect = 0; + u16 item = gBattleMons[gActiveBattler].item; + switch (GetBattlerHoldEffectParam(gActiveBattler)) + { + case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: + effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, FALSE); + break; + case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: + effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, FALSE); + break; + case HOLD_EFFECT_PARAM_MISTY_TERRAIN: + effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, FALSE); + break; + case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: + effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, FALSE); + break; + } + if (effect) + { + //gBattlescriptCurrInstr += 7; + return; + } + } + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + return; } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index 3c1a864d1..1a2589938 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5073,6 +5073,33 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId) return 0; } +u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute) +{ + if (gFieldStatuses & terrainFlag && gBattleMons[battler].statStages[statId] < MAX_STAT_STAGE) + { + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); + + gLastUsedItem = itemId; // for surge abilities + gEffectBattler = battler; + gBattleScripting.battler = battler; + SET_STATCHANGER(statId, 1, FALSE); + gBattleScripting.animArg1 = 0xE + statId; + gBattleScripting.animArg2 = 0; + if (execute) + { + BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; + } + return ITEM_STATS_CHANGE; + } + return 0; +} + static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal) { if (HasEnoughHpToEatBerry(battlerId, 2, itemId)) @@ -5312,6 +5339,23 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); effect = ITEM_STATS_CHANGE; } + case HOLD_EFFECT_SEEDS: + switch (GetBattlerHoldEffectParam(battlerId)) + { + case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: + effect = TryHandleSeed(battlerId, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, gLastUsedItem, TRUE); + break; + case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: + effect = TryHandleSeed(battlerId, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, gLastUsedItem, TRUE); + break; + case HOLD_EFFECT_PARAM_MISTY_TERRAIN: + effect = TryHandleSeed(battlerId, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, gLastUsedItem, TRUE); + break; + case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: + effect = TryHandleSeed(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, gLastUsedItem, TRUE); + break; + + } break; } From bf644f23a76e12c9d801ef0ef73446df0b28cc16 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 20:53:48 -0700 Subject: [PATCH 06/49] add heavy duty boots --- include/battle_util.h | 1 + src/battle_script_commands.c | 4 ++++ src/battle_util.c | 17 +++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/include/battle_util.h b/include/battle_util.h index 602901f93..40f92f704 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -131,5 +131,6 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId); bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); u8 GetBattleMoveSplit(u32 moveId); u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute); +bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 11326d82f..6185c5231 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5811,6 +5811,7 @@ static void Cmd_switchineffects(void) if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES) && GetBattlerAbility(gActiveBattler) != ABILITY_MAGIC_GUARD + && IsBattlerAffectedByHazards(gActiveBattler, FALSE) && IsBattlerGrounded(gActiveBattler)) { u8 spikesDmg = (5 - gSideTimers[GetBattlerSide(gActiveBattler)].spikesAmount) * 2; @@ -5823,6 +5824,7 @@ static void Cmd_switchineffects(void) } else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK) + && IsBattlerAffectedByHazards(gActiveBattler, FALSE) && GetBattlerAbility(gActiveBattler) != ABILITY_MAGIC_GUARD) { gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_STEALTH_ROCK_DAMAGED; @@ -5833,6 +5835,7 @@ static void Cmd_switchineffects(void) } else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES) + && IsBattlerAffectedByHazards(gActiveBattler, TRUE) && IsBattlerGrounded(gActiveBattler)) { gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_TOXIC_SPIKES_DAMAGED; @@ -5866,6 +5869,7 @@ static void Cmd_switchineffects(void) } else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STICKY_WEB_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STICKY_WEB) + && IsBattlerAffectedByHazards(gActiveBattler, FALSE) && IsBattlerGrounded(gActiveBattler)) { gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_STICKY_WEB_DAMAGED; diff --git a/src/battle_util.c b/src/battle_util.c index 1a2589938..56de96be3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7913,3 +7913,20 @@ u8 GetBattleMoveSplit(u32 moveId) else return SPLIT_SPECIAL; } + +bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes) +{ + bool32 ret = TRUE; + u32 holdEffect = GetBattlerHoldEffect(gActiveBattler, TRUE); + if (toxicSpikes && holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS && !IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON)) + { + ret = FALSE; + RecordItemEffectBattle(battlerId, holdEffect); + } + else if (holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS) + { + ret = FALSE; + RecordItemEffectBattle(battlerId, holdEffect); + } + return ret; +} From 5eb49722c0a14cf6197d41952c0dd5bc92a1f0ab Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 7 Jan 2021 19:33:39 -0700 Subject: [PATCH 07/49] add red card effect --- data/battle_scripts_1.s | 39 ++++++++++++++++++ include/battle.h | 1 + include/battle_scripts.h | 1 + include/battle_util.h | 3 +- include/constants/battle_script_commands.h | 6 +++ include/constants/battle_string_ids.h | 3 +- src/battle_main.c | 4 ++ src/battle_message.c | 2 + src/battle_script_commands.c | 40 +++++++++++++++---- src/battle_util.c | 46 ++++++++++++++++++++++ 10 files changed, 136 insertions(+), 9 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 40f4d0d93..e4e980276 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5592,16 +5592,27 @@ BattleScript_RoarSuccessSwitch:: waitstate printstring STRINGID_PKMNWASDRAGGEDOUT switchineffects BS_TARGET + jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessSwitch_Ret + setbyte sSWITCH_CASE, B_SWITCH_NORMAL goto BattleScript_MoveEnd +BattleScript_RoarSuccessSwitch_Ret: + swapattackerwithtarget @ continuation of RedCardActivates + removeitem BS_TARGET + setbyte sSWITCH_CASE, B_SWITCH_NORMAL + return BattleScript_RoarSuccessEndBattle:: call BattleScript_RoarSuccessRet + setbyte sSWITCH_CASE, B_SWITCH_NORMAL setoutcomeonteleport BS_ATTACKER finishaction BattleScript_RoarSuccessRet: + jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_HIT, BattleScript_RoarSuccessRet_Ret + jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessRet_Ret attackanimation waitanimation +BattleScript_RoarSuccessRet_Ret: switchoutabilities BS_TARGET returntoball BS_TARGET waitstate @@ -7790,3 +7801,31 @@ BattleScript_AnnounceAirLockCloudNine:: waitmessage 0x40 call BattleScript_WeatherFormChanges end3 + +BattleScript_RedCardActivates:: + jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_RedCardEnd + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + printstring STRINGID_REDCARDACTIVATE + waitmessage 0x40 + swapattackerwithtarget + jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain + jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups + setbyte sSWITCH_CASE, B_SWITCH_RED_CARD + forcerandomswitch BattleScript_RedCardEnd + @ changes the current battle script. the rest happens in BattleScript_RoarSuccessSwitch_Ret, if switch is successful + return +BattleScript_RedCardEnd: + return +BattleScript_RedCardIngrain: + printstring STRINGID_PKMNANCHOREDITSELF + waitmessage 0x40 + removeitem BS_SCRIPTING + swapattackerwithtarget + return +BattleScript_RedCardSuctionCups: + printstring STRINGID_PKMNANCHORSITSELFWITH + waitmessage 0x40 + removeitem BS_SCRIPTING + swapattackerwithtarget + return + diff --git a/include/battle.h b/include/battle.h index 15658fdb5..a7b23061d 100644 --- a/include/battle.h +++ b/include/battle.h @@ -614,6 +614,7 @@ struct BattleScripting u16 multihitMoveEffect; u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN. bool8 fixedPopup; // force ability popup to stick until manually called back + u8 switchCase; // special switching conditions, eg. red card }; // rom_80A5C6C diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 7153eebb8..2c5134ade 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -352,5 +352,6 @@ extern const u8 BattleScript_EmergencyExitWildNoPopUp[]; extern const u8 BattleScript_CheekPouchActivates[]; extern const u8 BattleScript_AnnounceAirLockCloudNine[]; extern const u8 BattleScript_AttackerItemStatRaise[]; +extern const u8 BattleScript_RedCardActivates[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_util.h b/include/battle_util.h index 40f92f704..fe7972b49 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -132,5 +132,6 @@ bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); u8 GetBattleMoveSplit(u32 moveId); u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute); bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes); - +void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); +bool32 TestSheerForceFlag(u8 battler, u16 move); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index d06db22b4..17e02a50c 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -36,6 +36,7 @@ #define sMULTIHIT_EFFECT gBattleScripting + 0x30 #define sILLUSION_NICK_HACK gBattleScripting + 0x32 #define sFIXED_ABILITY_POPUP gBattleScripting + 0x33 +#define sSWITCH_CASE gBattleScripting + 0x34 #define cMULTISTRING_CHOOSER gBattleCommunication + 5 @@ -234,4 +235,9 @@ #define BIT_ACC 0x40 #define BIT_EVASION 0x80 +// switch cases +#define B_SWITCH_NORMAL 0 +#define B_SWITCH_HIT 1 // dragon tail, circle throw +#define B_SWITCH_RED_CARD 2 + #endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 9348d67d5..76ac13940 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -558,8 +558,9 @@ #define STRINGID_AURABREAKENTERS 554 #define STRINGID_COMATOSEENTERS 555 #define STRINGID_SCREENCLEANERENTERS 556 +#define STRINGID_REDCARDACTIVATE 557 -#define BATTLESTRINGS_COUNT 557 +#define BATTLESTRINGS_COUNT 558 //// multichoice message IDs // switch in ability message diff --git a/src/battle_main.c b/src/battle_main.c index 48129c523..87f020227 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3041,6 +3041,10 @@ void SwitchInClearSetData(void) gBattleResources->flags->flags[gActiveBattler] = 0; gCurrentMove = 0; gBattleStruct->arenaTurnCounter = 0xFF; + + // reset damage to prevent things like red card activating if the switched-in mon is holding it + gSpecialStatuses[gActiveBattler].physicalDmg = 0; + gSpecialStatuses[gActiveBattler].specialDmg = 0; ClearBattlerMoveHistory(gActiveBattler); ClearBattlerAbilityHistory(gActiveBattler); diff --git a/src/battle_message.c b/src/battle_message.c index 35ccc6e26..4a35e2939 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -685,9 +685,11 @@ static const u8 sText_FairyAuraActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} static const u8 sText_AuraBreakActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} reversed all\nother POKéMON's auras!"); static const u8 sText_ComatoseActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is drowsing!"); static const u8 sText_ScreenCleanerActivates[] = _("All screens on the field were\ncleansed!"); +static const u8 sText_RedCardActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} held up its {B_LAST_ITEM}\nagainst {B_ATK_NAME_WITH_PREFIX}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_REDCARDACTIVATE - 12] = sText_RedCardActivate, [STRINGID_STATWASNOTLOWERED - 12] = sText_StatWasNotLowered, [STRINGID_CLOAKEDINAFREEZINGLIGHT - 12] = sText_CloakedInAFreezingLight, [STRINGID_DESTINYKNOTACTIVATES - 12] = sText_DestinyKnotActivates, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6185c5231..a5e959d9b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5010,22 +5010,47 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_EJECT_BUTTON: - /*if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW) - { - u8 battlers[4] = {0, 1, 2, 3}; - SortBattlersBySpeed - } - - BattleScript_ForceRandomSwitch*/ gBattleScripting.moveendState++; break; case MOVEEND_RED_CARD: + if (gCurrentMove != MOVE_DRAGON_TAIL + && gCurrentMove != MOVE_CIRCLE_THROW + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && IsBattlerAlive(gBattlerAttacker) + && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) + && (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER || (gBattleTypeFlags & BATTLE_TYPE_TRAINER))) + { + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u8 battler = battlers[i]; + // attacker is the one to be switched out, battler is one with red card + if (battler != gBattlerAttacker + && IsBattlerAlive(battler) + && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) + && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)) + { + gLastUsedItem = gBattleMons[battler].item; + gActiveBattler = gBattleScripting.battler = battler; // battler with red card + gEffectBattler = gBattlerAttacker; + if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE) + gBattlescriptCurrInstr = BattleScript_MoveEnd; // prevent user switch-in selection + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RedCardActivates; + effect = TRUE; + break; // only fastest red card activates + } + } + } gBattleScripting.moveendState++; break; case MOVEEND_EJECT_PACK: gBattleScripting.moveendState++; break; case MOVEEND_LIFE_ORB: + // TODO shell bell goes here too if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIFE_ORB && IsBattlerAlive(gBattlerAttacker) && !(GetBattlerAbility(gBattlerAttacker) == ABILITY_SHEER_FORCE && gBattleMoves[gCurrentMove].flags & FLAG_SHEER_FORCE_BOOST) @@ -7981,6 +8006,7 @@ static void Cmd_various(void) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED) { + gBattleScripting.switchCase = B_SWITCH_HIT; gBattlescriptCurrInstr = BattleScript_ForceRandomSwitch; } else diff --git a/src/battle_util.c b/src/battle_util.c index 56de96be3..df79bccea 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7930,3 +7930,49 @@ bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes) } return ret; } + +bool32 TestSheerForceFlag(u8 battler, u16 move) +{ + if (GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && gBattleMoves[move].flags & FLAG_SHEER_FORCE_BOOST) + return TRUE; + else + return FALSE; +} + +void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast) +{ + int i, j, currSpeed, currBattler; + u16 speeds[4] = {0}; + + for (i = 0; i < gBattlersCount; i++) + speeds[i] = GetBattlerTotalSpeedStat(battlers[i]); + + for (i = 1; i < gBattlersCount; i++) + { + currBattler = battlers[i]; + currSpeed = speeds[i]; + j = i - 1; + + if (slowToFast) + { + while (j >= 0 && speeds[j] > currSpeed) + { + battlers[j + 1] = battlers[j]; + speeds[j + 1] = speeds[j]; + j = j - 1; + } + } + else + { + while (j >= 0 && speeds[j] < currSpeed) + { + battlers[j + 1] = battlers[j]; + speeds[j + 1] = speeds[j]; + j = j - 1; + } + } + + battlers[j + 1] = currBattler; + speeds[j + 1] = currSpeed; + } +} From 0118723a9ca69aedf04b6bd7cddf8a832e004c96 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 7 Jan 2021 20:31:27 -0700 Subject: [PATCH 08/49] add eject button --- data/battle_scripts_1.s | 23 ++++++++++++++++++- include/battle_ai_script_commands.h | 1 + include/battle_scripts.h | 1 + include/constants/battle_string_ids.h | 3 ++- src/battle_ai_script_commands.c | 3 +-- src/battle_message.c | 2 ++ src/battle_script_commands.c | 33 ++++++++++++++++++++++++++- 7 files changed, 61 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e4e980276..8f11d1d67 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7803,7 +7803,7 @@ BattleScript_AnnounceAirLockCloudNine:: end3 BattleScript_RedCardActivates:: - jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_RedCardEnd + jumpifcantswitch BS_ATTACKER, BattleScript_RedCardEnd playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_REDCARDACTIVATE waitmessage 0x40 @@ -7829,3 +7829,24 @@ BattleScript_RedCardSuctionCups: swapattackerwithtarget return +BattleScript_EjectButtonActivates:: + jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd + makevisible BS_ATTACKER + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + printstring STRINGID_EJECTBUTTONACTIVATE + waitmessage 0x40 + removeitem BS_SCRIPTING + openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd + switchoutabilities BS_SCRIPTING + waitstate + switchhandleorder BS_SCRIPTING 0x2 + returntoball BS_SCRIPTING + getswitchedmondata BS_SCRIPTING + switchindataupdate BS_SCRIPTING + hpthresholds BS_SCRIPTING + printstring 0x3 + switchinanim BS_SCRIPTING 0x1 + waitstate + switchineffects BS_SCRIPTING +BattleScript_EjectButtonEnd: + return diff --git a/include/battle_ai_script_commands.h b/include/battle_ai_script_commands.h index be3787398..dc5459cab 100644 --- a/include/battle_ai_script_commands.h +++ b/include/battle_ai_script_commands.h @@ -23,5 +23,6 @@ void RecordAbilityBattle(u8 battlerId, u16 abilityId); void ClearBattlerAbilityHistory(u8 battlerId); void RecordItemEffectBattle(u8 battlerId, u8 itemEffect); void ClearBattlerItemEffectHistory(u8 battlerId); +s32 CountUsablePartyMons(u8 battlerId); #endif // GUARD_BATTLE_AI_SCRIPT_COMMANDS_H diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 2c5134ade..88ffe3505 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -353,5 +353,6 @@ extern const u8 BattleScript_CheekPouchActivates[]; extern const u8 BattleScript_AnnounceAirLockCloudNine[]; extern const u8 BattleScript_AttackerItemStatRaise[]; extern const u8 BattleScript_RedCardActivates[]; +extern const u8 BattleScript_EjectButtonActivates[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 76ac13940..a634e7f77 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -559,8 +559,9 @@ #define STRINGID_COMATOSEENTERS 555 #define STRINGID_SCREENCLEANERENTERS 556 #define STRINGID_REDCARDACTIVATE 557 +#define STRINGID_EJECTBUTTONACTIVATE 558 -#define BATTLESTRINGS_COUNT 558 +#define BATTLESTRINGS_COUNT 559 //// multichoice message IDs // switch in ability message diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 8a5f423a4..93a5e33db 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -54,7 +54,6 @@ static void RecordLastUsedMoveByTarget(void); static void BattleAI_DoAIProcessing(void); static void AIStackPushVar(const u8 *); static bool8 AIStackPop(void); -static s32 CountUsablePartyMons(u8 battlerId); static s32 AI_GetAbility(u32 battlerId, bool32 guess); static void Cmd_if_random_less_than(void); @@ -1614,7 +1613,7 @@ static void Cmd_nullsub_2B(void) { } -static s32 CountUsablePartyMons(u8 battlerId) +s32 CountUsablePartyMons(u8 battlerId) { s32 battlerOnField1, battlerOnField2, i, ret; struct Pokemon *party; diff --git a/src/battle_message.c b/src/battle_message.c index 4a35e2939..f52c30cca 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -686,9 +686,11 @@ static const u8 sText_AuraBreakActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} static const u8 sText_ComatoseActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is drowsing!"); static const u8 sText_ScreenCleanerActivates[] = _("All screens on the field were\ncleansed!"); static const u8 sText_RedCardActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} held up its {B_LAST_ITEM}\nagainst {B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_EjectButtonActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is switched\nout with the {B_LAST_ITEM}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_EJECTBUTTONACTIVATE - 12] = sText_EjectButtonActivate, [STRINGID_REDCARDACTIVATE - 12] = sText_RedCardActivate, [STRINGID_STATWASNOTLOWERED - 12] = sText_StatWasNotLowered, [STRINGID_CLOAKEDINAFREEZINGLIGHT - 12] = sText_CloakedInAFreezingLight, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a5e959d9b..0c72c581d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5010,6 +5010,36 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_EJECT_BUTTON: + if (gCurrentMove != MOVE_DRAGON_TAIL + && gCurrentMove != MOVE_CIRCLE_THROW + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && IsBattlerAlive(gBattlerAttacker) + && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) + && (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER || (gBattleTypeFlags & BATTLE_TYPE_TRAINER))) + { + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u8 battler = battlers[i]; + // attacker is the damage-dealer, battler is mon to be switched out + if (IsBattlerAlive(battler) + && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_BUTTON + && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) + && CountUsablePartyMons(battler) > 0) + { + gActiveBattler = gBattleScripting.battler = battler; + gLastUsedItem = gBattleMons[battler].item; + if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE) + gBattlescriptCurrInstr = BattleScript_MoveEnd; // prevent user switch-in selection + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EjectButtonActivates; + effect = TRUE; + break; // only the fastest Eject Button activates + } + } + } gBattleScripting.moveendState++; break; case MOVEEND_RED_CARD: @@ -5030,7 +5060,8 @@ static void Cmd_moveend(void) && IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD - && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)) + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) + && CountUsablePartyMons(battler) > 0) { gLastUsedItem = gBattleMons[battler].item; gActiveBattler = gBattleScripting.battler = battler; // battler with red card From 2bd5167a6c62c7ebc8ff3d55df7ddd7a35cd1686 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 7 Jan 2021 21:11:56 -0700 Subject: [PATCH 09/49] eject pack --- data/battle_scripts_1.s | 12 ++++++++++++ include/battle.h | 1 + include/battle_scripts.h | 3 +++ src/battle_script_commands.c | 26 ++++++++++++++++++++++++-- src/battle_util.c | 17 +++++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8f11d1d67..9d14f2b0e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7850,3 +7850,15 @@ BattleScript_EjectButtonActivates:: switchineffects BS_SCRIPTING BattleScript_EjectButtonEnd: return + +BattleScript_EjectPackActivate_Ret:: + goto BattleScript_EjectButtonActivates + +BattleScript_EjectPackActivate_End2:: + call BattleScript_EjectPackActivate_Ret + end2 + +BattleScript_EjectPackActivates:: + jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd + goto BattleScript_EjectPackActivate_Ret + diff --git a/include/battle.h b/include/battle.h index a7b23061d..c80dbcbc7 100644 --- a/include/battle.h +++ b/include/battle.h @@ -148,6 +148,7 @@ struct ProtectStruct struct SpecialStatus { + u8 statFell:1; u8 statLowered:1; u8 lightningRodRedirected:1; u8 restoredBattlerSprite: 1; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 88ffe3505..aa51b6afa 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -354,5 +354,8 @@ extern const u8 BattleScript_AnnounceAirLockCloudNine[]; extern const u8 BattleScript_AttackerItemStatRaise[]; extern const u8 BattleScript_RedCardActivates[]; extern const u8 BattleScript_EjectButtonActivates[]; +extern const u8 BattleScript_EjectPackActivate_Ret[]; +extern const u8 BattleScript_EjectPackActivate_End2[]; +extern const u8 BattleScript_EjectPackActivates[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0c72c581d..9dcb58da8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5027,7 +5027,7 @@ static void Cmd_moveend(void) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_BUTTON && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) - && CountUsablePartyMons(battler) > 0) + && CountUsablePartyMons(battler) > 0) // has mon to switch into { gActiveBattler = gBattleScripting.battler = battler; gLastUsedItem = gBattleMons[battler].item; @@ -5061,7 +5061,7 @@ static void Cmd_moveend(void) && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) - && CountUsablePartyMons(battler) > 0) + && CountUsablePartyMons(battler) > 0) // has mon to switch into { gLastUsedItem = gBattleMons[battler].item; gActiveBattler = gBattleScripting.battler = battler; // battler with red card @@ -5078,6 +5078,27 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_EJECT_PACK: + { + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u8 battler = battlers[i]; + if (IsBattlerAlive(battler) + && gSpecialStatuses[battler].statFell + && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_PACK + && CountUsablePartyMons(battler) > 0) // has mon to switch into + { + gSpecialStatuses[battler].statFell = FALSE; + gActiveBattler = gBattleScripting.battler = battler; + gLastUsedItem = gBattleMons[battler].item; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EjectPackActivates; + effect = TRUE; + break; // only fastest eject pack activates + } + } + } gBattleScripting.moveendState++; break; case MOVEEND_LIFE_ORB: @@ -9095,6 +9116,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr index++; gBattleTextBuff2[index] = B_BUFF_EOS; + gSpecialStatuses[gActiveBattler].statFell = TRUE; // for eject pack if (gBattleMons[gActiveBattler].statStages[statId] == MIN_STAT_STAGE) gBattleCommunication[MULTISTRING_CHOOSER] = 2; else diff --git a/src/battle_util.c b/src/battle_util.c index df79bccea..f16c538ac 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5357,6 +5357,23 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; + case HOLD_EFFECT_EJECT_PACK: + if (gSpecialStatuses[battlerId].statFell) + { + gSpecialStatuses[battlerId].statFell = FALSE; + gActiveBattler = gBattleScripting.battler = battlerId; + effect = ITEM_STATS_CHANGE; + if (moveTurn) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret; + } + else + { + BattleScriptExecute(BattleScript_EjectPackActivate_End2); + } + } + break; } if (effect) From b5128be68b22a4fa668570c41f326003af717f82 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 8 Jan 2021 08:02:00 -0700 Subject: [PATCH 10/49] eject packer invisible before openpartymenu --- asm/macros/battle_script.inc | 4 ++++ data/battle_scripts_1.s | 1 + include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 6 ++++++ 4 files changed, 12 insertions(+) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 1de63ad16..4d60a0ac6 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1765,6 +1765,10 @@ .4byte \ptr .endm + .macro makeinvisible battler:req + various \battler, VARIOUS_MAKE_INVISIBLE + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 19f87d363..be19be263 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7895,6 +7895,7 @@ BattleScript_EjectButtonActivates:: printstring STRINGID_EJECTBUTTONACTIVATE waitmessage 0x40 removeitem BS_SCRIPTING + makeinvisible BS_SCRIPTING openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd switchoutabilities BS_SCRIPTING waitstate diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 17e02a50c..da3f43225 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -169,6 +169,7 @@ #define VARIOUS_JUMP_IF_ABSENT 101 #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TERRAIN_SEED 103 +#define VARIOUS_MAKE_INVISIBLE 104 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 372971676..f0ae80fd1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8427,6 +8427,12 @@ static void Cmd_various(void) } gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); return; + case VARIOUS_MAKE_INVISIBLE: + if (gBattleControllerExecFlags) + break; + BtlController_EmitSpriteInvisibility(0, TRUE); + MarkBattlerForControllerExec(gActiveBattler); + break; } gBattlescriptCurrInstr += 3; From 0d8f804194cbcacc9e2937f4c711b409763a6016 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 15 Jan 2021 18:11:55 -0700 Subject: [PATCH 11/49] update mental herb to gen 5 --- data/battle_scripts_1.s | 13 +++++ include/battle_scripts.h | 2 + include/constants/battle_string_ids.h | 13 ++++- include/constants/hold_effects.h | 2 +- src/battle_message.c | 16 ++++++ src/battle_util.c | 74 ++++++++++++++++++++++----- src/data/items.h | 2 +- src/data/text/item_descriptions.h | 7 +++ 8 files changed, 114 insertions(+), 15 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bff609d59..f256430ef 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7508,6 +7508,19 @@ BattleScript_BerryCureChosenStatusRet:: removeitem BS_SCRIPTING return +BattleScript_MentalHerbCureRet:: + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + printfromtable gMentalHerbCureStringIds + waitmessage 0x40 + updatestatusicon BS_SCRIPTING + removeitem BS_SCRIPTING + copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe + return + +BattleScript_MentalHerbCureEnd2:: + call BattleScript_MentalHerbCureRet + end2 + BattleScript_WhiteHerbEnd2:: call BattleScript_WhiteHerbRet end2 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 009590f3a..3b30d5bbd 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -357,5 +357,7 @@ extern const u8 BattleScript_CottonDownActivates[]; extern const u8 BattleScript_BallFetch[]; extern const u8 BattleScript_SandSpitActivates[]; extern const u8 BattleScript_PerishBodyActivates[]; +extern const u8 BattleScript_MentalHerbCureRet[]; +extern const u8 BattleScript_MentalHerbCureEnd2[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 73b91c708..9f02662e5 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -564,8 +564,11 @@ #define STRINGID_PKMNSWILLPERISHIN3TURNS 560 #define STRINGID_ABILITYRAISEDSTATDRASTICALLY 561 #define STRINGID_AURAFLAREDTOLIFE 562 +#define STRINGID_ATKGOTOVERINFATUATION 563 +#define STRINGID_TORMENTEDNOMORE 564 +#define STRINGID_HEALBLOCKEDNOMORE 565 -#define BATTLESTRINGS_COUNT 563 +#define BATTLESTRINGS_COUNT 566 //// multichoice message IDs // switch in ability message @@ -583,4 +586,12 @@ #define MULTI_SWITCHIN_COMATOSE 11 #define MULTI_SWITCHIN_SCREENCLEANER 12 +// mental herb +#define MULTI_CUREINFATUATION 0 +#define MULTI_CURETAUNT 1 +#define MULTI_CUREENCORE 2 +#define MULTI_CURETORMENT 3 +#define MULTI_CUREHEALBLOCK 4 +#define MULTI_CUREDISABLE 5 + #endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 85017cb40..9afe5ef81 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -29,7 +29,7 @@ #define HOLD_EFFECT_EXP_SHARE 25 #define HOLD_EFFECT_QUICK_CLAW 26 #define HOLD_EFFECT_HAPPINESS_UP 27 -#define HOLD_EFFECT_CURE_ATTRACT 28 +#define HOLD_EFFECT_MENTAL_HERB 28 #define HOLD_EFFECT_CHOICE_BAND 29 #define HOLD_EFFECT_FLINCH 30 #define HOLD_EFFECT_BUG_POWER 31 diff --git a/src/battle_message.c b/src/battle_message.c index 90e8c8967..ee97ffbba 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -691,9 +691,15 @@ static const u8 sText_BattlerAbilityRaisedStat[] = _("{B_SCR_ACTIVE_NAME_WITH_PR static const u8 sText_ASandstormKickedUp[] = _("A sandstorm kicked up!"); static const u8 sText_PkmnsWillPerishIn3Turns[] = _("Both Pokémon will perish\nin three turns!"); static const u8 sText_AbilityRaisedStatDrastically[] = _("{B_DEF_ABILITY} raised {B_DEF_NAME_WITH_PREFIX}'s\n{B_BUFF1} drastically!"); +static const u8 sText_AttackerGotOverInfatuation[] =_("{B_ATK_NAME_WITH_PREFIX} got over\nits infatuation!"); +static const u8 sText_TormentedNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is\ntormented no more!"); +static const u8 sText_HealBlockedNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is cured of\nits heal block!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_HEALBLOCKEDNOMORE - 12] = sText_HealBlockedNoMore, + [STRINGID_TORMENTEDNOMORE - 12] = sText_TormentedNoMore, + [STRINGID_ATKGOTOVERINFATUATION - 12] = sText_AttackerGotOverInfatuation, [STRINGID_ABILITYRAISEDSTATDRASTICALLY - 12] = sText_AbilityRaisedStatDrastically, [STRINGID_PKMNSWILLPERISHIN3TURNS - 12] = sText_PkmnsWillPerishIn3Turns, [STRINGID_ASANDSTORMKICKEDUP - 12] = sText_ASandstormKickedUp, @@ -1247,6 +1253,16 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_SCREENCLEANERENTERS - 12] = sText_ScreenCleanerActivates, }; +const u16 gMentalHerbCureStringIds[] = +{ + [MULTI_CUREINFATUATION] = STRINGID_ATKGOTOVERINFATUATION, + [MULTI_CURETAUNT] = STRINGID_BUFFERENDS, + [MULTI_CUREENCORE] = STRINGID_PKMNENCOREENDED, + [MULTI_CURETORMENT] = STRINGID_TORMENTEDNOMORE, + [MULTI_CUREHEALBLOCK] = STRINGID_HEALBLOCKEDNOMORE, + [MULTI_CUREDISABLE] = STRINGID_PKMNMOVEDISABLEDNOMORE, +}; + const u16 gTerrainStringIds[] = { STRINGID_TERRAINBECOMESMISTY, STRINGID_TERRAINBECOMESGRASSY, STRINGID_TERRAINBECOMESELECTRIC, STRINGID_TERRAINBECOMESPSYCHIC diff --git a/src/battle_util.c b/src/battle_util.c index 210f00b27..a0633f6cf 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5202,6 +5202,58 @@ static bool32 UnnerveOn(u32 battlerId, u32 itemId) return FALSE; } +static bool32 GetMentalHerbEffect(u8 battlerId) +{ + bool32 ret = FALSE; + // check infatuation + if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) + { + gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION); + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREINFATUATION; //STRINGID_TARGETGOTOVERINFATUATION + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + ret = TRUE; + } + // check taunt + if (gDisableStructs[gBattlerTarget].tauntTimer != 0) + { + gDisableStructs[gBattlerTarget].tauntTimer = gDisableStructs[gBattlerTarget].tauntTimer2 = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETAUNT; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + ret = TRUE; + } + // check encore + if (gDisableStructs[gBattlerTarget].encoreTimer != 0) + { + gDisableStructs[gActiveBattler].encoredMove = 0; + gDisableStructs[gBattlerTarget].encoreTimerStartValue = gDisableStructs[gBattlerTarget].encoreTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; //STRINGID_PKMNENCOREENDED + ret = TRUE; + } + // check torment + if (gBattleMons[battlerId].status2 & STATUS2_TORMENT) + { + gBattleMons[battlerId].status2 &= ~(STATUS2_TORMENT); + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETORMENT; + ret = TRUE; + } + // check heal block + if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK) + { + gStatuses3[battlerId] & ~(STATUS3_HEAL_BLOCK); + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREHEALBLOCK; + ret = TRUE; + } + // disable + if (gDisableStructs[gBattlerTarget].disableTimer != 0) + { + gDisableStructs[gBattlerTarget].disableTimer = gDisableStructs[gBattlerTarget].disableTimerStartValue = 0; + gDisableStructs[gBattlerTarget].disabledMove = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREDISABLE; + ret = TRUE; + } + return ret; +} + u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) { int i = 0, moveType; @@ -5658,13 +5710,12 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) effect = ITEM_STATUS_CHANGE; } break; - case HOLD_EFFECT_CURE_ATTRACT: - if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) + case HOLD_EFFECT_MENTAL_HERB: + if (GetMentalHerbEffect(battlerId)) { - gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION); - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); - BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2); - gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleScripting.savedBattler = gBattlerAttacker; + gBattlerAttacker = battlerId; + BattleScriptExecute(BattleScript_MentalHerbCureEnd2); effect = ITEM_EFFECT_OTHER; } break; @@ -5757,14 +5808,13 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) effect = ITEM_EFFECT_OTHER; } break; - case HOLD_EFFECT_CURE_ATTRACT: - if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) + case HOLD_EFFECT_MENTAL_HERB: + if (GetMentalHerbEffect(battlerId)) { - gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION); - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + gBattleScripting.savedBattler = gBattlerAttacker; + gBattlerAttacker = battlerId; BattleScriptPushCursor(); - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet; + gBattlescriptCurrInstr = BattleScript_MentalHerbCureRet; effect = ITEM_EFFECT_OTHER; } break; diff --git a/src/data/items.h b/src/data/items.h index 30beb5352..aa06dea33 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -2423,7 +2423,7 @@ const struct Item gItems[] = .name = _("MENTAL HERB"), .itemId = ITEM_MENTAL_HERB, .price = 100, - .holdEffect = HOLD_EFFECT_CURE_ATTRACT, + .holdEffect = HOLD_EFFECT_MENTAL_HERB, .description = sMentalHerbDesc, .pocket = POCKET_ITEMS, .type = 4, diff --git a/src/data/text/item_descriptions.h b/src/data/text/item_descriptions.h index 5f79efc57..d47152f7f 100644 --- a/src/data/text/item_descriptions.h +++ b/src/data/text/item_descriptions.h @@ -743,10 +743,17 @@ static const u8 sSootheBellDesc[] = _( "calms spirits and\n" "fosters friendship."); +#if B_MENTAL_HERB < GEN_5 static const u8 sMentalHerbDesc[] = _( "A hold item that\n" "snaps POKéMON out\n" "of infatuation."); +#else +static const u8 sMentalHerbDesc[] = _( + "Snaps Pokémon out\n" + "of move-binding\n" + "effects."); +#endif static const u8 sChoiceBandDesc[] = _( "Raises a move's\n" From 449c2bcc34dd5918736a45d4e17f2df27383893f Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 15 Jan 2021 18:28:10 -0700 Subject: [PATCH 12/49] add config option --- include/constants/battle_config.h | 1 + src/battle_util.c | 78 ++++++++++++++++--------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 2c179f9d5..38cf4ea1b 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -127,6 +127,7 @@ #define B_HP_BERRIES GEN_6 // In Gen4+, berries which restore hp activate immediately after hp drops to half. In gen3, the effect occurs at the end of the turn. #define B_BERRIES_INSTANT GEN_6 // In Gen4+, most berries activate on battle start/switch-in if applicable. In gen3, they only activate either at the move end or turn end. #define B_X_ITEMS_BUFF GEN_7 // In Gen7+, the X Items raise a stat by 2 stages instead of 1. +#define B_MENTAL_HERB GEN_5 // In Gen5+, the Mental Herb cures Infatuation, Taunt, Encore, Torment, Heal Block, and Disable // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/src/battle_util.c b/src/battle_util.c index a0633f6cf..b095ca0fb 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5213,44 +5213,46 @@ static bool32 GetMentalHerbEffect(u8 battlerId) StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); ret = TRUE; } - // check taunt - if (gDisableStructs[gBattlerTarget].tauntTimer != 0) - { - gDisableStructs[gBattlerTarget].tauntTimer = gDisableStructs[gBattlerTarget].tauntTimer2 = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - ret = TRUE; - } - // check encore - if (gDisableStructs[gBattlerTarget].encoreTimer != 0) - { - gDisableStructs[gActiveBattler].encoredMove = 0; - gDisableStructs[gBattlerTarget].encoreTimerStartValue = gDisableStructs[gBattlerTarget].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; //STRINGID_PKMNENCOREENDED - ret = TRUE; - } - // check torment - if (gBattleMons[battlerId].status2 & STATUS2_TORMENT) - { - gBattleMons[battlerId].status2 &= ~(STATUS2_TORMENT); - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETORMENT; - ret = TRUE; - } - // check heal block - if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK) - { - gStatuses3[battlerId] & ~(STATUS3_HEAL_BLOCK); - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREHEALBLOCK; - ret = TRUE; - } - // disable - if (gDisableStructs[gBattlerTarget].disableTimer != 0) - { - gDisableStructs[gBattlerTarget].disableTimer = gDisableStructs[gBattlerTarget].disableTimerStartValue = 0; - gDisableStructs[gBattlerTarget].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREDISABLE; - ret = TRUE; - } + #if B_MENTAL_HERB >= GEN_5 + // check taunt + if (gDisableStructs[gBattlerTarget].tauntTimer != 0) + { + gDisableStructs[gBattlerTarget].tauntTimer = gDisableStructs[gBattlerTarget].tauntTimer2 = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETAUNT; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + ret = TRUE; + } + // check encore + if (gDisableStructs[gBattlerTarget].encoreTimer != 0) + { + gDisableStructs[gActiveBattler].encoredMove = 0; + gDisableStructs[gBattlerTarget].encoreTimerStartValue = gDisableStructs[gBattlerTarget].encoreTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; //STRINGID_PKMNENCOREENDED + ret = TRUE; + } + // check torment + if (gBattleMons[battlerId].status2 & STATUS2_TORMENT) + { + gBattleMons[battlerId].status2 &= ~(STATUS2_TORMENT); + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETORMENT; + ret = TRUE; + } + // check heal block + if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK) + { + gStatuses3[battlerId] & ~(STATUS3_HEAL_BLOCK); + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREHEALBLOCK; + ret = TRUE; + } + // disable + if (gDisableStructs[gBattlerTarget].disableTimer != 0) + { + gDisableStructs[gBattlerTarget].disableTimer = gDisableStructs[gBattlerTarget].disableTimerStartValue = 0; + gDisableStructs[gBattlerTarget].disabledMove = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREDISABLE; + ret = TRUE; + } + #endif return ret; } From 9e29d303ec3d10f3ab63494e6e5e03b9ac30e45d Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 16 Jan 2021 11:40:02 -0700 Subject: [PATCH 13/49] electric and misty terrain preventions --- data/battle_scripts_1.s | 21 ++++++++ include/battle_util.h | 5 ++ src/battle_script_commands.c | 48 +++-------------- src/battle_util.c | 101 ++++++++++++++++++++++++++--------- 4 files changed, 111 insertions(+), 64 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bff609d59..94dd32412 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2134,6 +2134,8 @@ BattleScript_EffectSleep:: jumpifleafguard BattleScript_LeafGuardProtects jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation @@ -2141,6 +2143,20 @@ BattleScript_EffectSleep:: setmoveeffect MOVE_EFFECT_SLEEP seteffectprimary goto BattleScript_MoveEnd + +BattleScript_ElectricTerrainPrevents: + pause 0x20 + printstring STRINGID_ELECTRICTERRAINPREVENTS + waitmessage 0x40 + orhalfword gMoveResultFlags, MOVE_RESULT_FAILED + goto BattleScript_MoveEnd + +BattleScript_MistyTerrainPrevents: + pause 0x20 + printstring STRINGID_MISTYTERRAINPREVENTS + waitmessage 0x40 + orhalfword gMoveResultFlags, MOVE_RESULT_FAILED + goto BattleScript_MoveEnd BattleScript_FlowerVeilProtectsRet:: pause 0x20 @@ -2654,6 +2670,7 @@ BattleScript_EffectToxic:: jumpifsubstituteblocks BattleScript_ButItFailed jumpifstatus BS_TARGET, STATUS1_POISON | STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected @@ -2704,6 +2721,7 @@ BattleScript_EffectRest:: attackcanceler attackstring ppreduce + jumpifword CMP_COMMON_BITS, gFieldStatuses, (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN), BattleScript_ButItFailed jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_RestIsAlreadyAsleep jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_RestIsAlreadyAsleep jumpifcantmakeasleep BattleScript_RestCantSleep @@ -2994,6 +3012,7 @@ BattleScript_EffectPoison:: jumpifstatus BS_TARGET, STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation @@ -3019,6 +3038,7 @@ BattleScript_EffectParalyze: jumpifstatus BS_TARGET, STATUS1_PARALYSIS, BattleScript_AlreadyParalyzed tryparalyzetype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected bichalfword gMoveResultFlags, MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE @@ -4317,6 +4337,7 @@ BattleScript_EffectWillOWisp:: jumpifleafguard BattleScript_LeafGuardProtects jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation diff --git a/include/battle_util.h b/include/battle_util.h index f7699fced..615af7dc5 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -130,5 +130,10 @@ void ClearIllusionMon(u32 battlerId); bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId); bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); u8 GetBattleMoveSplit(u32 moveId); +bool32 CanSleep(u8 battlerId); +bool32 CanBePoisoned(u8 battlerId); +bool32 CanBeBurned(u8 battlerId); +bool32 CanBeParalyzed(u8 battlerId); +bool32 CanBeFrozen(u8 battlerId); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6c5f37a7d..251f1e335 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2386,8 +2386,7 @@ void SetMoveEffect(bool32 primary, u32 certain) { s32 i, byTwo, affectsUser = 0; bool32 statusChanged = FALSE; - bool32 noSunCanFreeze = TRUE; - + switch (gBattleScripting.moveEffect) // Set move effects which happen later on { case MOVE_EFFECT_KNOCK_OFF: @@ -2448,15 +2447,9 @@ void SetMoveEffect(bool32 primary, u32 certain) else gActiveBattler = gBattlersCount; - if (gBattleMons[gEffectBattler].status1) - break; if (gActiveBattler != gBattlersCount) break; - if (GetBattlerAbility(gEffectBattler) == ABILITY_VITAL_SPIRIT - || GetBattlerAbility(gEffectBattler) == ABILITY_INSOMNIA - || GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE - || IsAbilityOnSide(gEffectBattler, ABILITY_SWEET_VEIL) - || IsAbilityStatusProtected(gEffectBattler)) + if (!CanSleep(gEffectBattler)) break; CancelMultiTurnMoves(gEffectBattler); @@ -2495,11 +2488,7 @@ void SetMoveEffect(bool32 primary, u32 certain) } if (!CanPoisonType(gBattleScripting.battler, gEffectBattler)) break; - if (gBattleMons[gEffectBattler].status1) - break; - if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY - || GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE - || IsAbilityStatusProtected(gEffectBattler)) + if (!CanBePoisoned(gEffectBattler)) break; statusChanged = TRUE; @@ -2534,29 +2523,14 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattleCommunication[MULTISTRING_CHOOSER] = 2; RESET_RETURN } - if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE)) - break; - if (GetBattlerAbility(gEffectBattler) == ABILITY_WATER_VEIL - || GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE - || IsAbilityStatusProtected(gEffectBattler)) - break; - if (gBattleMons[gEffectBattler].status1) + + if (!CanBeBurned(gEffectBattler)) break; statusChanged = TRUE; break; case STATUS1_FREEZE: - if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY) - noSunCanFreeze = FALSE; - if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ICE)) - break; - if (gBattleMons[gEffectBattler].status1) - break; - if (noSunCanFreeze == 0) - break; - if (GetBattlerAbility(gEffectBattler) == ABILITY_MAGMA_ARMOR - || GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE - || IsAbilityStatusProtected(gEffectBattler)) + if (!CanBeFrozen(gEffectBattler)) break; CancelMultiTurnMoves(gEffectBattler); @@ -2599,11 +2573,7 @@ void SetMoveEffect(bool32 primary, u32 certain) } if (!CanParalyzeType(gBattleScripting.battler, gEffectBattler)) break; - if (GetBattlerAbility(gEffectBattler) == ABILITY_LIMBER - || GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE - || IsAbilityStatusProtected(gEffectBattler)) - break; - if (gBattleMons[gEffectBattler].status1) + if (!CanBeParalyzed(gEffectBattler)) break; statusChanged = TRUE; @@ -2642,9 +2612,7 @@ void SetMoveEffect(bool32 primary, u32 certain) break; if (CanPoisonType(gBattleScripting.battler, gEffectBattler)) { - if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY - || GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE - || IsAbilityStatusProtected(gEffectBattler)) + if (!CanBePoisoned(gEffectBattler)) break; // It's redundant, because at this point we know the status1 value is 0. diff --git a/src/battle_util.c b/src/battle_util.c index 210f00b27..085d63ff9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2500,7 +2500,8 @@ u8 DoBattlerEndTurnEffects(void) if (!(gStatuses3[gActiveBattler] & STATUS3_YAWN) && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY) && gBattleMons[gActiveBattler].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gActiveBattler].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler) - && !IsLeafGuardProtected(gActiveBattler)) + && !IsLeafGuardProtected(gActiveBattler) + && !(gFieldStatuses & (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN))) { CancelMultiTurnMoves(gActiveBattler); gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2; @@ -4523,10 +4524,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && GetBattlerAbility(gBattlerAttacker) != ABILITY_INSOMNIA - && GetBattlerAbility(gBattlerAttacker) != ABILITY_VITAL_SPIRIT - && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) - && !IsAbilityStatusProtected(gBattlerAttacker) + && CanSleep(gBattlerAttacker) && IsMoveMakingContact(move, gBattlerAttacker) && (Random() % 3) == 0) { @@ -4545,11 +4543,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON) - && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_STEEL) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_IMMUNITY - && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) - && !IsAbilityStatusProtected(gBattlerAttacker) + && CanBePoisoned(gBattlerAttacker) && IsMoveMakingContact(move, gBattlerAttacker) && (Random() % 3) == 0) { @@ -4567,10 +4561,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && CanParalyzeType(gBattlerTarget, gBattlerAttacker) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_LIMBER - && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) - && !IsAbilityStatusProtected(gBattlerAttacker) + && CanBeParalyzed(gBattlerAttacker) && IsMoveMakingContact(move, gBattlerAttacker) && (Random() % 3) == 0) { @@ -4587,10 +4578,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) && TARGET_TURN_DAMAGED - && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_WATER_VEIL - && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) - && !IsAbilityStatusProtected(gBattlerAttacker) + && CanBeBurned(gBattlerAttacker) && (Random() % 3) == 0) { gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN; @@ -4698,11 +4686,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerTarget].hp != 0 && !gProtectStructs[gBattlerTarget].confusionSelfDmg - && !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_POISON) - && !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_STEEL) - && GetBattlerAbility(gBattlerTarget) != ABILITY_IMMUNITY - && !(gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) - && !IsAbilityStatusProtected(gBattlerTarget) + && CanBePoisoned(gBattlerTarget) && IsMoveMakingContact(move, gBattlerAttacker) && (Random() % 3) == 0) { @@ -5075,6 +5059,75 @@ enum ITEM_STATS_CHANGE, // 5 }; +bool32 CanSleep(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if (ability == ABILITY_INSOMNIA + || ability == ABILITY_VITAL_SPIRIT + || ability == ABILITY_COMATOSE + || gBattleMons[battlerId].status1 & STATUS1_ANY + || IsAbilityOnSide(battlerId, ABILITY_SWEET_VEIL) + || IsAbilityStatusProtected(battlerId) + || gFieldStatuses & (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanBePoisoned(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON) + || IS_BATTLER_OF_TYPE(battlerId, TYPE_STEEL) + || gBattleMons[battlerId].status1 & STATUS1_ANY + || ability == ABILITY_IMMUNITY + || ability == ABILITY_COMATOSE + || gBattleMons[battlerId].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battlerId) + || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return FALSE; + return TRUE; +} + +bool32 CanBeBurned(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if (IS_BATTLER_OF_TYPE(battlerId, TYPE_FIRE) + || gBattleMons[battlerId].status1 & STATUS1_ANY + || ability == ABILITY_WATER_VEIL + || ability == ABILITY_COMATOSE + || IsAbilityStatusProtected(battlerId) + || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return FALSE; + return TRUE; +} + +bool32 CanBeParalyzed(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if ((B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battlerId, TYPE_ELECTRIC)) + || ability == ABILITY_LIMBER + || ability == ABILITY_COMATOSE + || gBattleMons[battlerId].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battlerId) + || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return FALSE; + return TRUE; +} + +bool32 CanBeFrozen(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if (IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE) + || (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY) + || ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE + || gBattleMons[battlerId].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battlerId) + || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return FALSE; + return TRUE; +} + // second argument is 1/X of current hp compared to max hp static bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) { @@ -6207,7 +6260,7 @@ u8 IsMonDisobedient(void) obedienceLevel = gBattleMons[gBattlerAttacker].level - obedienceLevel; calc = (Random() & 255); - if (calc < obedienceLevel && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) && gBattleMons[gBattlerAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBattlerAttacker].ability != ABILITY_INSOMNIA) + if (calc < obedienceLevel && CanSleep(gBattlerAttacker)) { // try putting asleep int i; From 4a5a3ea6af004cc3431073eccd1bcc9a10241a86 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 16 Jan 2021 11:47:29 -0700 Subject: [PATCH 14/49] add safeguard checks --- src/battle_util.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 085d63ff9..ebaaf386d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5065,6 +5065,7 @@ bool32 CanSleep(u8 battlerId) if (ability == ABILITY_INSOMNIA || ability == ABILITY_VITAL_SPIRIT || ability == ABILITY_COMATOSE + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD || gBattleMons[battlerId].status1 & STATUS1_ANY || IsAbilityOnSide(battlerId, ABILITY_SWEET_VEIL) || IsAbilityStatusProtected(battlerId) @@ -5078,6 +5079,7 @@ bool32 CanBePoisoned(u8 battlerId) u16 ability = GetBattlerAbility(battlerId); if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON) || IS_BATTLER_OF_TYPE(battlerId, TYPE_STEEL) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD || gBattleMons[battlerId].status1 & STATUS1_ANY || ability == ABILITY_IMMUNITY || ability == ABILITY_COMATOSE @@ -5092,6 +5094,7 @@ bool32 CanBeBurned(u8 battlerId) { u16 ability = GetBattlerAbility(battlerId); if (IS_BATTLER_OF_TYPE(battlerId, TYPE_FIRE) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD || gBattleMons[battlerId].status1 & STATUS1_ANY || ability == ABILITY_WATER_VEIL || ability == ABILITY_COMATOSE @@ -5105,6 +5108,7 @@ bool32 CanBeParalyzed(u8 battlerId) { u16 ability = GetBattlerAbility(battlerId); if ((B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battlerId, TYPE_ELECTRIC)) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD || ability == ABILITY_LIMBER || ability == ABILITY_COMATOSE || gBattleMons[battlerId].status1 & STATUS1_ANY @@ -5119,6 +5123,7 @@ bool32 CanBeFrozen(u8 battlerId) u16 ability = GetBattlerAbility(battlerId); if (IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE) || (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD || ability == ABILITY_MAGMA_ARMOR || ability == ABILITY_COMATOSE || gBattleMons[battlerId].status1 & STATUS1_ANY From 10b1d33d13c0c95d4edc5fb904e4450622ee32b6 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 16 Jan 2021 12:05:51 -0700 Subject: [PATCH 15/49] handle battler being affected by terrain --- asm/macros/battle_script.inc | 6 ++++++ data/battle_scripts_1.s | 14 +++++++------- include/battle_util.h | 1 + include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 9 +++++++++ src/battle_util.c | 20 +++++++++++++++----- 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index b1c42e491..ed7ecb4e0 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1765,6 +1765,12 @@ .4byte \ptr .endm + .macro jumpifterrainaffected battler:req, terrainFlags:req, ptr:req + various \battler, VARIOUS_JUMP_IF_TERRAIN_AFFECTED + .4byte \terrainFlags + .4byte \ptr + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 94dd32412..fd8a96f35 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2134,8 +2134,8 @@ BattleScript_EffectSleep:: jumpifleafguard BattleScript_LeafGuardProtects jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed - jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents - jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation @@ -2670,7 +2670,7 @@ BattleScript_EffectToxic:: jumpifsubstituteblocks BattleScript_ButItFailed jumpifstatus BS_TARGET, STATUS1_POISON | STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed - jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected @@ -2721,7 +2721,7 @@ BattleScript_EffectRest:: attackcanceler attackstring ppreduce - jumpifword CMP_COMMON_BITS, gFieldStatuses, (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN), BattleScript_ButItFailed + jumpifterrainaffected BS_ATTACKER, (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN), BattleScript_ButItFailed jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_RestIsAlreadyAsleep jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_RestIsAlreadyAsleep jumpifcantmakeasleep BattleScript_RestCantSleep @@ -3012,7 +3012,7 @@ BattleScript_EffectPoison:: jumpifstatus BS_TARGET, STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed - jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation @@ -3038,7 +3038,7 @@ BattleScript_EffectParalyze: jumpifstatus BS_TARGET, STATUS1_PARALYSIS, BattleScript_AlreadyParalyzed tryparalyzetype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed - jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected bichalfword gMoveResultFlags, MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE @@ -4337,7 +4337,7 @@ BattleScript_EffectWillOWisp:: jumpifleafguard BattleScript_LeafGuardProtects jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed - jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation diff --git a/include/battle_util.h b/include/battle_util.h index 615af7dc5..a48e037c1 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -135,5 +135,6 @@ bool32 CanBePoisoned(u8 battlerId); bool32 CanBeBurned(u8 battlerId); bool32 CanBeParalyzed(u8 battlerId); bool32 CanBeFrozen(u8 battlerId); +bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 424009d20..01251e793 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -168,6 +168,7 @@ #define VARIOUS_JUMP_IF_ABSENT 101 #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 +#define VARIOUS_JUMP_IF_TERRAIN_AFFECTED 104 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 251f1e335..43acc2968 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8301,6 +8301,15 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe) } return; + case VARIOUS_JUMP_IF_TERRAIN_AFFECTED: + { + u32 flags = T1_READ_32(gBattlescriptCurrInstr + 3); + if (IsBattlerTerrainAffected(gActiveBattler, flags)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7); + else + gBattlescriptCurrInstr += 11; + } + return; } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index ebaaf386d..32264ced3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5059,6 +5059,16 @@ enum ITEM_STATS_CHANGE, // 5 }; +bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag) +{ + if (!(gFieldStatuses & terrainFlag)) + return FALSE; + else if (gStatuses3[battlerId] & STATUS3_SEMI_INVULNERABLE) + return FALSE; + + return IsBattlerGrounded(battlerId); +} + bool32 CanSleep(u8 battlerId) { u16 ability = GetBattlerAbility(battlerId); @@ -5069,7 +5079,7 @@ bool32 CanSleep(u8 battlerId) || gBattleMons[battlerId].status1 & STATUS1_ANY || IsAbilityOnSide(battlerId, ABILITY_SWEET_VEIL) || IsAbilityStatusProtected(battlerId) - || gFieldStatuses & (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN)) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN)) return FALSE; return TRUE; } @@ -5085,7 +5095,7 @@ bool32 CanBePoisoned(u8 battlerId) || ability == ABILITY_COMATOSE || gBattleMons[battlerId].status1 & STATUS1_ANY || IsAbilityStatusProtected(battlerId) - || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) return FALSE; return TRUE; } @@ -5099,7 +5109,7 @@ bool32 CanBeBurned(u8 battlerId) || ability == ABILITY_WATER_VEIL || ability == ABILITY_COMATOSE || IsAbilityStatusProtected(battlerId) - || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) return FALSE; return TRUE; } @@ -5113,7 +5123,7 @@ bool32 CanBeParalyzed(u8 battlerId) || ability == ABILITY_COMATOSE || gBattleMons[battlerId].status1 & STATUS1_ANY || IsAbilityStatusProtected(battlerId) - || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) return FALSE; return TRUE; } @@ -5128,7 +5138,7 @@ bool32 CanBeFrozen(u8 battlerId) || ability == ABILITY_COMATOSE || gBattleMons[battlerId].status1 & STATUS1_ANY || IsAbilityStatusProtected(battlerId) - || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) return FALSE; return TRUE; } From c2dfc571b2d488314f97507bde63bd620bc47aba Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 16 Jan 2021 12:21:04 -0700 Subject: [PATCH 16/49] misty terrain blocks confusion --- data/battle_scripts_1.s | 1 + include/battle_util.h | 1 + src/battle_script_commands.c | 3 +-- src/battle_util.c | 9 +++++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index fd8a96f35..3eb883a3d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2894,6 +2894,7 @@ BattleScript_EffectConfuse: jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_OwnTempoPrevents jumpifsubstituteblocks BattleScript_ButItFailed jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_AlreadyConfused + jumpifterrainaffected BS_TARGET, FIELD_STATUS_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation diff --git a/include/battle_util.h b/include/battle_util.h index a48e037c1..c9fa1da61 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -135,6 +135,7 @@ bool32 CanBePoisoned(u8 battlerId); bool32 CanBeBurned(u8 battlerId); bool32 CanBeParalyzed(u8 battlerId); bool32 CanBeFrozen(u8 battlerId); +bool32 CanBeConfused(u8 battlerId); bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 43acc2968..1e24b0d75 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2684,8 +2684,7 @@ void SetMoveEffect(bool32 primary, u32 certain) switch (gBattleScripting.moveEffect) { case MOVE_EFFECT_CONFUSION: - if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO - || gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION) + if (!CanBeConfused(gEffectBattler)) { gBattlescriptCurrInstr++; } diff --git a/src/battle_util.c b/src/battle_util.c index 32264ced3..8a4428e51 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5143,6 +5143,15 @@ bool32 CanBeFrozen(u8 battlerId) return TRUE; } +bool32 CanBeConfused(u8 battlerId) +{ + if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO + || gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + // second argument is 1/X of current hp compared to max hp static bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) { From 0dabbc2d315ed8d4aa5239126aa3209f8b9f06d8 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 16 Jan 2021 12:39:44 -0700 Subject: [PATCH 17/49] fix misty terrain check --- data/battle_scripts_1.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3eb883a3d..18413b1fb 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2894,7 +2894,7 @@ BattleScript_EffectConfuse: jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_OwnTempoPrevents jumpifsubstituteblocks BattleScript_ButItFailed jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_AlreadyConfused - jumpifterrainaffected BS_TARGET, FIELD_STATUS_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifsafeguard BattleScript_SafeguardProtected attackanimation From 492b5718e780628c8dadeeaddec0412d7131aae5 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:02:21 -0600 Subject: [PATCH 18/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index b095ca0fb..f62228c46 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5205,7 +5205,7 @@ static bool32 UnnerveOn(u32 battlerId, u32 itemId) static bool32 GetMentalHerbEffect(u8 battlerId) { bool32 ret = FALSE; - // check infatuation + // Check infatuation if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) { gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION); From d0f5528abb15b8580a5b7aea68b11c20f42ef1da Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:02:34 -0600 Subject: [PATCH 19/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index f62228c46..bc3418a91 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5209,7 +5209,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) { gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION); - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREINFATUATION; //STRINGID_TARGETGOTOVERINFATUATION + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREINFATUATION; // STRINGID_TARGETGOTOVERINFATUATION StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); ret = TRUE; } From 31cdf043ccfb4f8a7ad2a96ec05dd852c37db3d6 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:02:41 -0600 Subject: [PATCH 20/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index bc3418a91..aecdb445d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5214,7 +5214,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) ret = TRUE; } #if B_MENTAL_HERB >= GEN_5 - // check taunt + // Check taunt if (gDisableStructs[gBattlerTarget].tauntTimer != 0) { gDisableStructs[gBattlerTarget].tauntTimer = gDisableStructs[gBattlerTarget].tauntTimer2 = 0; From 97428b6e10668e2f1e2b6879f416574c9518e6cc Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:02:46 -0600 Subject: [PATCH 21/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index aecdb445d..da9cae886 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5227,7 +5227,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) { gDisableStructs[gActiveBattler].encoredMove = 0; gDisableStructs[gBattlerTarget].encoreTimerStartValue = gDisableStructs[gBattlerTarget].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; //STRINGID_PKMNENCOREENDED + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; // STRINGID_PKMNENCOREENDED ret = TRUE; } // check torment From d7c7f808b8b8073fe09bdcb889f006a6935f3dcd Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:02:51 -0600 Subject: [PATCH 22/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index da9cae886..e71db412e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5222,7 +5222,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); ret = TRUE; } - // check encore + // Check encore if (gDisableStructs[gBattlerTarget].encoreTimer != 0) { gDisableStructs[gActiveBattler].encoredMove = 0; From 332286ce0390e490518f0fcba4ffc345f83d719a Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:02:56 -0600 Subject: [PATCH 23/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index e71db412e..f56a37a36 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5230,7 +5230,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; // STRINGID_PKMNENCOREENDED ret = TRUE; } - // check torment + // Check torment if (gBattleMons[battlerId].status2 & STATUS2_TORMENT) { gBattleMons[battlerId].status2 &= ~(STATUS2_TORMENT); From a8c40a8d6f60640b12d9216bc7c8edf8110587ad Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:03:00 -0600 Subject: [PATCH 24/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index f56a37a36..f44146f11 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5237,7 +5237,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETORMENT; ret = TRUE; } - // check heal block + // Check heal block if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK) { gStatuses3[battlerId] & ~(STATUS3_HEAL_BLOCK); From 856781ce56fbc852cb08587a0108f01d5c5b3fe5 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 29 Mar 2021 08:03:05 -0600 Subject: [PATCH 25/49] Update src/battle_util.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index f44146f11..661f7068e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5244,7 +5244,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREHEALBLOCK; ret = TRUE; } - // disable + // Check disable if (gDisableStructs[gBattlerTarget].disableTimer != 0) { gDisableStructs[gBattlerTarget].disableTimer = gDisableStructs[gBattlerTarget].disableTimerStartValue = 0; From f050168c55f21bfd44103afffc264b2240a19285 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 12 Aug 2021 13:41:18 -0600 Subject: [PATCH 26/49] misty terrain blocks toxic spikes --- src/battle_script_commands.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 94d53f991..ac9dfb36d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5867,7 +5867,8 @@ static void Cmd_switchineffects(void) } else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES) - && IsBattlerGrounded(gActiveBattler)) + && IsBattlerGrounded(gActiveBattler) + && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) { gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_TOXIC_SPIKES_DAMAGED; if (IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_POISON)) // Absorb the toxic spikes. From 5e250853c6efcee5021550e97cfd4fafb5a17f6f Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 12 Aug 2021 13:45:50 -0600 Subject: [PATCH 27/49] misty terrain blocks toxic spikes --- src/battle_script_commands.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ac9dfb36d..f650306d8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5867,8 +5867,7 @@ static void Cmd_switchineffects(void) } else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES) - && IsBattlerGrounded(gActiveBattler) - && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) + && IsBattlerGrounded(gActiveBattler)) { gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_TOXIC_SPIKES_DAMAGED; if (IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_POISON)) // Absorb the toxic spikes. @@ -5884,7 +5883,8 @@ static void Cmd_switchineffects(void) if (!(gBattleMons[gActiveBattler].status1 & STATUS1_ANY) && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL) && GetBattlerAbility(gActiveBattler) != ABILITY_IMMUNITY - && !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD)) + && !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD) + && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) { if (gSideTimers[GetBattlerSide(gActiveBattler)].toxicSpikesAmount >= 2) gBattleMons[gActiveBattler].status1 |= STATUS1_TOXIC_POISON; From 0bbbd1e7a9c91614c2d073a1585f67ccf83bf83a Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 12 Aug 2021 14:08:41 -0600 Subject: [PATCH 28/49] fix electric/misty yawn/rest interactions --- data/battle_scripts_1.s | 10 +++++++++- include/battle_scripts.h | 1 + src/battle_util.c | 24 ++++++++++++++++++------ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 07d0c9143..39fbdab17 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2154,6 +2154,12 @@ BattleScript_EffectSleep:: seteffectprimary goto BattleScript_MoveEnd +BattleScript_TerrainPreventsEnd2:: + pause 0x20 + printfromtable gTerrainPreventsStringIds + waitmessage 0x40 + end2 + BattleScript_ElectricTerrainPrevents: pause 0x20 printstring STRINGID_ELECTRICTERRAINPREVENTS @@ -2733,11 +2739,11 @@ BattleScript_EffectRest:: attackcanceler attackstring ppreduce - jumpifterrainaffected BS_ATTACKER, (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN), BattleScript_ButItFailed jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_RestIsAlreadyAsleep jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_RestIsAlreadyAsleep jumpifcantmakeasleep BattleScript_RestCantSleep trysetrest BattleScript_AlreadyAtFullHp + jumpifterrainaffected BS_ATTACKER, (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN), BattleScript_ButItFailed pause B_WAIT_TIME_SHORT printfromtable gRestUsedStringIds waitmessage B_WAIT_TIME_LONG @@ -4630,6 +4636,8 @@ BattleScript_EffectYawn:: jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_PrintBankAbilityMadeIneffective jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_PrintBankAbilityMadeIneffective jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_PrintBankAbilityMadeIneffective + jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents + jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents jumpifflowerveil BattleScript_FlowerVeilProtects jumpifleafguard BattleScript_LeafGuardProtects jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects diff --git a/include/battle_scripts.h b/include/battle_scripts.h index f0712fc43..e48e4f12b 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -369,5 +369,6 @@ extern const u8 BattleScript_JabocaRowapBerryActivates[]; extern const u8 BattleScript_NotAffectedAbilityPopUp[]; extern const u8 BattleScript_BattlerShookOffTaunt[]; extern const u8 BattleScript_BattlerGotOverItsInfatuation[]; +extern const u8 BattleScript_TerrainPreventsEnd2[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/src/battle_util.c b/src/battle_util.c index b7c6424c8..9900990e8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2724,15 +2724,27 @@ u8 DoBattlerEndTurnEffects(void) if (!(gStatuses3[gActiveBattler] & STATUS3_YAWN) && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY) && gBattleMons[gActiveBattler].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gActiveBattler].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler) - && !IsLeafGuardProtected(gActiveBattler) - && !(gFieldStatuses & (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN))) + && !IsLeafGuardProtected(gActiveBattler)) { CancelMultiTurnMoves(gActiveBattler); - gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2; - BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1); - MarkBattlerForControllerExec(gActiveBattler); gEffectBattler = gActiveBattler; - BattleScriptExecute(BattleScript_YawnMakesAsleep); + if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + BattleScriptExecute(BattleScript_TerrainPreventsEnd2); + } + else if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_MISTY_TERRAIN)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + BattleScriptExecute(BattleScript_TerrainPreventsEnd2); + } + else + { + gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1); + MarkBattlerForControllerExec(gActiveBattler); + BattleScriptExecute(BattleScript_YawnMakesAsleep); + } effect++; } } From 85f98300ff94b78de776b78f421f71dc7d4ff185 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 12 Aug 2021 14:14:51 -0600 Subject: [PATCH 29/49] use B_WAIT_TIME_SHORT and B_WAIT_TIME_LONG --- data/battle_scripts_1.s | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 39fbdab17..166957c02 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2155,22 +2155,22 @@ BattleScript_EffectSleep:: goto BattleScript_MoveEnd BattleScript_TerrainPreventsEnd2:: - pause 0x20 + pause B_WAIT_TIME_SHORT printfromtable gTerrainPreventsStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG end2 BattleScript_ElectricTerrainPrevents: - pause 0x20 + pause B_WAIT_TIME_SHORT printstring STRINGID_ELECTRICTERRAINPREVENTS - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG orhalfword gMoveResultFlags, MOVE_RESULT_FAILED goto BattleScript_MoveEnd BattleScript_MistyTerrainPrevents: - pause 0x20 + pause B_WAIT_TIME_SHORT printstring STRINGID_MISTYTERRAINPREVENTS - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG orhalfword gMoveResultFlags, MOVE_RESULT_FAILED goto BattleScript_MoveEnd From 6ce122744767ac97694997aa9c90472d977cbb60 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 11:05:11 -0400 Subject: [PATCH 30/49] fix throat spray bugs. move shell bell, throat spray etc to life orb moveend case --- data/battle_scripts_1.s | 8 ++- include/battle_util.h | 3 +- include/constants/battle_script_commands.h | 6 +-- src/battle_script_commands.c | 22 ++------- src/battle_util.c | 57 ++++++++++++++++------ 5 files changed, 57 insertions(+), 39 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 0d3eb9d50..762b9d3e5 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1868,7 +1868,7 @@ BattleScript_RoomServiceLoop: jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_ROOM_SERVICE, BattleScript_RoomServiceLoop_NextBattler jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_RoomServiceLoop_NextBattler setstatchanger STAT_SPEED, 1, TRUE - statbuffchange 0, BattleScript_RoomServiceLoop_NextBattler + statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_RoomServiceLoop_NextBattler jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_RoomServiceLoop_NextBattler playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL waitanimation @@ -2193,18 +2193,21 @@ BattleScript_AlreadyAsleep:: pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYASLEEP waitmessage B_WAIT_TIME_LONG + orhalfword gMoveResultFlags, MOVE_RESULT_FAILED goto BattleScript_MoveEnd BattleScript_WasntAffected:: pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNWASNTAFFECTED waitmessage B_WAIT_TIME_LONG + orhalfword gMoveResultFlags, MOVE_RESULT_FAILED goto BattleScript_MoveEnd BattleScript_CantMakeAsleep:: pause B_WAIT_TIME_SHORT printfromtable gUproarAwakeStringIds waitmessage B_WAIT_TIME_LONG + orhalfword gMoveResultFlags, MOVE_RESULT_FAILED goto BattleScript_MoveEnd BattleScript_EffectPoisonHit: @@ -5643,7 +5646,7 @@ BattleScript_TargetItemStatRaiseRemoveItemRet: BattleScript_AttackerItemStatRaise:: copybyte sBATTLER, gBattlerAttacker - statbuffchange 0, BattleScript_AttackerItemStatRaiseRet + statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_AttackerItemStatRaiseRet jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_AttackerItemStatRaiseRet playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL waitanimation @@ -7120,6 +7123,7 @@ BattleScript_SoundproofProtected:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXBLOCKSY waitmessage B_WAIT_TIME_LONG + orhalfword gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE goto BattleScript_MoveEnd BattleScript_DazzlingProtected:: diff --git a/include/battle_util.h b/include/battle_util.h index 1948161b4..f72f85d5c 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -28,9 +28,10 @@ #define ITEMEFFECT_ON_SWITCH_IN 0x0 #define ITEMEFFECT_MOVE_END 0x3 -#define ITEMEFFECT_KINGSROCK_SHELLBELL 0x4 +#define ITEMEFFECT_KINGSROCK 0x4 #define ITEMEFFECT_TARGET 0x5 #define ITEMEFFECT_ORBS 0x6 +#define ITEMEFFECT_LIFEORB_SHELLBELL 0x7 #define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK))) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 766af072c..f35a37766 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -231,15 +231,15 @@ #define MOVEEND_ITEM_EFFECTS_TARGET 13 #define MOVEEND_MOVE_EFFECTS2 14 #define MOVEEND_ITEM_EFFECTS_ALL 15 -#define MOVEEND_KINGSROCK_SHELLBELL 16 +#define MOVEEND_KINGSROCK 16 // these item effects will occur each strike of a multi-hit move #define MOVEEND_SUBSTITUTE 17 #define MOVEEND_UPDATE_LAST_MOVES 18 #define MOVEEND_MIRROR_MOVE 19 -#define MOVEEND_NEXT_TARGET 20 +#define MOVEEND_NEXT_TARGET 20 // everything up until here is handled for each strike of a multi-hit move #define MOVEEND_EJECT_BUTTON 21 #define MOVEEND_RED_CARD 22 #define MOVEEND_EJECT_PACK 23 -#define MOVEEND_LIFE_ORB 24 +#define MOVEEND_LIFEORB_SHELLBELL 24 // includes shell bell, throat spray, etc #define MOVEEND_PICKPOCKET 25 #define MOVEEND_DANCER 26 #define MOVEEND_EMERGENCY_EXIT 27 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3344573fb..a53a6b0e0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4934,8 +4934,9 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK_SHELLBELL: // king's rock and shell bell - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK_SHELLBELL, 0, FALSE)) + case MOVEEND_KINGSROCK: // king's rock and shell bell + // these effects will occur at each hit in a multi-strike move + if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -5199,22 +5200,9 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_LIFE_ORB: - // TODO shell bell goes here too - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIFE_ORB - && IsBattlerAlive(gBattlerAttacker) - && !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD - && gSpecialStatuses[gBattlerAttacker].damagedMons) - { - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 10; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; + case MOVEEND_LIFEORB_SHELLBELL: + if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE)) effect = TRUE; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_ItemHurtRet; - gLastUsedItem = gBattleMons[gBattlerAttacker].item; - } gBattleScripting.moveendState++; break; case MOVEEND_PICKPOCKET: diff --git a/src/battle_util.c b/src/battle_util.c index 0173ca49f..5f5f2e19b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6354,7 +6354,8 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } } break; - case ITEMEFFECT_KINGSROCK_SHELLBELL: + case ITEMEFFECT_KINGSROCK: + // occur on each hit of a multi-strike move switch (atkHoldEffect) { case HOLD_EFFECT_FLINCH: @@ -6371,6 +6372,25 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptPop(); } break; + case HOLD_EFFECT_BLUNDER_POLICY: + if (gBattleStruct->blunderPolicy + && gBattleMons[gBattlerAttacker].hp != 0 + && gBattleMons[gBattlerAttacker].statStages[STAT_SPEED] < MAX_STAT_STAGE) + { + gBattleStruct->blunderPolicy = FALSE; + gLastUsedItem = atkItem; + gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPEED, 2, FALSE); + effect = ITEM_STATS_CHANGE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; + } + break; + } + break; + case ITEMEFFECT_LIFEORB_SHELLBELL: + // occur after the final hit of a multi-strike move + switch (atkHoldEffect) + { case HOLD_EFFECT_SHELL_BELL: if (gBattleMoveDamage != 0 // Need to have done damage && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) @@ -6389,35 +6409,40 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) gSpecialStatuses[gBattlerTarget].dmg = 0; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret; - effect++; + effect = TRUE; + } + break; + case HOLD_EFFECT_LIFE_ORB: + if (IsBattlerAlive(gBattlerAttacker) + && !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD + && gSpecialStatuses[gBattlerAttacker].damagedMons) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 10; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + effect = TRUE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_ItemHurtRet; + gLastUsedItem = gBattleMons[gBattlerAttacker].item; } break; case HOLD_EFFECT_THROAT_SPRAY: // Does NOT need to be a damaging move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && !(gHitMarker & (HITMARKER_UNABLE_TO_USE_MOVE)) && gBattleMons[gBattlerAttacker].hp != 0 && gBattleMoves[gCurrentMove].flags & FLAG_SOUND - && gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] < MAX_STAT_STAGE) + && gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] < MAX_STAT_STAGE + && !NoAliveMonsForEitherParty()) // don't activate if battle will end { gLastUsedItem = atkItem; + gBattleScripting.battler = gBattlerAttacker; gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE); effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; } break; - case HOLD_EFFECT_BLUNDER_POLICY: - if (gBattleStruct->blunderPolicy - && gBattleMons[gBattlerAttacker].hp != 0 - && gBattleMons[gBattlerAttacker].statStages[STAT_SPEED] < MAX_STAT_STAGE) - { - gBattleStruct->blunderPolicy = FALSE; - gLastUsedItem = atkItem; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPEED, 2, FALSE); - effect = ITEM_STATS_CHANGE; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; - } - break; } break; case ITEMEFFECT_TARGET: From 7f4accdae4e50af6b43a8c9be2273a915a130077 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 11:16:16 -0400 Subject: [PATCH 31/49] fix room service switching in effect --- src/battle_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 5f5f2e19b..04b5abddd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5826,6 +5826,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) RecordItemEffectBattle(battlerId, HOLD_EFFECT_AIR_BALLOON); break; case HOLD_EFFECT_ROOM_SERVICE: + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gBattleMons[battlerId].statStages[STAT_SPEED] > MIN_STAT_STAGE) { PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPEED); @@ -5838,6 +5839,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); effect = ITEM_STATS_CHANGE; } + break; case HOLD_EFFECT_SEEDS: switch (GetBattlerHoldEffectParam(battlerId)) { From 93e2e0914834eba3b90384cf25a4d5c013200505 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 12:17:38 -0400 Subject: [PATCH 32/49] fix terrain seeds. create generic CompareStat function --- data/battle_scripts_1.s | 14 +++++---- include/battle_util.h | 1 + src/battle_script_commands.c | 55 ++++++------------------------------ src/battle_util.c | 55 ++++++++++++++++++++++++++++++++++-- 4 files changed, 71 insertions(+), 54 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 762b9d3e5..188a90ee2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7755,12 +7755,13 @@ BattleScript_BerryStatRaiseEnd2:: 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_BerryStatRaiseDoStatUp -BattleScript_BerryStatRaiseDoStatUp:: + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseEnd2_End + setgraphicalstatchangevalues + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM call BattleScript_StatUp removeitem BS_ATTACKER +BattleScript_BerryStatRaiseEnd2_End:: end2 BattleScript_BerryStatRaiseRet:: @@ -7769,12 +7770,13 @@ BattleScript_BerryStatRaiseRet:: 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: + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseRet_End + setgraphicalstatchangevalues + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM call BattleScript_StatUp removeitem BS_SCRIPTING +BattleScript_BerryStatRaiseRet_End: return BattleScript_BerryFocusEnergyEnd2:: diff --git a/include/battle_util.h b/include/battle_util.h index f72f85d5c..6e2b2b5dd 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -148,6 +148,7 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId); u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute); bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); +bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind, bool32 checkContrary); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a53a6b0e0..576dde83c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3583,52 +3583,11 @@ static void Cmd_jumpifstat(void) { bool32 ret = 0; u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - u8 statValue = gBattleMons[battlerId].statStages[gBattlescriptCurrInstr[3]]; + u8 statId = gBattlescriptCurrInstr[3]; u8 cmpTo = gBattlescriptCurrInstr[4]; u8 cmpKind = gBattlescriptCurrInstr[2]; - // Because this command is used as a way of checking if a stat can be lowered/raised, - // we need to do some modification at run-time. - if (GetBattlerAbility(battlerId) == ABILITY_CONTRARY) - { - if (cmpKind == CMP_GREATER_THAN) - cmpKind = CMP_LESS_THAN; - else if (cmpKind == CMP_LESS_THAN) - cmpKind = CMP_GREATER_THAN; - - if (cmpTo == 0) - cmpTo = 0xC; - else if (cmpTo == 0xC) - cmpTo = 0; - } - - switch (cmpKind) - { - case CMP_EQUAL: - if (statValue == cmpTo) - ret++; - break; - case CMP_NOT_EQUAL: - if (statValue != cmpTo) - ret++; - break; - case CMP_GREATER_THAN: - if (statValue > cmpTo) - ret++; - break; - case CMP_LESS_THAN: - if (statValue < cmpTo) - ret++; - break; - case CMP_COMMON_BITS: - if (statValue & cmpTo) - ret++; - break; - case CMP_NO_COMMON_BITS: - if (!(statValue & cmpTo)) - ret++; - break; - } + ret = CompareStat(battlerId, statId, cmpTo, cmpKind, TRUE); if (ret) gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 5); @@ -8561,7 +8520,7 @@ static void Cmd_various(void) if (ItemBattleEffects(1, gActiveBattler, FALSE)) return; break; - case VARIOUS_TERRAIN_SEED: + case VARIOUS_TERRAIN_SEED: if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_SEEDS) { u8 effect = 0; @@ -9278,12 +9237,16 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr gBattleTextBuff2[index] = STRINGID_STATFELL >> 8; index++; gBattleTextBuff2[index] = B_BUFF_EOS; - - gSpecialStatuses[gActiveBattler].statFell = TRUE; // For eject pack + if (gBattleMons[gActiveBattler].statStages[statId] == MIN_STAT_STAGE) + { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE; + } else + { + gSpecialStatuses[gActiveBattler].statFell = TRUE; // For eject pack gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL + } } } else // stat increase diff --git a/src/battle_util.c b/src/battle_util.c index 04b5abddd..16f414c5e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5569,7 +5569,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split) u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute) { - if (gFieldStatuses & terrainFlag && gBattleMons[battler].statStages[statId] < MAX_STAT_STAGE) + if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, TRUE)) { PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); @@ -5826,7 +5826,6 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) RecordItemEffectBattle(battlerId, HOLD_EFFECT_AIR_BALLOON); break; case HOLD_EFFECT_ROOM_SERVICE: - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gBattleMons[battlerId].statStages[STAT_SPEED] > MIN_STAT_STAGE) { PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPEED); @@ -8944,3 +8943,55 @@ bool32 TestSheerForceFlag(u8 battler, u16 move) else return FALSE; } + +// This function is the body of "jumpifstat", but can be used dynamically in a function +bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind, bool32 checkContrary) +{ + bool8 ret = FALSE; + u8 statValue = gBattleMons[battlerId].statStages[statId]; + + // Because this command is used as a way of checking if a stat can be lowered/raised, + // we need to do some modification at run-time. + if (checkContrary && GetBattlerAbility(battlerId) == ABILITY_CONTRARY) + { + if (cmpKind == CMP_GREATER_THAN) + cmpKind = CMP_LESS_THAN; + else if (cmpKind == CMP_LESS_THAN) + cmpKind = CMP_GREATER_THAN; + + if (cmpTo == MIN_STAT_STAGE) + cmpTo = MAX_STAT_STAGE; + else if (cmpTo == MAX_STAT_STAGE) + cmpTo = MIN_STAT_STAGE; + } + + switch (cmpKind) + { + case CMP_EQUAL: + if (statValue == cmpTo) + ret = TRUE; + break; + case CMP_NOT_EQUAL: + if (statValue != cmpTo) + ret = TRUE; + break; + case CMP_GREATER_THAN: + if (statValue > cmpTo) + ret = TRUE; + break; + case CMP_LESS_THAN: + if (statValue < cmpTo) + ret = TRUE; + break; + case CMP_COMMON_BITS: + if (statValue & cmpTo) + ret = TRUE; + break; + case CMP_NO_COMMON_BITS: + if (!(statValue & cmpTo)) + ret = TRUE; + break; + } + + return ret; +} From c7a587913bb6dbed0e11f960005d2e481f370113 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 13:13:02 -0400 Subject: [PATCH 33/49] replace statStages checks with CompareStat --- include/battle_util.h | 2 +- src/battle_script_commands.c | 23 ++++++++-------- src/battle_util.c | 53 ++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 6e2b2b5dd..91db8af1d 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -148,7 +148,7 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId); u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute); bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); -bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind, bool32 checkContrary); +bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 576dde83c..afc2dc124 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3587,7 +3587,7 @@ static void Cmd_jumpifstat(void) u8 cmpTo = gBattlescriptCurrInstr[4]; u8 cmpKind = gBattlescriptCurrInstr[2]; - ret = CompareStat(battlerId, statId, cmpTo, cmpKind, TRUE); + ret = CompareStat(battlerId, statId, cmpTo, cmpKind); if (ret) gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 5); @@ -4786,7 +4786,7 @@ static void Cmd_moveend(void) && gBattleMons[gBattlerTarget].hp != 0 && gBattlerAttacker != gBattlerTarget && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED - && gBattleMoves[gCurrentMove].power && gBattleMons[gBattlerTarget].statStages[STAT_ATK] < MAX_STAT_STAGE) + && gBattleMoves[gCurrentMove].power && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[gBattlerTarget].statStages[STAT_ATK]++; BattleScriptPushCursor(); @@ -7476,7 +7476,7 @@ static void Cmd_various(void) bits = 0; for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) { - if (gBattleMons[gActiveBattler].statStages[i] != 12) + if (CompareStat(gActiveBattler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) bits |= gBitTable[i]; } if (bits) @@ -7713,7 +7713,7 @@ static void Cmd_various(void) || GetBattlerAbility(gActiveBattler) == ABILITY_AS_ONE_ICE_RIDER) && HasAttackerFaintedTarget() && !NoAliveMonsForEitherParty() - && gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12) + && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[gBattlerAttacker].statStages[STAT_ATK]++; SET_STATCHANGER(STAT_ATK, 1, FALSE); @@ -7731,7 +7731,7 @@ static void Cmd_various(void) || GetBattlerAbility(gActiveBattler) == ABILITY_AS_ONE_SHADOW_RIDER) && HasAttackerFaintedTarget() && !NoAliveMonsForEitherParty() - && gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] != 12) + && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]++; SET_STATCHANGER(STAT_SPATK, 1, FALSE); @@ -7776,7 +7776,7 @@ static void Cmd_various(void) if (GetBattlerAbility(gActiveBattler) == ABILITY_BEAST_BOOST && HasAttackerFaintedTarget() && !NoAliveMonsForEitherParty() - && gBattleMons[gBattlerAttacker].statStages[i] != 12) + && CompareStat(gActiveBattler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[gBattlerAttacker].statStages[i]++; SET_STATCHANGER(i, 1, FALSE); @@ -7793,7 +7793,7 @@ static void Cmd_various(void) if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART && IsBattlerAlive(gBattleScripting.battler) && !NoAliveMonsForEitherParty() - && gBattleMons[gBattleScripting.battler].statStages[STAT_SPATK] != 12) + && CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[gBattleScripting.battler].statStages[STAT_SPATK]++; SET_STATCHANGER(STAT_SPATK, 1, FALSE); @@ -7809,7 +7809,7 @@ static void Cmd_various(void) if (gBattleMoves[gCurrentMove].effect == EFFECT_FELL_STINGER && HasAttackerFaintedTarget() && !NoAliveMonsForEitherParty() - && gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12) + && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { if (B_FELL_STINGER_STAT_RAISE >= GEN_7) SET_STATCHANGER(STAT_ATK, 3, FALSE); @@ -10712,8 +10712,8 @@ static void Cmd_handlerollout(void) static void Cmd_jumpifconfusedandstatmaxed(void) { if (gBattleMons[gBattlerTarget].status2 & STATUS2_CONFUSION - && gBattleMons[gBattlerTarget].statStages[gBattlescriptCurrInstr[1]] == MAX_STAT_STAGE) - gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); + && CompareStat(gBattlerTarget, gBattlescriptCurrInstr[1], MAX_STAT_STAGE, CMP_LESS_THAN)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); // Fails if we're confused AND stat cannot be raised else gBattlescriptCurrInstr += 6; } @@ -10922,7 +10922,8 @@ static void Cmd_maxattackhalvehp(void) // belly drum if (!(gBattleMons[gBattlerAttacker].maxHP / 2)) halfHp = 1; - + + // Belly Drum fails if the user's current HP is less than half its maximum, or if the user's Attack is already at +6 (even if the user has Contrary). if (gBattleMons[gBattlerAttacker].statStages[STAT_ATK] < MAX_STAT_STAGE && gBattleMons[gBattlerAttacker].hp > halfHp) { diff --git a/src/battle_util.c b/src/battle_util.c index 16f414c5e..466ebcfe6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1444,8 +1444,8 @@ void PrepareStringBattle(u16 stringId, u8 battler) // Check Defiant and Competitive stat raise whenever a stat is lowered. else if ((stringId == STRINGID_DEFENDERSSTATFELL || stringId == STRINGID_PKMNCUTSATTACKWITH) - && ((GetBattlerAbility(gBattlerTarget) == ABILITY_DEFIANT && gBattleMons[gBattlerTarget].statStages[STAT_ATK] != MAX_STAT_STAGE) - || (GetBattlerAbility(gBattlerTarget) == ABILITY_COMPETITIVE && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] != MAX_STAT_STAGE)) + && ((GetBattlerAbility(gBattlerTarget) == ABILITY_DEFIANT && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + || (GetBattlerAbility(gBattlerTarget) == ABILITY_COMPETITIVE && CompareStat(gBattlerTarget, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))) && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != BATTLE_PARTNER(gBattlerTarget) && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) { @@ -4053,7 +4053,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move gSpecialStatuses[battler].switchInAbilityDone = 1; - if (gBattleMons[battler].statStages[statId] != MAX_STAT_STAGE) + if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[battler].statStages[statId]++; SET_STATCHANGER(statId, 1, FALSE); @@ -4304,7 +4304,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_SPEED_BOOST: - if (gBattleMons[battler].statStages[STAT_SPEED] < MAX_STAT_STAGE && gDisableStructs[battler].isFirstTurn != 2) + if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && gDisableStructs[battler].isFirstTurn != 2) { gBattleMons[battler].statStages[STAT_SPEED]++; gBattleScripting.animArg1 = 14 + STAT_SPEED; @@ -4322,9 +4322,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move for (i = STAT_ATK; i < statsNum; i++) { - if (gBattleMons[battler].statStages[i] != MIN_STAT_STAGE) + if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN)) validToLower |= gBitTable[i]; - if (gBattleMons[battler].statStages[i] != MAX_STAT_STAGE) + if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) validToRaise |= gBitTable[i]; } @@ -4527,7 +4527,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } else if (effect == 2) // Boost Stat ability; { - if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE) + if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; @@ -4556,7 +4556,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) && moveType == TYPE_DARK - && gBattleMons[battler].statStages[STAT_ATK] != MAX_STAT_STAGE) + && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptPushCursor(); @@ -4569,7 +4569,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) && (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST) - && gBattleMons[battler].statStages[STAT_SPEED] != MAX_STAT_STAGE) + && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_SPEED, 1, FALSE); BattleScriptPushCursor(); @@ -4582,7 +4582,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) && moveType == TYPE_WATER - && gBattleMons[battler].statStages[STAT_DEF] != MAX_STAT_STAGE) + && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_DEF, 2, FALSE); BattleScriptPushCursor(); @@ -4594,7 +4594,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) - && gBattleMons[battler].statStages[STAT_DEF] != MAX_STAT_STAGE) + && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_DEF, 1, FALSE); BattleScriptPushCursor(); @@ -4611,7 +4611,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && gBattleMons[battler].hp < gBattleMons[battler].maxHP / 2 && (gMultiHitCounter == 0 || gMultiHitCounter == 1) && !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) - && gBattleMons[battler].statStages[STAT_SPATK] != MAX_STAT_STAGE) + && CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_SPATK, 1, FALSE); BattleScriptPushCursor(); @@ -4642,7 +4642,8 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) && IS_MOVE_PHYSICAL(gCurrentMove) - && (gBattleMons[battler].statStages[STAT_SPEED] != MAX_STAT_STAGE || gBattleMons[battler].statStages[STAT_DEF] != MIN_STAT_STAGE)) + && (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if speed cannot be raised + || CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN))) // Don't activate if defense cannot be lowered { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_WeakArmorActivates; @@ -4699,7 +4700,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && gIsCriticalHit && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) - && gBattleMons[battler].statStages[STAT_ATK] != MAX_STAT_STAGE) + && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(STAT_ATK, MAX_STAT_STAGE - gBattleMons[battler].statStages[STAT_ATK], FALSE); BattleScriptPushCursor(); @@ -4726,7 +4727,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_TANGLING_HAIR: if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 - && gBattleMons[gBattlerAttacker].statStages[STAT_SPEED] != MIN_STAT_STAGE + && CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED && IsMoveMakingContact(move, gBattlerAttacker)) @@ -4919,7 +4920,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) - && gBattleMons[battler].statStages[STAT_SPEED] != MAX_STAT_STAGE + && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && (moveType == TYPE_FIRE || moveType == TYPE_WATER)) { SET_STATCHANGER(STAT_SPEED, 6, FALSE); @@ -5441,7 +5442,7 @@ static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId, bool32 end2) static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2) { - if (gBattleMons[battlerId].statStages[statId] < MAX_STAT_STAGE && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId)) + if (CompareStat(battlerId, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId)) { PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); @@ -5475,7 +5476,7 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) for (i = 0; i < 5; i++) { - if (gBattleMons[battlerId].statStages[STAT_ATK + i] < MAX_STAT_STAGE) + if (CompareStat(battlerId, STAT_ATK + i, MAX_STAT_STAGE, CMP_LESS_THAN)) break; } if (i != 5 && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId)) @@ -5483,7 +5484,7 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) do { i = Random() % 5; - } while (gBattleMons[battlerId].statStages[STAT_ATK + i] == MAX_STAT_STAGE); + } while (!CompareStat(battlerId, STAT_ATK + i, MAX_STAT_STAGE, CMP_LESS_THAN)); PREPARE_STAT_BUFFER(gBattleTextBuff1, i + 1); @@ -5544,7 +5545,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split) { if (IsBattlerAlive(battlerId) && TARGET_TURN_DAMAGED - && gBattleMons[battlerId].statStages[statId] < MAX_STAT_STAGE + && CompareStat(battlerId, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) && GetBattleMoveSplit(gCurrentMove) == split) { @@ -5569,7 +5570,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split) u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute) { - if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, TRUE)) + if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); @@ -5826,7 +5827,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) RecordItemEffectBattle(battlerId, HOLD_EFFECT_AIR_BALLOON); break; case HOLD_EFFECT_ROOM_SERVICE: - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gBattleMons[battlerId].statStages[STAT_SPEED] > MIN_STAT_STAGE) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battlerId, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN)) { PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPEED); PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); @@ -6376,7 +6377,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) case HOLD_EFFECT_BLUNDER_POLICY: if (gBattleStruct->blunderPolicy && gBattleMons[gBattlerAttacker].hp != 0 - && gBattleMons[gBattlerAttacker].statStages[STAT_SPEED] < MAX_STAT_STAGE) + && CompareStat(gBattlerAttacker, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleStruct->blunderPolicy = FALSE; gLastUsedItem = atkItem; @@ -6433,7 +6434,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) && !(gHitMarker & (HITMARKER_UNABLE_TO_USE_MOVE)) && gBattleMons[gBattlerAttacker].hp != 0 && gBattleMoves[gCurrentMove].flags & FLAG_SOUND - && gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] < MAX_STAT_STAGE + && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) && !NoAliveMonsForEitherParty()) // don't activate if battle will end { gLastUsedItem = atkItem; @@ -8945,14 +8946,14 @@ bool32 TestSheerForceFlag(u8 battler, u16 move) } // This function is the body of "jumpifstat", but can be used dynamically in a function -bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind, bool32 checkContrary) +bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind) { bool8 ret = FALSE; u8 statValue = gBattleMons[battlerId].statStages[statId]; // Because this command is used as a way of checking if a stat can be lowered/raised, // we need to do some modification at run-time. - if (checkContrary && GetBattlerAbility(battlerId) == ABILITY_CONTRARY) + if (GetBattlerAbility(battlerId) == ABILITY_CONTRARY) { if (cmpKind == CMP_GREATER_THAN) cmpKind = CMP_LESS_THAN; From 4e2948012fbd80b4145a65fe5ccfb116b48a2e99 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 13:18:33 -0400 Subject: [PATCH 34/49] poison type still absorbs toxic spikes with heavy duty boots --- src/battle_script_commands.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index afc2dc124..a55bc968b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5991,7 +5991,6 @@ static void Cmd_switchineffects(void) } else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES) - && IsBattlerAffectedByHazards(gActiveBattler, TRUE) && IsBattlerGrounded(gActiveBattler)) { gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_TOXIC_SPIKES_DAMAGED; @@ -6003,7 +6002,7 @@ static void Cmd_switchineffects(void) BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ToxicSpikesAbsorbed; } - else + else if (IsBattlerAffectedByHazards(gActiveBattler, TRUE)) { if (!(gBattleMons[gActiveBattler].status1 & STATUS1_ANY) && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL) From 5c5276b04dc8198ee415b15bb191833f308b82d8 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 14:29:28 -0400 Subject: [PATCH 35/49] red card fixes --- data/battle_scripts_1.s | 4 ++-- src/battle_script_commands.c | 43 ++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 188a90ee2..c19812433 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5583,6 +5583,7 @@ BattleScript_RoarSuccessSwitch:: goto BattleScript_MoveEnd BattleScript_RoarSuccessSwitch_Ret: swapattackerwithtarget @ continuation of RedCardActivates + restoretarget removeitem BS_TARGET setbyte sSWITCH_CASE, B_SWITCH_NORMAL return @@ -8031,11 +8032,10 @@ BattleScript_StickyBarbTransfer:: return BattleScript_RedCardActivates:: - jumpifcantswitch BS_ATTACKER, BattleScript_RedCardEnd playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_REDCARDACTIVATE waitmessage 0x40 - swapattackerwithtarget + swapattackerwithtarget jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups setbyte sSWITCH_CASE, B_SWITCH_RED_CARD diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a55bc968b..7cc12b391 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5103,26 +5103,26 @@ static void Cmd_moveend(void) case MOVEEND_RED_CARD: if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && IsBattlerAlive(gBattlerAttacker) - && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) - && (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER || (gBattleTypeFlags & BATTLE_TYPE_TRAINER))) + && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) { + // since we check if battler was damaged, we don't need to check move result. + // In fact, doing so actually prevents multi-target moves from activating red card properly u8 battlers[4] = {0, 1, 2, 3}; SortBattlersBySpeed(battlers, FALSE); for (i = 0; i < gBattlersCount; i++) { u8 battler = battlers[i]; + // Search for fastest hit pokemon with a red card // Attacker is the one to be switched out, battler is one with red card if (battler != gBattlerAttacker && IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD - && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) - && CountUsablePartyMons(battler) > 0) // Has mon to switch into - { + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)) + { gLastUsedItem = gBattleMons[battler].item; - gActiveBattler = gBattleScripting.battler = battler; // Battler with red card + gActiveBattler = gBattleStruct->savedBattlerTarget = gBattleScripting.battler = battler; // Battler with red card gEffectBattler = gBattlerAttacker; if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE) gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection @@ -5533,6 +5533,7 @@ bool32 CanBattlerSwitch(u32 battlerId) } else { + // check if attacker side has mon to switch into battlerIn1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) @@ -6125,7 +6126,7 @@ static void Cmd_endlinkbattle(void) } static void Cmd_returntoball(void) -{ +{ gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); BtlController_EmitReturnMonToBall(0, 1); MarkBattlerForControllerExec(gActiveBattler); @@ -9420,6 +9421,30 @@ static void Cmd_forcerandomswitch(void) struct Pokemon* party = NULL; s32 validMons = 0; s32 minNeeded; + + // check wild mon holding a red card + // red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF... + if (gBattleScripting.switchCase == B_SWITCH_RED_CARD + && !(gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) + { + if (WILD_DOUBLE_BATTLE) + { + // if wild mon with red card is the last one alive, it ends the battle + if (!IS_WHOLE_SIDE_ALIVE(gBattlerAttacker)) + { + gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; + return; + } + // else, try to make attacker (aka player) change pokemon + } + else + { + // Wild mon with red card will end single battle + gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; + return; + } + } // Swapping pokemon happens in: // trainer battles @@ -9434,7 +9459,7 @@ static void Cmd_forcerandomswitch(void) && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) ) - { + { if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) party = gPlayerParty; else From 79f39a1fd04a87b6b6381da8349f9220a8251399 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 14:56:36 -0400 Subject: [PATCH 36/49] fix eject button --- data/battle_scripts_1.s | 1 - src/battle_script_commands.c | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c19812433..c7256dc7e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8057,7 +8057,6 @@ BattleScript_RedCardSuctionCups: return BattleScript_EjectButtonActivates:: - jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd makevisible BS_ATTACKER playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_EJECTBUTTONACTIVATE diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7cc12b391..9f1b0ba93 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5070,11 +5070,12 @@ static void Cmd_moveend(void) case MOVEEND_EJECT_BUTTON: if (gCurrentMove != MOVE_DRAGON_TAIL && gCurrentMove != MOVE_CIRCLE_THROW - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && IsBattlerAlive(gBattlerAttacker) && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove) && (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER || (gBattleTypeFlags & BATTLE_TYPE_TRAINER))) { + // Since we check if battler was damaged, we don't need to check move result. + // In fact, doing so actually prevents multi-target moves from activating eject button properly u8 battlers[4] = {0, 1, 2, 3}; SortBattlersBySpeed(battlers, FALSE); for (i = 0; i < gBattlersCount; i++) @@ -5106,7 +5107,7 @@ static void Cmd_moveend(void) && IsBattlerAlive(gBattlerAttacker) && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) { - // since we check if battler was damaged, we don't need to check move result. + // Since we check if battler was damaged, we don't need to check move result. // In fact, doing so actually prevents multi-target moves from activating red card properly u8 battlers[4] = {0, 1, 2, 3}; SortBattlersBySpeed(battlers, FALSE); From e475813799a4311d06a3403335494ee1ef4acd01 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sat, 4 Sep 2021 08:18:38 -0400 Subject: [PATCH 37/49] revert mental herb desc --- src/data/text/item_descriptions.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/data/text/item_descriptions.h b/src/data/text/item_descriptions.h index d47152f7f..5f79efc57 100644 --- a/src/data/text/item_descriptions.h +++ b/src/data/text/item_descriptions.h @@ -743,17 +743,10 @@ static const u8 sSootheBellDesc[] = _( "calms spirits and\n" "fosters friendship."); -#if B_MENTAL_HERB < GEN_5 static const u8 sMentalHerbDesc[] = _( "A hold item that\n" "snaps POKéMON out\n" "of infatuation."); -#else -static const u8 sMentalHerbDesc[] = _( - "Snaps Pokémon out\n" - "of move-binding\n" - "effects."); -#endif static const u8 sChoiceBandDesc[] = _( "Raises a move's\n" From a9cbaa5966c7a0f5a23517318bad485e08357c80 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sat, 4 Sep 2021 08:40:43 -0400 Subject: [PATCH 38/49] fix mental herb encore, heal block --- src/battle_util.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index adb0c70ad..81f9cfaf9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5605,6 +5605,7 @@ static bool32 UnnerveOn(u32 battlerId, u32 itemId) static bool32 GetMentalHerbEffect(u8 battlerId) { bool32 ret = FALSE; + // Check infatuation if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) { @@ -5615,18 +5616,18 @@ static bool32 GetMentalHerbEffect(u8 battlerId) } #if B_MENTAL_HERB >= GEN_5 // Check taunt - if (gDisableStructs[gBattlerTarget].tauntTimer != 0) + if (gDisableStructs[battlerId].tauntTimer != 0) { - gDisableStructs[gBattlerTarget].tauntTimer = gDisableStructs[gBattlerTarget].tauntTimer2 = 0; + gDisableStructs[battlerId].tauntTimer = gDisableStructs[battlerId].tauntTimer2 = 0; gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETAUNT; PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); ret = TRUE; } // Check encore - if (gDisableStructs[gBattlerTarget].encoreTimer != 0) + if (gDisableStructs[battlerId].encoreTimer != 0) { - gDisableStructs[gActiveBattler].encoredMove = 0; - gDisableStructs[gBattlerTarget].encoreTimerStartValue = gDisableStructs[gBattlerTarget].encoreTimer = 0; + gDisableStructs[battlerId].encoredMove = 0; + gDisableStructs[battlerId].encoreTimerStartValue = gDisableStructs[battlerId].encoreTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; // STRINGID_PKMNENCOREENDED ret = TRUE; } @@ -5645,10 +5646,10 @@ static bool32 GetMentalHerbEffect(u8 battlerId) ret = TRUE; } // Check disable - if (gDisableStructs[gBattlerTarget].disableTimer != 0) + if (gDisableStructs[battlerId].disableTimer != 0) { - gDisableStructs[gBattlerTarget].disableTimer = gDisableStructs[gBattlerTarget].disableTimerStartValue = 0; - gDisableStructs[gBattlerTarget].disabledMove = 0; + gDisableStructs[battlerId].disableTimer = gDisableStructs[battlerId].disableTimerStartValue = 0; + gDisableStructs[battlerId].disabledMove = 0; gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREDISABLE; ret = TRUE; } From 95af97593bb18597a462e952026e74c121d576ab Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 14 Sep 2021 11:53:35 -0400 Subject: [PATCH 39/49] fix some comment styling. fix throat spray for multi-target moves --- data/battle_scripts_1.s | 9 +++++---- include/battle.h | 2 +- include/constants/battle_script_commands.h | 6 +++--- src/battle_main.c | 2 +- src/battle_script_commands.c | 16 +++++++++++----- src/battle_util.c | 9 ++------- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4ea8042a7..f0d4f4c97 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6948,13 +6948,13 @@ BattleScript_SnowWarningActivates:: BattleScript_TerrainSeedLoop: savetarget setbyte gBattlerTarget, 0 -TerrainSeedLoop: +BattleScript_TerrainSeedLoopIter: copybyte sBATTLER, gBattlerTarget - doterrainseed BS_TARGET, TerrainSeedLoop_NextBattler + doterrainseed BS_TARGET, BattleScript_TerrainSeedLoop_NextBattler removeitem BS_TARGET -TerrainSeedLoop_NextBattler: +BattleScript_TerrainSeedLoop_NextBattler: addbyte gBattlerTarget, 0x1 - jumpifbytenotequal gBattlerTarget, gBattlersCount, TerrainSeedLoop + jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TerrainSeedLoopIter restoretarget return @@ -7187,6 +7187,7 @@ BattleScript_AbilityNoSpecificStatLoss:: printstring STRINGID_PKMNSXPREVENTSYLOSS waitmessage B_WAIT_TIME_LONG setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY + orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT return BattleScript_StickyHoldActivates:: diff --git a/include/battle.h b/include/battle.h index a3f7d027d..43a941737 100644 --- a/include/battle.h +++ b/include/battle.h @@ -126,7 +126,7 @@ struct ProtectStruct u32 stealMove:1; u32 prlzImmobility:1; u32 confusionSelfDmg:1; - u32 targetNotAffected:1; + u32 targetAffected:1; u32 chargingTurn:1; u32 fleeFlag:2; // For RunAway and Smoke Ball. u32 usedImprisonedMove:1; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index f35a37766..a59b930b4 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -231,15 +231,15 @@ #define MOVEEND_ITEM_EFFECTS_TARGET 13 #define MOVEEND_MOVE_EFFECTS2 14 #define MOVEEND_ITEM_EFFECTS_ALL 15 -#define MOVEEND_KINGSROCK 16 // these item effects will occur each strike of a multi-hit move +#define MOVEEND_KINGSROCK 16 // These item effects will occur each strike of a multi-hit move #define MOVEEND_SUBSTITUTE 17 #define MOVEEND_UPDATE_LAST_MOVES 18 #define MOVEEND_MIRROR_MOVE 19 -#define MOVEEND_NEXT_TARGET 20 // everything up until here is handled for each strike of a multi-hit move +#define MOVEEND_NEXT_TARGET 20 // Everything up until here is handled for each strike of a multi-hit move #define MOVEEND_EJECT_BUTTON 21 #define MOVEEND_RED_CARD 22 #define MOVEEND_EJECT_PACK 23 -#define MOVEEND_LIFEORB_SHELLBELL 24 // includes shell bell, throat spray, etc +#define MOVEEND_LIFEORB_SHELLBELL 24 // Includes shell bell, throat spray, etc #define MOVEEND_PICKPOCKET 25 #define MOVEEND_DANCER 26 #define MOVEEND_EMERGENCY_EXIT 27 diff --git a/src/battle_main.c b/src/battle_main.c index aed1dc568..74995bbf3 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3078,7 +3078,7 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].stealMove = 0; gProtectStructs[gActiveBattler].prlzImmobility = 0; gProtectStructs[gActiveBattler].confusionSelfDmg = 0; - gProtectStructs[gActiveBattler].targetNotAffected = 0; + gProtectStructs[gActiveBattler].targetAffected = 0; gProtectStructs[gActiveBattler].chargingTurn = 0; gProtectStructs[gActiveBattler].fleeFlag = 0; gProtectStructs[gActiveBattler].usedImprisonedMove = 0; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 044090069..6ba74177d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4913,8 +4913,8 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK: // king's rock and shell bell - // these effects will occur at each hit in a multi-strike move + case MOVEEND_KINGSROCK: // King's rock and shell bell + // These effects will occur at each hit in a multi-strike move if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) effect = TRUE; gBattleScripting.moveendState++; @@ -5043,6 +5043,11 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon. + // Set a flag if move hits either target (for throat spray that can't check damage) + if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + gProtectStructs[gBattlerAttacker].targetAffected = 1; + if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !gProtectStructs[gBattlerAttacker].chargingTurn @@ -5285,6 +5290,7 @@ static void Cmd_moveend(void) if (gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget) *(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3; gProtectStructs[gBattlerAttacker].usesBouncedMove = 0; + gProtectStructs[gBattlerAttacker].targetAffected = 0; gBattleStruct->ateBoost[gBattlerAttacker] = 0; gStatuses3[gBattlerAttacker] &= ~(STATUS3_ME_FIRST); gSpecialStatuses[gBattlerAttacker].gemBoost = 0; @@ -5554,7 +5560,7 @@ bool32 CanBattlerSwitch(u32 battlerId) } else { - // check if attacker side has mon to switch into + // Check if attacker side has mon to switch into battlerIn1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) @@ -6147,7 +6153,7 @@ static void Cmd_endlinkbattle(void) } static void Cmd_returntoball(void) -{ +{ gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); BtlController_EmitReturnMonToBall(0, 1); MarkBattlerForControllerExec(gActiveBattler); @@ -7802,7 +7808,7 @@ static void Cmd_various(void) if (GetBattlerAbility(gActiveBattler) == ABILITY_BEAST_BOOST && HasAttackerFaintedTarget() && !NoAliveMonsForEitherParty() - && CompareStat(gActiveBattler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) + && CompareStat(gBattlerAttacker, i, MAX_STAT_STAGE, CMP_LESS_THAN)) { gBattleMons[gBattlerAttacker].statStages[i]++; SET_STATCHANGER(i, 1, FALSE); diff --git a/src/battle_util.c b/src/battle_util.c index bc5c7e0e7..ab7db3d88 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1410,7 +1410,6 @@ void CancelMultiTurnMoves(u8 battler) bool8 WasUnableToUseMove(u8 battler) { if (gProtectStructs[battler].prlzImmobility - || gProtectStructs[battler].targetNotAffected || gProtectStructs[battler].usedImprisonedMove || gProtectStructs[battler].loveImmobility || gProtectStructs[battler].usedDisabledMove @@ -6399,10 +6398,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) switch (atkHoldEffect) { case HOLD_EFFECT_SHELL_BELL: - if (gBattleMoveDamage != 0 // Need to have done damage - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && gSpecialStatuses[gBattlerTarget].dmg != 0 - && gSpecialStatuses[gBattlerTarget].dmg != 0xFFFF + if (gSpecialStatuses[gBattlerAttacker].damagedMons // Need to have done damage && gBattlerAttacker != gBattlerTarget && gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP && gBattleMons[gBattlerAttacker].hp != 0) @@ -6435,8 +6431,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; case HOLD_EFFECT_THROAT_SPRAY: // Does NOT need to be a damaging move - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && !(gHitMarker & (HITMARKER_UNABLE_TO_USE_MOVE)) + if (gProtectStructs[gBattlerAttacker].targetAffected && gBattleMons[gBattlerAttacker].hp != 0 && gBattleMoves[gCurrentMove].flags & FLAG_SOUND && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) From 60713a8f2d76769ba4f8ae60ed3663e189811a06 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 14 Sep 2021 12:50:36 -0400 Subject: [PATCH 40/49] fix room service activation msg, stat target --- asm/macros/battle_script.inc | 5 ++ data/battle_scripts_1.s | 17 ++---- include/battle_util.h | 1 + include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 11 ++++ src/battle_util.c | 63 ++++++++++++++++++---- 6 files changed, 75 insertions(+), 23 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 14bfe2c38..ac7266690 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1786,6 +1786,11 @@ various \battler, VARIOUS_MAKE_INVISIBLE .endm + .macro tryroomservice battler:req, ptr:req + various \battler, VARIOUS_ROOM_SERVICE + .4byte \ptr + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f0d4f4c97..28e9f8327 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1860,21 +1860,12 @@ BattleScript_EffectTrickRoom: attackanimation waitanimation printfromtable gRoomsStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG savetarget setbyte gBattlerTarget, 0 BattleScript_RoomServiceLoop: copybyte sBATTLER, gBattlerTarget - jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_ROOM_SERVICE, BattleScript_RoomServiceLoop_NextBattler - jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_RoomServiceLoop_NextBattler - setstatchanger STAT_SPEED, 1, TRUE - statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_RoomServiceLoop_NextBattler - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_RoomServiceLoop_NextBattler - playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL - waitanimation - playstatchangeanimation BS_TARGET, BIT_SPEED, STAT_CHANGE_NEGATIVE - printstring STRINGID_USINGITEMSTATOFPKMNROSE - waitmessage 0x40 + tryroomservice BS_TARGET, BattleScript_RoomServiceLoop_NextBattler removeitem BS_TARGET BattleScript_RoomServiceLoop_NextBattler: addbyte gBattlerTarget, 0x1 @@ -7776,7 +7767,7 @@ BattleScript_BerryStatRaiseEnd2:: BattleScript_BerryStatRaiseEnd2_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_BerryStatRaiseEnd2_Anim: - statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseEnd2_End + statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseEnd2_End setgraphicalstatchangevalues playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM @@ -7791,7 +7782,7 @@ BattleScript_BerryStatRaiseRet:: BattleScript_BerryStatRaiseRet_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_BerryStatRaiseRet_Anim: - statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseRet_End + statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseRet_End setgraphicalstatchangevalues playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM diff --git a/include/battle_util.h b/include/battle_util.h index 91db8af1d..ad0c69534 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -149,6 +149,7 @@ u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exec bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); +bool32 TryRoomService(u8 battlerId); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index a59b930b4..6ab8df300 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -177,6 +177,7 @@ #define VARIOUS_MOVEEND_ITEM_EFFECTS 105 #define VARIOUS_TERRAIN_SEED 106 #define VARIOUS_MAKE_INVISIBLE 107 +#define VARIOUS_ROOM_SERVICE 108 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6ba74177d..b3f528a00 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8553,6 +8553,17 @@ static void Cmd_various(void) if (ItemBattleEffects(1, gActiveBattler, FALSE)) return; break; + case VARIOUS_ROOM_SERVICE: + if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(gActiveBattler)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; + } + else + { + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + } + return; case VARIOUS_TERRAIN_SEED: if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_SEEDS) { diff --git a/src/battle_util.c b/src/battle_util.c index ab7db3d88..eb10bc896 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5577,8 +5577,7 @@ u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exec PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); gLastUsedItem = itemId; // For surge abilities - gEffectBattler = battler; - gBattleScripting.battler = battler; + gEffectBattler = gBattleScripting.battler = battler; SET_STATCHANGER(statId, 1, FALSE); gBattleScripting.animArg1 = 0xE + statId; gBattleScripting.animArg2 = 0; @@ -5831,15 +5830,8 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) RecordItemEffectBattle(battlerId, HOLD_EFFECT_AIR_BALLOON); break; case HOLD_EFFECT_ROOM_SERVICE: - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battlerId, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN)) + if (TryRoomService(battlerId)) { - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPEED); - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); - - gEffectBattler = battlerId; - SET_STATCHANGER(STAT_SPEED, 1, TRUE); - gBattleScripting.animArg1 = 0xE + STAT_SPEED; - gBattleScripting.animArg2 = 0; BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); effect = ITEM_STATS_CHANGE; } @@ -8996,3 +8988,54 @@ bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind) return ret; } + +void BufferStatChange(u8 battlerId, u8 statId, u8 stringId) +{ + bool8 hasContrary = (GetBattlerAbility(battlerId) == ABILITY_CONTRARY); + + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); + if (stringId == STRINGID_STATFELL) + { + if (hasContrary) + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); + } + } + else if (stringId == STRINGID_STATROSE) + { + if (hasContrary) + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); + } + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, stringId); + } +} + +bool32 TryRoomService(u8 battlerId) +{ + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battlerId, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN)) + { + BufferStatChange(battlerId, STAT_SPEED, STRINGID_STATFELL); + gEffectBattler = gBattleScripting.battler = battlerId; + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + gBattleScripting.animArg1 = 0xE + STAT_SPEED; + gBattleScripting.animArg2 = 0; + gLastUsedItem = gBattleMons[battlerId].item; + return TRUE; + } + else + { + return FALSE; + } +} From 55c3e152cfd2ea94b285c0829aba1a933dbe01fa Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 14 Sep 2021 15:07:15 -0400 Subject: [PATCH 41/49] replace some BufferStatChange, fix room service and terrain seeds --- include/battle_util.h | 1 + src/battle_util.c | 23 ++++++++++------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index ad0c69534..4f250c7ea 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -150,6 +150,7 @@ bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); bool32 TryRoomService(u8 battlerId); +void BufferStatChange(u8 battlerId, u8 statId, u8 stringId); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_util.c b/src/battle_util.c index eb10bc896..4cec2160a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -557,6 +557,7 @@ void HandleAction_UseItem(void) } break; case AI_ITEM_X_STAT: + // TODO Contrary check gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_ROSE_ITEM; if (*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1)) & (1 << AI_DIRE_HIT)) { @@ -5445,9 +5446,7 @@ static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2) { if (CompareStat(battlerId, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId)) { - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); - + BufferStatChange(battlerId, statId, STRINGID_STATROSE); gEffectBattler = battlerId; if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) SET_STATCHANGER(statId, 2, FALSE); @@ -5474,6 +5473,7 @@ static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2) static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) { s32 i; + u16 stringId; for (i = 0; i < 5; i++) { @@ -5488,16 +5488,17 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) } while (!CompareStat(battlerId, STAT_ATK + i, MAX_STAT_STAGE, CMP_LESS_THAN)); PREPARE_STAT_BUFFER(gBattleTextBuff1, i + 1); - + stringId = (GetBattlerAbility(battlerId) == ABILITY_CONTRARY) ? STRINGID_STATFELL : STRINGID_STATROSE; + gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; gBattleTextBuff2[1] = B_BUFF_STRING; gBattleTextBuff2[2] = STRINGID_STATSHARPLY; gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; gBattleTextBuff2[4] = B_BUFF_STRING; - gBattleTextBuff2[5] = STRINGID_STATROSE; - gBattleTextBuff2[6] = STRINGID_STATROSE >> 8; + gBattleTextBuff2[5] = stringId; + gBattleTextBuff2[6] = stringId >> 8; gBattleTextBuff2[7] = EOS; - + gEffectBattler = battlerId; if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) @@ -5550,9 +5551,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split) && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) && GetBattleMoveSplit(gCurrentMove) == split) { - - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); + BufferStatChange(battlerId, statId, STRINGID_STATROSE); gEffectBattler = battlerId; if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) @@ -5573,9 +5572,7 @@ u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exec { if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); - + BufferStatChange(battler, statId, STRINGID_STATROSE); gLastUsedItem = itemId; // For surge abilities gEffectBattler = gBattleScripting.battler = battler; SET_STATCHANGER(statId, 1, FALSE); From c4ce4c150dbe2c7d67d4bc0ecb2000909fd1f26f Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 14 Sep 2021 15:38:16 -0400 Subject: [PATCH 42/49] fix eject pack --- include/battle.h | 1 + src/battle_script_commands.c | 5 ++++- src/battle_util.c | 7 +++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/battle.h b/include/battle.h index 43a941737..36646c9fe 100644 --- a/include/battle.h +++ b/include/battle.h @@ -145,6 +145,7 @@ struct ProtectStruct u32 micle:1; u32 custap:1; // also quick claw u32 touchedProtectLike:1; + u32 disableEjectPack:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b3f528a00..7146840da 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5171,6 +5171,7 @@ static void Cmd_moveend(void) if (IsBattlerAlive(battler) && gSpecialStatuses[battler].statFell && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_PACK + && !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker)) // Does not activate if attacker used Parting Shot and can switch out && CountUsablePartyMons(battler) > 0) // Has mon to switch into { gSpecialStatuses[battler].statFell = FALSE; @@ -9288,7 +9289,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr } else { - gSpecialStatuses[gActiveBattler].statFell = TRUE; // For eject pack + // Check eject pack. disableEjectPack set for edge cases (e.g. attacking weak armor'd eject pack holder with u-turn) + if (gProtectStructs[gActiveBattler].disableEjectPack == 0) + gSpecialStatuses[gActiveBattler].statFell = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL } } diff --git a/src/battle_util.c b/src/battle_util.c index 4cec2160a..7edc4eadc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -557,7 +557,6 @@ void HandleAction_UseItem(void) } break; case AI_ITEM_X_STAT: - // TODO Contrary check gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_ROSE_ITEM; if (*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1)) & (1 << AI_DIRE_HIT)) { @@ -4645,6 +4644,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if speed cannot be raised || CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN))) // Don't activate if defense cannot be lowered { + if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE && CanBattlerSwitch(gBattlerAttacker)) + gProtectStructs[battler].disableEjectPack = 1; // Set flag for target + BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_WeakArmorActivates; effect++; @@ -5851,7 +5853,8 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; case HOLD_EFFECT_EJECT_PACK: - if (gSpecialStatuses[battlerId].statFell) + if (gSpecialStatuses[battlerId].statFell + && !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out { gSpecialStatuses[battlerId].statFell = FALSE; gActiveBattler = gBattleScripting.battler = battlerId; From 801ba039d6f3595ee218c4c77eb4c5f81c95b596 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 14 Sep 2021 19:18:53 -0400 Subject: [PATCH 43/49] fix red card --- src/battle_script_commands.c | 44 ++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7146840da..5b090b5e4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5145,7 +5145,8 @@ static void Cmd_moveend(void) && IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD - && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)) + && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) + && CanBattlerSwitch(gBattlerAttacker)) { gLastUsedItem = gBattleMons[battler].item; gActiveBattler = gBattleStruct->savedBattlerTarget = gBattleScripting.battler = battler; // Battler with red card @@ -9469,29 +9470,36 @@ static void Cmd_forcerandomswitch(void) s32 validMons = 0; s32 minNeeded; - // check wild mon holding a red card - // red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF... + bool32 redCardForcedSwitch = FALSE; + + // Red card checks against wild pokemon. If we have reached here, the player has a mon to switch into + // Red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF... if (gBattleScripting.switchCase == B_SWITCH_RED_CARD && !(gBattleTypeFlags & BATTLE_TYPE_TRAINER) - && GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) + && GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) // Check opponent's red card activating { - if (WILD_DOUBLE_BATTLE) - { - // if wild mon with red card is the last one alive, it ends the battle - if (!IS_WHOLE_SIDE_ALIVE(gBattlerAttacker)) - { - gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; - return; - } - // else, try to make attacker (aka player) change pokemon - } - else + if (!WILD_DOUBLE_BATTLE) { // Wild mon with red card will end single battle gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; return; } + else + { + // Wild double battle, wild mon red card activation on player + if (IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) + { + // Both player's battlers are alive + redCardForcedSwitch = FALSE; + } + else + { + // Player has only one mon alive -> force red card switch before manually switching to other mon + redCardForcedSwitch = TRUE; + } + } } + // Swapping pokemon happens in: // trainer battles @@ -9505,8 +9513,10 @@ static void Cmd_forcerandomswitch(void) || (WILD_DOUBLE_BATTLE && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) + || redCardForcedSwitch ) - { + { + if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) party = gPlayerParty; else @@ -9614,7 +9624,7 @@ static void Cmd_forcerandomswitch(void) } } - if (validMons <= minNeeded) + if (!redCardForcedSwitch && validMons <= minNeeded) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } From 0bca01cb743d96a4a36165604c9971691b7b917d Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 15 Sep 2021 12:56:58 -0400 Subject: [PATCH 44/49] mental herb fixes --- data/battle_scripts_1.s | 2 +- include/constants/battle_string_ids.h | 14 +++++++------- src/battle_message.c | 12 ++++++------ src/battle_util.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4f30b3f30..a0e7b9445 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7547,7 +7547,7 @@ BattleScript_BerryCureChosenStatusRet:: BattleScript_MentalHerbCureRet:: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL printfromtable gMentalHerbCureStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG updatestatusicon BS_SCRIPTING removeitem BS_SCRIPTING copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 344d1c596..4ddae6990 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -813,12 +813,12 @@ #define B_MSG_SWITCHIN_ASONE 13 #define B_MSG_SWITCHIN_CURIOUS_MEDICINE 14 -// mental herb -#define MULTI_CUREINFATUATION 0 -#define MULTI_CURETAUNT 1 -#define MULTI_CUREENCORE 2 -#define MULTI_CURETORMENT 3 -#define MULTI_CUREHEALBLOCK 4 -#define MULTI_CUREDISABLE 5 +// gMentalHerbCureStringIds +#define B_MSG_MENTALHERBCURE_INFATUATION 0 +#define B_MSG_MENTALHERBCURE_TAUNT 1 +#define B_MSG_MENTALHERBCURE_ENCORE 2 +#define B_MSG_MENTALHERBCURE_TORMENT 3 +#define B_MSG_MENTALHERBCURE_HEALBLOCK 4 +#define B_MSG_MENTALHERBCURE_DISABLE 5 #endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H diff --git a/src/battle_message.c b/src/battle_message.c index 3c21604d8..bec1bf9a8 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1272,12 +1272,12 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = const u16 gMentalHerbCureStringIds[] = { - [MULTI_CUREINFATUATION] = STRINGID_ATKGOTOVERINFATUATION, - [MULTI_CURETAUNT] = STRINGID_BUFFERENDS, - [MULTI_CUREENCORE] = STRINGID_PKMNENCOREENDED, - [MULTI_CURETORMENT] = STRINGID_TORMENTEDNOMORE, - [MULTI_CUREHEALBLOCK] = STRINGID_HEALBLOCKEDNOMORE, - [MULTI_CUREDISABLE] = STRINGID_PKMNMOVEDISABLEDNOMORE, + [B_MSG_MENTALHERBCURE_INFATUATION] = STRINGID_ATKGOTOVERINFATUATION, + [B_MSG_MENTALHERBCURE_TAUNT] = STRINGID_BUFFERENDS, + [B_MSG_MENTALHERBCURE_ENCORE] = STRINGID_PKMNENCOREENDED, + [B_MSG_MENTALHERBCURE_TORMENT] = STRINGID_TORMENTEDNOMORE, + [B_MSG_MENTALHERBCURE_HEALBLOCK] = STRINGID_HEALBLOCKEDNOMORE, + [B_MSG_MENTALHERBCURE_DISABLE] = STRINGID_PKMNMOVEDISABLEDNOMORE, }; const u16 gTerrainStringIds[] = diff --git a/src/battle_util.c b/src/battle_util.c index 5027e48b9..27b4521f4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5643,7 +5643,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) // Check heal block if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK) { - gStatuses3[battlerId] & ~(STATUS3_HEAL_BLOCK); + gStatuses3[battlerId] &= ~(STATUS3_HEAL_BLOCK); gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREHEALBLOCK; ret = TRUE; } From 705b76506701e7870314c8017ff0a7210fb799fb Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 15 Sep 2021 14:51:24 -0400 Subject: [PATCH 45/49] update multistring chooser labels in GetMentalHerbEffect --- src/battle_util.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 27b4521f4..c880c7fdd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5612,7 +5612,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION) { gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION); - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREINFATUATION; // STRINGID_TARGETGOTOVERINFATUATION + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); ret = TRUE; } @@ -5621,7 +5621,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) if (gDisableStructs[battlerId].tauntTimer != 0) { gDisableStructs[battlerId].tauntTimer = gDisableStructs[battlerId].tauntTimer2 = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETAUNT; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); ret = TRUE; } @@ -5630,21 +5630,21 @@ static bool32 GetMentalHerbEffect(u8 battlerId) { gDisableStructs[battlerId].encoredMove = 0; gDisableStructs[battlerId].encoreTimerStartValue = gDisableStructs[battlerId].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREENCORE; // STRINGID_PKMNENCOREENDED + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED ret = TRUE; } // Check torment if (gBattleMons[battlerId].status2 & STATUS2_TORMENT) { gBattleMons[battlerId].status2 &= ~(STATUS2_TORMENT); - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CURETORMENT; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; ret = TRUE; } // Check heal block if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK) { gStatuses3[battlerId] &= ~(STATUS3_HEAL_BLOCK); - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREHEALBLOCK; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; ret = TRUE; } // Check disable @@ -5652,7 +5652,7 @@ static bool32 GetMentalHerbEffect(u8 battlerId) { gDisableStructs[battlerId].disableTimer = gDisableStructs[battlerId].disableTimerStartValue = 0; gDisableStructs[battlerId].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_CUREDISABLE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; ret = TRUE; } #endif From 845e333ba182f3ed5a5968d9773239c1cb1ca781 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 15 Sep 2021 17:11:42 -0400 Subject: [PATCH 46/49] fix electric/misty terrain interactions with yawn/rest failures --- data/battle_scripts_1.s | 7 ++----- include/battle_scripts.h | 2 ++ src/battle_script_commands.c | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f449306a6..f02dd9a3e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2118,14 +2118,14 @@ BattleScript_TerrainPreventsEnd2:: waitmessage B_WAIT_TIME_LONG end2 -BattleScript_ElectricTerrainPrevents: +BattleScript_ElectricTerrainPrevents:: pause B_WAIT_TIME_SHORT printstring STRINGID_ELECTRICTERRAINPREVENTS waitmessage B_WAIT_TIME_LONG orhalfword gMoveResultFlags, MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_MistyTerrainPrevents: +BattleScript_MistyTerrainPrevents:: pause B_WAIT_TIME_SHORT printstring STRINGID_MISTYTERRAINPREVENTS waitmessage B_WAIT_TIME_LONG @@ -2698,7 +2698,6 @@ BattleScript_EffectRest:: jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_RestIsAlreadyAsleep jumpifcantmakeasleep BattleScript_RestCantSleep trysetrest BattleScript_AlreadyAtFullHp - jumpifterrainaffected BS_ATTACKER, (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN), BattleScript_ButItFailed pause B_WAIT_TIME_SHORT printfromtable gRestUsedStringIds waitmessage B_WAIT_TIME_LONG @@ -4593,8 +4592,6 @@ BattleScript_EffectYawn:: jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_PrintBankAbilityMadeIneffective jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_PrintBankAbilityMadeIneffective jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_PrintBankAbilityMadeIneffective - jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents - jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents jumpifflowerveil BattleScript_FlowerVeilProtects jumpifleafguard BattleScript_LeafGuardProtects jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 175496ca0..30066438b 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -374,5 +374,7 @@ extern const u8 BattleScript_BattlerGotOverItsInfatuation[]; extern const u8 BattleScript_Pickpocket[]; extern const u8 BattleScript_StickyBarbTransfer[]; extern const u8 BattleScript_TerrainPreventsEnd2[]; +extern const u8 BattleScript_MistyTerrainPrevents[]; +extern const u8 BattleScript_ElectricTerrainPrevents[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d57d2daae..b8a37704c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8800,6 +8800,14 @@ static void Cmd_trysetrest(void) { gBattlescriptCurrInstr = failJump; } + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; + } + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + { + gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; + } else { if (gBattleMons[gBattlerTarget].status1 & ((u8)(~STATUS1_SLEEP))) @@ -11438,6 +11446,18 @@ static void Cmd_setyawn(void) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + // When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: + // "But it failed" will display first. + gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; + } + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + { + // When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: + // "But it failed" will display first. + gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; + } else { gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); From f61d516aad400c7ce7bcae7f85db54cad74ecf0e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 15 Sep 2021 17:15:50 -0400 Subject: [PATCH 47/49] some syntax/format fixes --- include/battle_util.h | 2 -- include/constants/battle_string_ids.h | 5 +++++ src/battle_message.c | 4 +++- src/battle_util.c | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index a7263e4be..202cdbddb 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -145,7 +145,6 @@ bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item); void TrySaveExchangedItem(u8 battlerId, u16 stolenItem); bool32 IsPartnerMonFromSameTrainer(u8 battlerId); - // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability); @@ -163,5 +162,4 @@ bool32 CanBeFrozen(u8 battlerId); bool32 CanBeConfused(u8 battlerId); bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); - #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 0558e4feb..e0b466b17 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -810,4 +810,9 @@ #define B_MSG_SWITCHIN_ASONE 13 #define B_MSG_SWITCHIN_CURIOUS_MEDICINE 14 +// gTerrainPreventsStringIds +#define B_MSG_TERRAINPREVENTS_MISTY 0 +#define B_MSG_TERRAINPREVENTS_ELECTRIC 1 +#define B_MSG_TERRAINPREVENTS_PSYCHIC 2 + #endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H diff --git a/src/battle_message.c b/src/battle_message.c index 19468f168..1e9fd918b 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1271,7 +1271,9 @@ const u16 gTerrainStringIds[] = const u16 gTerrainPreventsStringIds[] = { - STRINGID_MISTYTERRAINPREVENTS, STRINGID_ELECTRICTERRAINPREVENTS, STRINGID_PSYCHICTERRAINPREVENTS + [B_MSG_TERRAINPREVENTS_MISTY] = STRINGID_MISTYTERRAINPREVENTS, + [B_MSG_TERRAINPREVENTS_ELECTRIC] = STRINGID_ELECTRICTERRAINPREVENTS, + [B_MSG_TERRAINPREVENTS_PSYCHIC] = STRINGID_PSYCHICTERRAINPREVENTS }; const u16 gMagicCoatBounceStringIds[] = diff --git a/src/battle_util.c b/src/battle_util.c index 8b2a186f1..9c1061b33 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2730,12 +2730,12 @@ u8 DoBattlerEndTurnEffects(void) gEffectBattler = gActiveBattler; if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_ELECTRIC_TERRAIN)) { - gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_ELECTRIC; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); } else if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_MISTY_TERRAIN)) { - gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); } else From 806be64935fec921f95eede6c85ddb5ea7ccb863 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 17:10:41 -0400 Subject: [PATCH 48/49] format fixes --- src/battle_script_commands.c | 4 +--- src/battle_util.c | 27 ++++++++------------------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5b090b5e4..0405d5055 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4913,7 +4913,7 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK: // King's rock and shell bell + case MOVEEND_KINGSROCK: // King's rock // These effects will occur at each hit in a multi-strike move if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) effect = TRUE; @@ -9499,7 +9499,6 @@ static void Cmd_forcerandomswitch(void) } } } - // Swapping pokemon happens in: // trainer battles @@ -9516,7 +9515,6 @@ static void Cmd_forcerandomswitch(void) || redCardForcedSwitch ) { - if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) party = gPlayerParty; else diff --git a/src/battle_util.c b/src/battle_util.c index 7edc4eadc..bdb1b4912 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4646,7 +4646,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move { if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE && CanBattlerSwitch(gBattlerAttacker)) gProtectStructs[battler].disableEjectPack = 1; // Set flag for target - + BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_WeakArmorActivates; effect++; @@ -5491,7 +5491,6 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) PREPARE_STAT_BUFFER(gBattleTextBuff1, i + 1); stringId = (GetBattlerAbility(battlerId) == ABILITY_CONTRARY) ? STRINGID_STATFELL : STRINGID_STATROSE; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; gBattleTextBuff2[1] = B_BUFF_STRING; gBattleTextBuff2[2] = STRINGID_STATSHARPLY; @@ -5500,9 +5499,7 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) gBattleTextBuff2[5] = stringId; gBattleTextBuff2[6] = stringId >> 8; gBattleTextBuff2[7] = EOS; - gEffectBattler = battlerId; - if (GetBattlerAbility(battlerId) == ABILITY_RIPEN) SET_STATCHANGER(i + 1, 4, FALSE); else @@ -5510,7 +5507,6 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) gBattleScripting.animArg1 = 0x21 + i + 6; gBattleScripting.animArg2 = 0; - if (end2) { BattleScriptExecute(BattleScript_BerryStatRaiseEnd2); @@ -5520,6 +5516,7 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2) BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet; } + return ITEM_STATS_CHANGE; } return 0; @@ -8992,33 +8989,25 @@ bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind) void BufferStatChange(u8 battlerId, u8 statId, u8 stringId) { bool8 hasContrary = (GetBattlerAbility(battlerId) == ABILITY_CONTRARY); - + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); if (stringId == STRINGID_STATFELL) { if (hasContrary) - { - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); - } + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE) else - { - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); - } + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL) } else if (stringId == STRINGID_STATROSE) { if (hasContrary) - { - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL); - } + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL) else - { - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE); - } + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE) } else { - PREPARE_STRING_BUFFER(gBattleTextBuff2, stringId); + PREPARE_STRING_BUFFER(gBattleTextBuff2, stringId) } } From 40fcd257a074e05ed2ba517f1e255012f1f0912c Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 19:36:06 -0400 Subject: [PATCH 49/49] fixes --- src/battle_script_commands.c | 2 +- src/battle_util.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0405d5055..98056aff2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10791,7 +10791,7 @@ static void Cmd_handlerollout(void) static void Cmd_jumpifconfusedandstatmaxed(void) { if (gBattleMons[gBattlerTarget].status2 & STATUS2_CONFUSION - && CompareStat(gBattlerTarget, gBattlescriptCurrInstr[1], MAX_STAT_STAGE, CMP_LESS_THAN)) + && !CompareStat(gBattlerTarget, gBattlescriptCurrInstr[1], MAX_STAT_STAGE, CMP_LESS_THAN)) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); // Fails if we're confused AND stat cannot be raised else gBattlescriptCurrInstr += 6; diff --git a/src/battle_util.c b/src/battle_util.c index bdb1b4912..ac9e9dc99 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6350,7 +6350,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; case ITEMEFFECT_KINGSROCK: - // occur on each hit of a multi-strike move + // Occur on each hit of a multi-strike move switch (atkHoldEffect) { case HOLD_EFFECT_FLINCH: @@ -6383,7 +6383,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; case ITEMEFFECT_LIFEORB_SHELLBELL: - // occur after the final hit of a multi-strike move + // Occur after the final hit of a multi-strike move switch (atkHoldEffect) { case HOLD_EFFECT_SHELL_BELL: @@ -6401,7 +6401,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) gSpecialStatuses[gBattlerTarget].dmg = 0; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret; - effect = TRUE; + effect = ITEM_HP_CHANGE; } break; case HOLD_EFFECT_LIFE_ORB: @@ -6413,7 +6413,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 10; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; - effect = TRUE; + effect = ITEM_HP_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ItemHurtRet; gLastUsedItem = gBattleMons[gBattlerAttacker].item; @@ -6424,7 +6424,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) && gBattleMons[gBattlerAttacker].hp != 0 && gBattleMoves[gCurrentMove].flags & FLAG_SOUND && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) - && !NoAliveMonsForEitherParty()) // don't activate if battle will end + && !NoAliveMonsForEitherParty()) // Don't activate if battle will end { gLastUsedItem = atkItem; gBattleScripting.battler = gBattlerAttacker;